##// END OF EJS Templates
ColorANSI.py -> utils/coloransi.py and all imports updated.
Brian Granger -
Show More
@@ -1,230 +1,229 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 pprint,pformat
24 from pprint import pformat
25
25
26 # Our own
26 # Our own
27 from IPython import Release
27 from IPython import Release
28 from IPython import ultraTB
28 from IPython import ultraTB
29 from IPython.ColorANSI import ColorScheme,ColorSchemeTable # too long names
29 from IPython.Itpl import itpl
30 from IPython.Itpl import Itpl,itpl,printpl
31
30
32 from IPython.genutils import *
31 from IPython.genutils import *
33
32
34 #****************************************************************************
33 #****************************************************************************
35 class CrashHandler:
34 class CrashHandler:
36 """Customizable crash handlers for IPython-based systems.
35 """Customizable crash handlers for IPython-based systems.
37
36
38 Instances of this class provide a __call__ method which can be used as a
37 Instances of this class provide a __call__ method which can be used as a
39 sys.excepthook, i.e., the __call__ signature is:
38 sys.excepthook, i.e., the __call__ signature is:
40
39
41 def __call__(self,etype, evalue, etb)
40 def __call__(self,etype, evalue, etb)
42
41
43 """
42 """
44
43
45 def __init__(self,IP,app_name,contact_name,contact_email,
44 def __init__(self,IP,app_name,contact_name,contact_email,
46 bug_tracker,crash_report_fname,
45 bug_tracker,crash_report_fname,
47 show_crash_traceback=True):
46 show_crash_traceback=True):
48 """New crash handler.
47 """New crash handler.
49
48
50 Inputs:
49 Inputs:
51
50
52 - IP: a running IPython instance, which will be queried at crash time
51 - IP: a running IPython instance, which will be queried at crash time
53 for internal information.
52 for internal information.
54
53
55 - app_name: a string containing the name of your application.
54 - app_name: a string containing the name of your application.
56
55
57 - contact_name: a string with the name of the person to contact.
56 - contact_name: a string with the name of the person to contact.
58
57
59 - contact_email: a string with the email address of the contact.
58 - contact_email: a string with the email address of the contact.
60
59
61 - bug_tracker: a string with the URL for your project's bug tracker.
60 - bug_tracker: a string with the URL for your project's bug tracker.
62
61
63 - crash_report_fname: a string with the filename for the crash report
62 - crash_report_fname: a string with the filename for the crash report
64 to be saved in. These reports are left in the ipython user directory
63 to be saved in. These reports are left in the ipython user directory
65 as determined by the running IPython instance.
64 as determined by the running IPython instance.
66
65
67 Optional inputs:
66 Optional inputs:
68
67
69 - show_crash_traceback(True): if false, don't print the crash
68 - show_crash_traceback(True): if false, don't print the crash
70 traceback on stderr, only generate the on-disk report
69 traceback on stderr, only generate the on-disk report
71
70
72
71
73 Non-argument instance attributes:
72 Non-argument instance attributes:
74
73
75 These instances contain some non-argument attributes which allow for
74 These instances contain some non-argument attributes which allow for
76 further customization of the crash handler's behavior. Please see the
75 further customization of the crash handler's behavior. Please see the
77 source for further details.
76 source for further details.
78 """
77 """
79
78
80 # apply args into instance
79 # apply args into instance
81 self.IP = IP # IPython instance
80 self.IP = IP # IPython instance
82 self.app_name = app_name
81 self.app_name = app_name
83 self.contact_name = contact_name
82 self.contact_name = contact_name
84 self.contact_email = contact_email
83 self.contact_email = contact_email
85 self.bug_tracker = bug_tracker
84 self.bug_tracker = bug_tracker
86 self.crash_report_fname = crash_report_fname
85 self.crash_report_fname = crash_report_fname
87 self.show_crash_traceback = show_crash_traceback
86 self.show_crash_traceback = show_crash_traceback
88
87
89 # Hardcoded defaults, which can be overridden either by subclasses or
88 # Hardcoded defaults, which can be overridden either by subclasses or
90 # at runtime for the instance.
89 # at runtime for the instance.
91
90
92 # Template for the user message. Subclasses which completely override
91 # Template for the user message. Subclasses which completely override
93 # this, or user apps, can modify it to suit their tastes. It gets
92 # 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.
93 # expanded using itpl, so calls of the kind $self.foo are valid.
95 self.user_message_template = """
94 self.user_message_template = """
96 Oops, $self.app_name crashed. We do our best to make it stable, but...
95 Oops, $self.app_name crashed. We do our best to make it stable, but...
97
96
98 A crash report was automatically generated with the following information:
97 A crash report was automatically generated with the following information:
99 - A verbatim copy of the crash traceback.
98 - A verbatim copy of the crash traceback.
100 - A copy of your input history during this session.
99 - A copy of your input history during this session.
101 - Data on your current $self.app_name configuration.
100 - Data on your current $self.app_name configuration.
102
101
103 It was left in the file named:
102 It was left in the file named:
104 \t'$self.crash_report_fname'
103 \t'$self.crash_report_fname'
105 If you can email this file to the developers, the information in it will help
104 If you can email this file to the developers, the information in it will help
106 them in understanding and correcting the problem.
105 them in understanding and correcting the problem.
107
106
108 You can mail it to: $self.contact_name at $self.contact_email
107 You can mail it to: $self.contact_name at $self.contact_email
109 with the subject '$self.app_name Crash Report'.
108 with the subject '$self.app_name Crash Report'.
110
109
111 If you want to do it now, the following command will work (under Unix):
110 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
111 mail -s '$self.app_name Crash Report' $self.contact_email < $self.crash_report_fname
113
112
114 To ensure accurate tracking of this issue, please file a report about it at:
113 To ensure accurate tracking of this issue, please file a report about it at:
115 $self.bug_tracker
114 $self.bug_tracker
116 """
115 """
117
116
118 def __call__(self,etype, evalue, etb):
117 def __call__(self,etype, evalue, etb):
119 """Handle an exception, call for compatible with sys.excepthook"""
118 """Handle an exception, call for compatible with sys.excepthook"""
120
119
121 # Report tracebacks shouldn't use color in general (safer for users)
120 # Report tracebacks shouldn't use color in general (safer for users)
122 color_scheme = 'NoColor'
121 color_scheme = 'NoColor'
123
122
124 # Use this ONLY for developer debugging (keep commented out for release)
123 # Use this ONLY for developer debugging (keep commented out for release)
125 #color_scheme = 'Linux' # dbg
124 #color_scheme = 'Linux' # dbg
126
125
127 try:
126 try:
128 rptdir = self.IP.rc.ipythondir
127 rptdir = self.IP.rc.ipythondir
129 except:
128 except:
130 rptdir = os.getcwd()
129 rptdir = os.getcwd()
131 if not os.path.isdir(rptdir):
130 if not os.path.isdir(rptdir):
132 rptdir = os.getcwd()
131 rptdir = os.getcwd()
133 report_name = os.path.join(rptdir,self.crash_report_fname)
132 report_name = os.path.join(rptdir,self.crash_report_fname)
134 # write the report filename into the instance dict so it can get
133 # write the report filename into the instance dict so it can get
135 # properly expanded out in the user message template
134 # properly expanded out in the user message template
136 self.crash_report_fname = report_name
135 self.crash_report_fname = report_name
137 TBhandler = ultraTB.VerboseTB(color_scheme=color_scheme,
136 TBhandler = ultraTB.VerboseTB(color_scheme=color_scheme,
138 long_header=1)
137 long_header=1)
139 traceback = TBhandler.text(etype,evalue,etb,context=31)
138 traceback = TBhandler.text(etype,evalue,etb,context=31)
140
139
141 # print traceback to screen
140 # print traceback to screen
142 if self.show_crash_traceback:
141 if self.show_crash_traceback:
143 print >> sys.stderr, traceback
142 print >> sys.stderr, traceback
144
143
145 # and generate a complete report on disk
144 # and generate a complete report on disk
146 try:
145 try:
147 report = open(report_name,'w')
146 report = open(report_name,'w')
148 except:
147 except:
149 print >> sys.stderr, 'Could not create crash report on disk.'
148 print >> sys.stderr, 'Could not create crash report on disk.'
150 return
149 return
151
150
152 # Inform user on stderr of what happened
151 # Inform user on stderr of what happened
153 msg = itpl('\n'+'*'*70+'\n'+self.user_message_template)
152 msg = itpl('\n'+'*'*70+'\n'+self.user_message_template)
154 print >> sys.stderr, msg
153 print >> sys.stderr, msg
155
154
156 # Construct report on disk
155 # Construct report on disk
157 report.write(self.make_report(traceback))
156 report.write(self.make_report(traceback))
158 report.close()
157 report.close()
159 raw_input("Press enter to exit:")
158 raw_input("Press enter to exit:")
160
159
161 def make_report(self,traceback):
160 def make_report(self,traceback):
162 """Return a string containing a crash report."""
161 """Return a string containing a crash report."""
163
162
164 sec_sep = '\n\n'+'*'*75+'\n\n'
163 sec_sep = '\n\n'+'*'*75+'\n\n'
165
164
166 report = []
165 report = []
167 rpt_add = report.append
166 rpt_add = report.append
168
167
169 rpt_add('*'*75+'\n\n'+'IPython post-mortem report\n\n')
168 rpt_add('*'*75+'\n\n'+'IPython post-mortem report\n\n')
170 rpt_add('IPython version: %s \n\n' % Release.version)
169 rpt_add('IPython version: %s \n\n' % Release.version)
171 rpt_add('BZR revision : %s \n\n' % Release.revision)
170 rpt_add('BZR revision : %s \n\n' % Release.revision)
172 rpt_add('Platform info : os.name -> %s, sys.platform -> %s' %
171 rpt_add('Platform info : os.name -> %s, sys.platform -> %s' %
173 (os.name,sys.platform) )
172 (os.name,sys.platform) )
174 rpt_add(sec_sep+'Current user configuration structure:\n\n')
173 rpt_add(sec_sep+'Current user configuration structure:\n\n')
175 rpt_add(pformat(self.IP.rc.dict()))
174 rpt_add(pformat(self.IP.rc.dict()))
176 rpt_add(sec_sep+'Crash traceback:\n\n' + traceback)
175 rpt_add(sec_sep+'Crash traceback:\n\n' + traceback)
177 try:
176 try:
178 rpt_add(sec_sep+"History of session input:")
177 rpt_add(sec_sep+"History of session input:")
179 for line in self.IP.user_ns['_ih']:
178 for line in self.IP.user_ns['_ih']:
180 rpt_add(line)
179 rpt_add(line)
181 rpt_add('\n*** Last line of input (may not be in above history):\n')
180 rpt_add('\n*** Last line of input (may not be in above history):\n')
182 rpt_add(self.IP._last_input_line+'\n')
181 rpt_add(self.IP._last_input_line+'\n')
183 except:
182 except:
184 pass
183 pass
185
184
186 return ''.join(report)
185 return ''.join(report)
187
186
188 class IPythonCrashHandler(CrashHandler):
187 class IPythonCrashHandler(CrashHandler):
189 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
188 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
190
189
191 def __init__(self,IP):
190 def __init__(self,IP):
192
191
193 # Set here which of the IPython authors should be listed as contact
192 # Set here which of the IPython authors should be listed as contact
194 AUTHOR_CONTACT = 'Ville'
193 AUTHOR_CONTACT = 'Ville'
195
194
196 # Set argument defaults
195 # Set argument defaults
197 app_name = 'IPython'
196 app_name = 'IPython'
198 bug_tracker = 'https://bugs.launchpad.net/ipython/+filebug'
197 bug_tracker = 'https://bugs.launchpad.net/ipython/+filebug'
199 contact_name,contact_email = Release.authors[AUTHOR_CONTACT][:2]
198 contact_name,contact_email = Release.authors[AUTHOR_CONTACT][:2]
200 crash_report_fname = 'IPython_crash_report.txt'
199 crash_report_fname = 'IPython_crash_report.txt'
201 # Call parent constructor
200 # Call parent constructor
202 CrashHandler.__init__(self,IP,app_name,contact_name,contact_email,
201 CrashHandler.__init__(self,IP,app_name,contact_name,contact_email,
203 bug_tracker,crash_report_fname)
202 bug_tracker,crash_report_fname)
204
203
205 def make_report(self,traceback):
204 def make_report(self,traceback):
206 """Return a string containing a crash report."""
205 """Return a string containing a crash report."""
207
206
208 sec_sep = '\n\n'+'*'*75+'\n\n'
207 sec_sep = '\n\n'+'*'*75+'\n\n'
209
208
210 report = []
209 report = []
211 rpt_add = report.append
210 rpt_add = report.append
212
211
213 rpt_add('*'*75+'\n\n'+'IPython post-mortem report\n\n')
212 rpt_add('*'*75+'\n\n'+'IPython post-mortem report\n\n')
214 rpt_add('IPython version: %s \n\n' % Release.version)
213 rpt_add('IPython version: %s \n\n' % Release.version)
215 rpt_add('BZR revision : %s \n\n' % Release.revision)
214 rpt_add('BZR revision : %s \n\n' % Release.revision)
216 rpt_add('Platform info : os.name -> %s, sys.platform -> %s' %
215 rpt_add('Platform info : os.name -> %s, sys.platform -> %s' %
217 (os.name,sys.platform) )
216 (os.name,sys.platform) )
218 rpt_add(sec_sep+'Current user configuration structure:\n\n')
217 rpt_add(sec_sep+'Current user configuration structure:\n\n')
219 rpt_add(pformat(self.IP.rc.dict()))
218 rpt_add(pformat(self.IP.rc.dict()))
220 rpt_add(sec_sep+'Crash traceback:\n\n' + traceback)
219 rpt_add(sec_sep+'Crash traceback:\n\n' + traceback)
221 try:
220 try:
222 rpt_add(sec_sep+"History of session input:")
221 rpt_add(sec_sep+"History of session input:")
223 for line in self.IP.user_ns['_ih']:
222 for line in self.IP.user_ns['_ih']:
224 rpt_add(line)
223 rpt_add(line)
225 rpt_add('\n*** Last line of input (may not be in above history):\n')
224 rpt_add('\n*** Last line of input (may not be in above history):\n')
226 rpt_add(self.IP._last_input_line+'\n')
225 rpt_add(self.IP._last_input_line+'\n')
227 except:
226 except:
228 pass
227 pass
229
228
230 return ''.join(report)
229 return ''.join(report)
@@ -1,522 +1,523 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Pdb debugger class.
3 Pdb debugger class.
4
4
5 Modified from the standard pdb.Pdb class to avoid including readline, so that
5 Modified from the standard pdb.Pdb class to avoid including readline, so that
6 the command line completion of other programs which include this isn't
6 the command line completion of other programs which include this isn't
7 damaged.
7 damaged.
8
8
9 In the future, this class will be expanded with improvements over the standard
9 In the future, this class will be expanded with improvements over the standard
10 pdb.
10 pdb.
11
11
12 The code in this file is mainly lifted out of cmd.py in Python 2.2, with minor
12 The code in this file is mainly lifted out of cmd.py in Python 2.2, with minor
13 changes. Licensing should therefore be under the standard Python terms. For
13 changes. Licensing should therefore be under the standard Python terms. For
14 details on the PSF (Python Software Foundation) standard license, see:
14 details on the PSF (Python Software Foundation) standard license, see:
15
15
16 http://www.python.org/2.2.3/license.html"""
16 http://www.python.org/2.2.3/license.html"""
17
17
18 #*****************************************************************************
18 #*****************************************************************************
19 #
19 #
20 # This file is licensed under the PSF license.
20 # This file is licensed under the PSF license.
21 #
21 #
22 # Copyright (C) 2001 Python Software Foundation, www.python.org
22 # Copyright (C) 2001 Python Software Foundation, www.python.org
23 # Copyright (C) 2005-2006 Fernando Perez. <fperez@colorado.edu>
23 # Copyright (C) 2005-2006 Fernando Perez. <fperez@colorado.edu>
24 #
24 #
25 #
25 #
26 #*****************************************************************************
26 #*****************************************************************************
27
27
28 import bdb
28 import bdb
29 import cmd
29 import cmd
30 import linecache
30 import linecache
31 import os
31 import os
32 import sys
32 import sys
33
33
34 from IPython import PyColorize, ColorANSI, ipapi
34 from IPython import PyColorize, ipapi
35 from IPython.utils import coloransi
35 from IPython.genutils import Term
36 from IPython.genutils import Term
36 from IPython.excolors import exception_colors
37 from IPython.excolors import exception_colors
37
38
38 # See if we can use pydb.
39 # See if we can use pydb.
39 has_pydb = False
40 has_pydb = False
40 prompt = 'ipdb> '
41 prompt = 'ipdb> '
41 #We have to check this directly from sys.argv, config struct not yet available
42 #We have to check this directly from sys.argv, config struct not yet available
42 if '-pydb' in sys.argv:
43 if '-pydb' in sys.argv:
43 try:
44 try:
44 import pydb
45 import pydb
45 if hasattr(pydb.pydb, "runl") and pydb.version>'1.17':
46 if hasattr(pydb.pydb, "runl") and pydb.version>'1.17':
46 # Version 1.17 is broken, and that's what ships with Ubuntu Edgy, so we
47 # Version 1.17 is broken, and that's what ships with Ubuntu Edgy, so we
47 # better protect against it.
48 # better protect against it.
48 has_pydb = True
49 has_pydb = True
49 except ImportError:
50 except ImportError:
50 print "Pydb (http://bashdb.sourceforge.net/pydb/) does not seem to be available"
51 print "Pydb (http://bashdb.sourceforge.net/pydb/) does not seem to be available"
51
52
52 if has_pydb:
53 if has_pydb:
53 from pydb import Pdb as OldPdb
54 from pydb import Pdb as OldPdb
54 #print "Using pydb for %run -d and post-mortem" #dbg
55 #print "Using pydb for %run -d and post-mortem" #dbg
55 prompt = 'ipydb> '
56 prompt = 'ipydb> '
56 else:
57 else:
57 from pdb import Pdb as OldPdb
58 from pdb import Pdb as OldPdb
58
59
59 # Allow the set_trace code to operate outside of an ipython instance, even if
60 # Allow the set_trace code to operate outside of an ipython instance, even if
60 # it does so with some limitations. The rest of this support is implemented in
61 # it does so with some limitations. The rest of this support is implemented in
61 # the Tracer constructor.
62 # the Tracer constructor.
62 def BdbQuit_excepthook(et,ev,tb):
63 def BdbQuit_excepthook(et,ev,tb):
63 if et==bdb.BdbQuit:
64 if et==bdb.BdbQuit:
64 print 'Exiting Debugger.'
65 print 'Exiting Debugger.'
65 else:
66 else:
66 BdbQuit_excepthook.excepthook_ori(et,ev,tb)
67 BdbQuit_excepthook.excepthook_ori(et,ev,tb)
67
68
68 def BdbQuit_IPython_excepthook(self,et,ev,tb):
69 def BdbQuit_IPython_excepthook(self,et,ev,tb):
69 print 'Exiting Debugger.'
70 print 'Exiting Debugger.'
70
71
71 class Tracer(object):
72 class Tracer(object):
72 """Class for local debugging, similar to pdb.set_trace.
73 """Class for local debugging, similar to pdb.set_trace.
73
74
74 Instances of this class, when called, behave like pdb.set_trace, but
75 Instances of this class, when called, behave like pdb.set_trace, but
75 providing IPython's enhanced capabilities.
76 providing IPython's enhanced capabilities.
76
77
77 This is implemented as a class which must be initialized in your own code
78 This is implemented as a class which must be initialized in your own code
78 and not as a standalone function because we need to detect at runtime
79 and not as a standalone function because we need to detect at runtime
79 whether IPython is already active or not. That detection is done in the
80 whether IPython is already active or not. That detection is done in the
80 constructor, ensuring that this code plays nicely with a running IPython,
81 constructor, ensuring that this code plays nicely with a running IPython,
81 while functioning acceptably (though with limitations) if outside of it.
82 while functioning acceptably (though with limitations) if outside of it.
82 """
83 """
83
84
84 def __init__(self,colors=None):
85 def __init__(self,colors=None):
85 """Create a local debugger instance.
86 """Create a local debugger instance.
86
87
87 :Parameters:
88 :Parameters:
88
89
89 - `colors` (None): a string containing the name of the color scheme to
90 - `colors` (None): a string containing the name of the color scheme to
90 use, it must be one of IPython's valid color schemes. If not given, the
91 use, it must be one of IPython's valid color schemes. If not given, the
91 function will default to the current IPython scheme when running inside
92 function will default to the current IPython scheme when running inside
92 IPython, and to 'NoColor' otherwise.
93 IPython, and to 'NoColor' otherwise.
93
94
94 Usage example:
95 Usage example:
95
96
96 from IPython.Debugger import Tracer; debug_here = Tracer()
97 from IPython.Debugger import Tracer; debug_here = Tracer()
97
98
98 ... later in your code
99 ... later in your code
99 debug_here() # -> will open up the debugger at that point.
100 debug_here() # -> will open up the debugger at that point.
100
101
101 Once the debugger activates, you can use all of its regular commands to
102 Once the debugger activates, you can use all of its regular commands to
102 step through code, set breakpoints, etc. See the pdb documentation
103 step through code, set breakpoints, etc. See the pdb documentation
103 from the Python standard library for usage details.
104 from the Python standard library for usage details.
104 """
105 """
105
106
106 global __IPYTHON__
107 global __IPYTHON__
107 try:
108 try:
108 __IPYTHON__
109 __IPYTHON__
109 except NameError:
110 except NameError:
110 # Outside of ipython, we set our own exception hook manually
111 # Outside of ipython, we set our own exception hook manually
111 __IPYTHON__ = ipapi.get(True,False)
112 __IPYTHON__ = ipapi.get(True,False)
112 BdbQuit_excepthook.excepthook_ori = sys.excepthook
113 BdbQuit_excepthook.excepthook_ori = sys.excepthook
113 sys.excepthook = BdbQuit_excepthook
114 sys.excepthook = BdbQuit_excepthook
114 def_colors = 'NoColor'
115 def_colors = 'NoColor'
115 try:
116 try:
116 # Limited tab completion support
117 # Limited tab completion support
117 import rlcompleter,readline
118 import readline
118 readline.parse_and_bind('tab: complete')
119 readline.parse_and_bind('tab: complete')
119 except ImportError:
120 except ImportError:
120 pass
121 pass
121 else:
122 else:
122 # In ipython, we use its custom exception handler mechanism
123 # In ipython, we use its custom exception handler mechanism
123 ip = ipapi.get()
124 ip = ipapi.get()
124 def_colors = ip.options.colors
125 def_colors = ip.options.colors
125 ip.set_custom_exc((bdb.BdbQuit,),BdbQuit_IPython_excepthook)
126 ip.set_custom_exc((bdb.BdbQuit,),BdbQuit_IPython_excepthook)
126
127
127 if colors is None:
128 if colors is None:
128 colors = def_colors
129 colors = def_colors
129 self.debugger = Pdb(colors)
130 self.debugger = Pdb(colors)
130
131
131 def __call__(self):
132 def __call__(self):
132 """Starts an interactive debugger at the point where called.
133 """Starts an interactive debugger at the point where called.
133
134
134 This is similar to the pdb.set_trace() function from the std lib, but
135 This is similar to the pdb.set_trace() function from the std lib, but
135 using IPython's enhanced debugger."""
136 using IPython's enhanced debugger."""
136
137
137 self.debugger.set_trace(sys._getframe().f_back)
138 self.debugger.set_trace(sys._getframe().f_back)
138
139
139 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
140 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
140 """Make new_fn have old_fn's doc string. This is particularly useful
141 """Make new_fn have old_fn's doc string. This is particularly useful
141 for the do_... commands that hook into the help system.
142 for the do_... commands that hook into the help system.
142 Adapted from from a comp.lang.python posting
143 Adapted from from a comp.lang.python posting
143 by Duncan Booth."""
144 by Duncan Booth."""
144 def wrapper(*args, **kw):
145 def wrapper(*args, **kw):
145 return new_fn(*args, **kw)
146 return new_fn(*args, **kw)
146 if old_fn.__doc__:
147 if old_fn.__doc__:
147 wrapper.__doc__ = old_fn.__doc__ + additional_text
148 wrapper.__doc__ = old_fn.__doc__ + additional_text
148 return wrapper
149 return wrapper
149
150
150 def _file_lines(fname):
151 def _file_lines(fname):
151 """Return the contents of a named file as a list of lines.
152 """Return the contents of a named file as a list of lines.
152
153
153 This function never raises an IOError exception: if the file can't be
154 This function never raises an IOError exception: if the file can't be
154 read, it simply returns an empty list."""
155 read, it simply returns an empty list."""
155
156
156 try:
157 try:
157 outfile = open(fname)
158 outfile = open(fname)
158 except IOError:
159 except IOError:
159 return []
160 return []
160 else:
161 else:
161 out = outfile.readlines()
162 out = outfile.readlines()
162 outfile.close()
163 outfile.close()
163 return out
164 return out
164
165
165 class Pdb(OldPdb):
166 class Pdb(OldPdb):
166 """Modified Pdb class, does not load readline."""
167 """Modified Pdb class, does not load readline."""
167
168
168 if sys.version[:3] >= '2.5' or has_pydb:
169 if sys.version[:3] >= '2.5' or has_pydb:
169 def __init__(self,color_scheme='NoColor',completekey=None,
170 def __init__(self,color_scheme='NoColor',completekey=None,
170 stdin=None, stdout=None):
171 stdin=None, stdout=None):
171
172
172 # Parent constructor:
173 # Parent constructor:
173 if has_pydb and completekey is None:
174 if has_pydb and completekey is None:
174 OldPdb.__init__(self,stdin=stdin,stdout=Term.cout)
175 OldPdb.__init__(self,stdin=stdin,stdout=Term.cout)
175 else:
176 else:
176 OldPdb.__init__(self,completekey,stdin,stdout)
177 OldPdb.__init__(self,completekey,stdin,stdout)
177
178
178 self.prompt = prompt # The default prompt is '(Pdb)'
179 self.prompt = prompt # The default prompt is '(Pdb)'
179
180
180 # IPython changes...
181 # IPython changes...
181 self.is_pydb = has_pydb
182 self.is_pydb = has_pydb
182
183
183 if self.is_pydb:
184 if self.is_pydb:
184
185
185 # iplib.py's ipalias seems to want pdb's checkline
186 # iplib.py's ipalias seems to want pdb's checkline
186 # which located in pydb.fn
187 # which located in pydb.fn
187 import pydb.fns
188 import pydb.fns
188 self.checkline = lambda filename, lineno: \
189 self.checkline = lambda filename, lineno: \
189 pydb.fns.checkline(self, filename, lineno)
190 pydb.fns.checkline(self, filename, lineno)
190
191
191 self.curframe = None
192 self.curframe = None
192 self.do_restart = self.new_do_restart
193 self.do_restart = self.new_do_restart
193
194
194 self.old_all_completions = __IPYTHON__.Completer.all_completions
195 self.old_all_completions = __IPYTHON__.Completer.all_completions
195 __IPYTHON__.Completer.all_completions=self.all_completions
196 __IPYTHON__.Completer.all_completions=self.all_completions
196
197
197 self.do_list = decorate_fn_with_doc(self.list_command_pydb,
198 self.do_list = decorate_fn_with_doc(self.list_command_pydb,
198 OldPdb.do_list)
199 OldPdb.do_list)
199 self.do_l = self.do_list
200 self.do_l = self.do_list
200 self.do_frame = decorate_fn_with_doc(self.new_do_frame,
201 self.do_frame = decorate_fn_with_doc(self.new_do_frame,
201 OldPdb.do_frame)
202 OldPdb.do_frame)
202
203
203 self.aliases = {}
204 self.aliases = {}
204
205
205 # Create color table: we copy the default one from the traceback
206 # Create color table: we copy the default one from the traceback
206 # module and add a few attributes needed for debugging
207 # module and add a few attributes needed for debugging
207 self.color_scheme_table = exception_colors()
208 self.color_scheme_table = exception_colors()
208
209
209 # shorthands
210 # shorthands
210 C = ColorANSI.TermColors
211 C = coloransi.TermColors
211 cst = self.color_scheme_table
212 cst = self.color_scheme_table
212
213
213 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
214 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
214 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
215 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
215
216
216 cst['Linux'].colors.breakpoint_enabled = C.LightRed
217 cst['Linux'].colors.breakpoint_enabled = C.LightRed
217 cst['Linux'].colors.breakpoint_disabled = C.Red
218 cst['Linux'].colors.breakpoint_disabled = C.Red
218
219
219 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
220 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
220 cst['LightBG'].colors.breakpoint_disabled = C.Red
221 cst['LightBG'].colors.breakpoint_disabled = C.Red
221
222
222 self.set_colors(color_scheme)
223 self.set_colors(color_scheme)
223
224
224 # Add a python parser so we can syntax highlight source while
225 # Add a python parser so we can syntax highlight source while
225 # debugging.
226 # debugging.
226 self.parser = PyColorize.Parser()
227 self.parser = PyColorize.Parser()
227
228
228
229
229 else:
230 else:
230 # Ugly hack: for Python 2.3-2.4, we can't call the parent constructor,
231 # Ugly hack: for Python 2.3-2.4, we can't call the parent constructor,
231 # because it binds readline and breaks tab-completion. This means we
232 # because it binds readline and breaks tab-completion. This means we
232 # have to COPY the constructor here.
233 # have to COPY the constructor here.
233 def __init__(self,color_scheme='NoColor'):
234 def __init__(self,color_scheme='NoColor'):
234 bdb.Bdb.__init__(self)
235 bdb.Bdb.__init__(self)
235 cmd.Cmd.__init__(self,completekey=None) # don't load readline
236 cmd.Cmd.__init__(self,completekey=None) # don't load readline
236 self.prompt = 'ipdb> ' # The default prompt is '(Pdb)'
237 self.prompt = 'ipdb> ' # The default prompt is '(Pdb)'
237 self.aliases = {}
238 self.aliases = {}
238
239
239 # These two lines are part of the py2.4 constructor, let's put them
240 # These two lines are part of the py2.4 constructor, let's put them
240 # unconditionally here as they won't cause any problems in 2.3.
241 # unconditionally here as they won't cause any problems in 2.3.
241 self.mainpyfile = ''
242 self.mainpyfile = ''
242 self._wait_for_mainpyfile = 0
243 self._wait_for_mainpyfile = 0
243
244
244 # Read $HOME/.pdbrc and ./.pdbrc
245 # Read $HOME/.pdbrc and ./.pdbrc
245 try:
246 try:
246 self.rcLines = _file_lines(os.path.join(os.environ['HOME'],
247 self.rcLines = _file_lines(os.path.join(os.environ['HOME'],
247 ".pdbrc"))
248 ".pdbrc"))
248 except KeyError:
249 except KeyError:
249 self.rcLines = []
250 self.rcLines = []
250 self.rcLines.extend(_file_lines(".pdbrc"))
251 self.rcLines.extend(_file_lines(".pdbrc"))
251
252
252 # Create color table: we copy the default one from the traceback
253 # Create color table: we copy the default one from the traceback
253 # module and add a few attributes needed for debugging
254 # module and add a few attributes needed for debugging
254 self.color_scheme_table = exception_colors()
255 self.color_scheme_table = exception_colors()
255
256
256 # shorthands
257 # shorthands
257 C = ColorANSI.TermColors
258 C = coloransi.TermColors
258 cst = self.color_scheme_table
259 cst = self.color_scheme_table
259
260
260 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
261 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
261 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
262 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
262
263
263 cst['Linux'].colors.breakpoint_enabled = C.LightRed
264 cst['Linux'].colors.breakpoint_enabled = C.LightRed
264 cst['Linux'].colors.breakpoint_disabled = C.Red
265 cst['Linux'].colors.breakpoint_disabled = C.Red
265
266
266 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
267 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
267 cst['LightBG'].colors.breakpoint_disabled = C.Red
268 cst['LightBG'].colors.breakpoint_disabled = C.Red
268
269
269 self.set_colors(color_scheme)
270 self.set_colors(color_scheme)
270
271
271 # Add a python parser so we can syntax highlight source while
272 # Add a python parser so we can syntax highlight source while
272 # debugging.
273 # debugging.
273 self.parser = PyColorize.Parser()
274 self.parser = PyColorize.Parser()
274
275
275 def set_colors(self, scheme):
276 def set_colors(self, scheme):
276 """Shorthand access to the color table scheme selector method."""
277 """Shorthand access to the color table scheme selector method."""
277 self.color_scheme_table.set_active_scheme(scheme)
278 self.color_scheme_table.set_active_scheme(scheme)
278
279
279 def interaction(self, frame, traceback):
280 def interaction(self, frame, traceback):
280 __IPYTHON__.set_completer_frame(frame)
281 __IPYTHON__.set_completer_frame(frame)
281 OldPdb.interaction(self, frame, traceback)
282 OldPdb.interaction(self, frame, traceback)
282
283
283 def new_do_up(self, arg):
284 def new_do_up(self, arg):
284 OldPdb.do_up(self, arg)
285 OldPdb.do_up(self, arg)
285 __IPYTHON__.set_completer_frame(self.curframe)
286 __IPYTHON__.set_completer_frame(self.curframe)
286 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
287 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
287
288
288 def new_do_down(self, arg):
289 def new_do_down(self, arg):
289 OldPdb.do_down(self, arg)
290 OldPdb.do_down(self, arg)
290 __IPYTHON__.set_completer_frame(self.curframe)
291 __IPYTHON__.set_completer_frame(self.curframe)
291
292
292 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
293 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
293
294
294 def new_do_frame(self, arg):
295 def new_do_frame(self, arg):
295 OldPdb.do_frame(self, arg)
296 OldPdb.do_frame(self, arg)
296 __IPYTHON__.set_completer_frame(self.curframe)
297 __IPYTHON__.set_completer_frame(self.curframe)
297
298
298 def new_do_quit(self, arg):
299 def new_do_quit(self, arg):
299
300
300 if hasattr(self, 'old_all_completions'):
301 if hasattr(self, 'old_all_completions'):
301 __IPYTHON__.Completer.all_completions=self.old_all_completions
302 __IPYTHON__.Completer.all_completions=self.old_all_completions
302
303
303
304
304 return OldPdb.do_quit(self, arg)
305 return OldPdb.do_quit(self, arg)
305
306
306 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
307 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
307
308
308 def new_do_restart(self, arg):
309 def new_do_restart(self, arg):
309 """Restart command. In the context of ipython this is exactly the same
310 """Restart command. In the context of ipython this is exactly the same
310 thing as 'quit'."""
311 thing as 'quit'."""
311 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
312 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
312 return self.do_quit(arg)
313 return self.do_quit(arg)
313
314
314 def postloop(self):
315 def postloop(self):
315 __IPYTHON__.set_completer_frame(None)
316 __IPYTHON__.set_completer_frame(None)
316
317
317 def print_stack_trace(self):
318 def print_stack_trace(self):
318 try:
319 try:
319 for frame_lineno in self.stack:
320 for frame_lineno in self.stack:
320 self.print_stack_entry(frame_lineno, context = 5)
321 self.print_stack_entry(frame_lineno, context = 5)
321 except KeyboardInterrupt:
322 except KeyboardInterrupt:
322 pass
323 pass
323
324
324 def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ',
325 def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ',
325 context = 3):
326 context = 3):
326 #frame, lineno = frame_lineno
327 #frame, lineno = frame_lineno
327 print >>Term.cout, self.format_stack_entry(frame_lineno, '', context)
328 print >>Term.cout, self.format_stack_entry(frame_lineno, '', context)
328
329
329 # vds: >>
330 # vds: >>
330 frame, lineno = frame_lineno
331 frame, lineno = frame_lineno
331 filename = frame.f_code.co_filename
332 filename = frame.f_code.co_filename
332 __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0)
333 __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0)
333 # vds: <<
334 # vds: <<
334
335
335 def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3):
336 def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3):
336 import linecache, repr
337 import linecache, repr
337
338
338 ret = []
339 ret = []
339
340
340 Colors = self.color_scheme_table.active_colors
341 Colors = self.color_scheme_table.active_colors
341 ColorsNormal = Colors.Normal
342 ColorsNormal = Colors.Normal
342 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
343 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
343 tpl_call = '%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
344 tpl_call = '%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
344 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
345 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
345 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
346 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
346 ColorsNormal)
347 ColorsNormal)
347
348
348 frame, lineno = frame_lineno
349 frame, lineno = frame_lineno
349
350
350 return_value = ''
351 return_value = ''
351 if '__return__' in frame.f_locals:
352 if '__return__' in frame.f_locals:
352 rv = frame.f_locals['__return__']
353 rv = frame.f_locals['__return__']
353 #return_value += '->'
354 #return_value += '->'
354 return_value += repr.repr(rv) + '\n'
355 return_value += repr.repr(rv) + '\n'
355 ret.append(return_value)
356 ret.append(return_value)
356
357
357 #s = filename + '(' + `lineno` + ')'
358 #s = filename + '(' + `lineno` + ')'
358 filename = self.canonic(frame.f_code.co_filename)
359 filename = self.canonic(frame.f_code.co_filename)
359 link = tpl_link % filename
360 link = tpl_link % filename
360
361
361 if frame.f_code.co_name:
362 if frame.f_code.co_name:
362 func = frame.f_code.co_name
363 func = frame.f_code.co_name
363 else:
364 else:
364 func = "<lambda>"
365 func = "<lambda>"
365
366
366 call = ''
367 call = ''
367 if func != '?':
368 if func != '?':
368 if '__args__' in frame.f_locals:
369 if '__args__' in frame.f_locals:
369 args = repr.repr(frame.f_locals['__args__'])
370 args = repr.repr(frame.f_locals['__args__'])
370 else:
371 else:
371 args = '()'
372 args = '()'
372 call = tpl_call % (func, args)
373 call = tpl_call % (func, args)
373
374
374 # The level info should be generated in the same format pdb uses, to
375 # The level info should be generated in the same format pdb uses, to
375 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
376 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
376 if frame is self.curframe:
377 if frame is self.curframe:
377 ret.append('> ')
378 ret.append('> ')
378 else:
379 else:
379 ret.append(' ')
380 ret.append(' ')
380 ret.append('%s(%s)%s\n' % (link,lineno,call))
381 ret.append('%s(%s)%s\n' % (link,lineno,call))
381
382
382 start = lineno - 1 - context//2
383 start = lineno - 1 - context//2
383 lines = linecache.getlines(filename)
384 lines = linecache.getlines(filename)
384 start = max(start, 0)
385 start = max(start, 0)
385 start = min(start, len(lines) - context)
386 start = min(start, len(lines) - context)
386 lines = lines[start : start + context]
387 lines = lines[start : start + context]
387
388
388 for i,line in enumerate(lines):
389 for i,line in enumerate(lines):
389 show_arrow = (start + 1 + i == lineno)
390 show_arrow = (start + 1 + i == lineno)
390 linetpl = (frame is self.curframe or show_arrow) \
391 linetpl = (frame is self.curframe or show_arrow) \
391 and tpl_line_em \
392 and tpl_line_em \
392 or tpl_line
393 or tpl_line
393 ret.append(self.__format_line(linetpl, filename,
394 ret.append(self.__format_line(linetpl, filename,
394 start + 1 + i, line,
395 start + 1 + i, line,
395 arrow = show_arrow) )
396 arrow = show_arrow) )
396
397
397 return ''.join(ret)
398 return ''.join(ret)
398
399
399 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
400 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
400 bp_mark = ""
401 bp_mark = ""
401 bp_mark_color = ""
402 bp_mark_color = ""
402
403
403 scheme = self.color_scheme_table.active_scheme_name
404 scheme = self.color_scheme_table.active_scheme_name
404 new_line, err = self.parser.format2(line, 'str', scheme)
405 new_line, err = self.parser.format2(line, 'str', scheme)
405 if not err: line = new_line
406 if not err: line = new_line
406
407
407 bp = None
408 bp = None
408 if lineno in self.get_file_breaks(filename):
409 if lineno in self.get_file_breaks(filename):
409 bps = self.get_breaks(filename, lineno)
410 bps = self.get_breaks(filename, lineno)
410 bp = bps[-1]
411 bp = bps[-1]
411
412
412 if bp:
413 if bp:
413 Colors = self.color_scheme_table.active_colors
414 Colors = self.color_scheme_table.active_colors
414 bp_mark = str(bp.number)
415 bp_mark = str(bp.number)
415 bp_mark_color = Colors.breakpoint_enabled
416 bp_mark_color = Colors.breakpoint_enabled
416 if not bp.enabled:
417 if not bp.enabled:
417 bp_mark_color = Colors.breakpoint_disabled
418 bp_mark_color = Colors.breakpoint_disabled
418
419
419 numbers_width = 7
420 numbers_width = 7
420 if arrow:
421 if arrow:
421 # This is the line with the error
422 # This is the line with the error
422 pad = numbers_width - len(str(lineno)) - len(bp_mark)
423 pad = numbers_width - len(str(lineno)) - len(bp_mark)
423 if pad >= 3:
424 if pad >= 3:
424 marker = '-'*(pad-3) + '-> '
425 marker = '-'*(pad-3) + '-> '
425 elif pad == 2:
426 elif pad == 2:
426 marker = '> '
427 marker = '> '
427 elif pad == 1:
428 elif pad == 1:
428 marker = '>'
429 marker = '>'
429 else:
430 else:
430 marker = ''
431 marker = ''
431 num = '%s%s' % (marker, str(lineno))
432 num = '%s%s' % (marker, str(lineno))
432 line = tpl_line % (bp_mark_color + bp_mark, num, line)
433 line = tpl_line % (bp_mark_color + bp_mark, num, line)
433 else:
434 else:
434 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
435 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
435 line = tpl_line % (bp_mark_color + bp_mark, num, line)
436 line = tpl_line % (bp_mark_color + bp_mark, num, line)
436
437
437 return line
438 return line
438
439
439 def list_command_pydb(self, arg):
440 def list_command_pydb(self, arg):
440 """List command to use if we have a newer pydb installed"""
441 """List command to use if we have a newer pydb installed"""
441 filename, first, last = OldPdb.parse_list_cmd(self, arg)
442 filename, first, last = OldPdb.parse_list_cmd(self, arg)
442 if filename is not None:
443 if filename is not None:
443 self.print_list_lines(filename, first, last)
444 self.print_list_lines(filename, first, last)
444
445
445 def print_list_lines(self, filename, first, last):
446 def print_list_lines(self, filename, first, last):
446 """The printing (as opposed to the parsing part of a 'list'
447 """The printing (as opposed to the parsing part of a 'list'
447 command."""
448 command."""
448 try:
449 try:
449 Colors = self.color_scheme_table.active_colors
450 Colors = self.color_scheme_table.active_colors
450 ColorsNormal = Colors.Normal
451 ColorsNormal = Colors.Normal
451 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
452 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
452 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
453 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
453 src = []
454 src = []
454 for lineno in range(first, last+1):
455 for lineno in range(first, last+1):
455 line = linecache.getline(filename, lineno)
456 line = linecache.getline(filename, lineno)
456 if not line:
457 if not line:
457 break
458 break
458
459
459 if lineno == self.curframe.f_lineno:
460 if lineno == self.curframe.f_lineno:
460 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
461 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
461 else:
462 else:
462 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
463 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
463
464
464 src.append(line)
465 src.append(line)
465 self.lineno = lineno
466 self.lineno = lineno
466
467
467 print >>Term.cout, ''.join(src)
468 print >>Term.cout, ''.join(src)
468
469
469 except KeyboardInterrupt:
470 except KeyboardInterrupt:
470 pass
471 pass
471
472
472 def do_list(self, arg):
473 def do_list(self, arg):
473 self.lastcmd = 'list'
474 self.lastcmd = 'list'
474 last = None
475 last = None
475 if arg:
476 if arg:
476 try:
477 try:
477 x = eval(arg, {}, {})
478 x = eval(arg, {}, {})
478 if type(x) == type(()):
479 if type(x) == type(()):
479 first, last = x
480 first, last = x
480 first = int(first)
481 first = int(first)
481 last = int(last)
482 last = int(last)
482 if last < first:
483 if last < first:
483 # Assume it's a count
484 # Assume it's a count
484 last = first + last
485 last = first + last
485 else:
486 else:
486 first = max(1, int(x) - 5)
487 first = max(1, int(x) - 5)
487 except:
488 except:
488 print '*** Error in argument:', `arg`
489 print '*** Error in argument:', `arg`
489 return
490 return
490 elif self.lineno is None:
491 elif self.lineno is None:
491 first = max(1, self.curframe.f_lineno - 5)
492 first = max(1, self.curframe.f_lineno - 5)
492 else:
493 else:
493 first = self.lineno + 1
494 first = self.lineno + 1
494 if last is None:
495 if last is None:
495 last = first + 10
496 last = first + 10
496 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
497 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
497
498
498 # vds: >>
499 # vds: >>
499 lineno = first
500 lineno = first
500 filename = self.curframe.f_code.co_filename
501 filename = self.curframe.f_code.co_filename
501 __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0)
502 __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0)
502 # vds: <<
503 # vds: <<
503
504
504 do_l = do_list
505 do_l = do_list
505
506
506 def do_pdef(self, arg):
507 def do_pdef(self, arg):
507 """The debugger interface to magic_pdef"""
508 """The debugger interface to magic_pdef"""
508 namespaces = [('Locals', self.curframe.f_locals),
509 namespaces = [('Locals', self.curframe.f_locals),
509 ('Globals', self.curframe.f_globals)]
510 ('Globals', self.curframe.f_globals)]
510 __IPYTHON__.magic_pdef(arg, namespaces=namespaces)
511 __IPYTHON__.magic_pdef(arg, namespaces=namespaces)
511
512
512 def do_pdoc(self, arg):
513 def do_pdoc(self, arg):
513 """The debugger interface to magic_pdoc"""
514 """The debugger interface to magic_pdoc"""
514 namespaces = [('Locals', self.curframe.f_locals),
515 namespaces = [('Locals', self.curframe.f_locals),
515 ('Globals', self.curframe.f_globals)]
516 ('Globals', self.curframe.f_globals)]
516 __IPYTHON__.magic_pdoc(arg, namespaces=namespaces)
517 __IPYTHON__.magic_pdoc(arg, namespaces=namespaces)
517
518
518 def do_pinfo(self, arg):
519 def do_pinfo(self, arg):
519 """The debugger equivalant of ?obj"""
520 """The debugger equivalant of ?obj"""
520 namespaces = [('Locals', self.curframe.f_locals),
521 namespaces = [('Locals', self.curframe.f_locals),
521 ('Globals', self.curframe.f_globals)]
522 ('Globals', self.curframe.f_globals)]
522 __IPYTHON__.magic_pinfo("pinfo %s" % arg, namespaces=namespaces)
523 __IPYTHON__.magic_pinfo("pinfo %s" % arg, namespaces=namespaces)
@@ -1,607 +1,607 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tools for inspecting Python objects.
2 """Tools for inspecting Python objects.
3
3
4 Uses syntax highlighting for presenting the various information elements.
4 Uses syntax highlighting for presenting the various information elements.
5
5
6 Similar in spirit to the inspect module, but all calls take a name argument to
6 Similar in spirit to the inspect module, but all calls take a name argument to
7 reference the name under which an object is being read.
7 reference the name under which an object is being read.
8 """
8 """
9
9
10 #*****************************************************************************
10 #*****************************************************************************
11 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
11 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
12 #
12 #
13 # Distributed under the terms of the BSD License. The full license is in
13 # Distributed under the terms of the BSD License. The full license is in
14 # the file COPYING, distributed as part of this software.
14 # the file COPYING, distributed as part of this software.
15 #*****************************************************************************
15 #*****************************************************************************
16
16
17 __all__ = ['Inspector','InspectColors']
17 __all__ = ['Inspector','InspectColors']
18
18
19 # stdlib modules
19 # stdlib modules
20 import __builtin__
20 import __builtin__
21 import StringIO
21 import StringIO
22 import inspect
22 import inspect
23 import linecache
23 import linecache
24 import os
24 import os
25 import string
25 import string
26 import sys
26 import sys
27 import types
27 import types
28
28
29 # IPython's own
29 # IPython's own
30 from IPython import PyColorize
30 from IPython import PyColorize
31 from IPython.genutils import page,indent,Term
31 from IPython.genutils import page,indent,Term
32 from IPython.Itpl import itpl
32 from IPython.Itpl import itpl
33 from IPython.wildcard import list_namespace
33 from IPython.wildcard import list_namespace
34 from IPython.ColorANSI import *
34 from IPython.utils.coloransi import *
35
35
36 #****************************************************************************
36 #****************************************************************************
37 # HACK!!! This is a crude fix for bugs in python 2.3's inspect module. We
37 # HACK!!! This is a crude fix for bugs in python 2.3's inspect module. We
38 # simply monkeypatch inspect with code copied from python 2.4.
38 # simply monkeypatch inspect with code copied from python 2.4.
39 if sys.version_info[:2] == (2,3):
39 if sys.version_info[:2] == (2,3):
40 from inspect import ismodule, getabsfile, modulesbyfile
40 from inspect import ismodule, getabsfile, modulesbyfile
41 def getmodule(object):
41 def getmodule(object):
42 """Return the module an object was defined in, or None if not found."""
42 """Return the module an object was defined in, or None if not found."""
43 if ismodule(object):
43 if ismodule(object):
44 return object
44 return object
45 if hasattr(object, '__module__'):
45 if hasattr(object, '__module__'):
46 return sys.modules.get(object.__module__)
46 return sys.modules.get(object.__module__)
47 try:
47 try:
48 file = getabsfile(object)
48 file = getabsfile(object)
49 except TypeError:
49 except TypeError:
50 return None
50 return None
51 if file in modulesbyfile:
51 if file in modulesbyfile:
52 return sys.modules.get(modulesbyfile[file])
52 return sys.modules.get(modulesbyfile[file])
53 for module in sys.modules.values():
53 for module in sys.modules.values():
54 if hasattr(module, '__file__'):
54 if hasattr(module, '__file__'):
55 modulesbyfile[
55 modulesbyfile[
56 os.path.realpath(
56 os.path.realpath(
57 getabsfile(module))] = module.__name__
57 getabsfile(module))] = module.__name__
58 if file in modulesbyfile:
58 if file in modulesbyfile:
59 return sys.modules.get(modulesbyfile[file])
59 return sys.modules.get(modulesbyfile[file])
60 main = sys.modules['__main__']
60 main = sys.modules['__main__']
61 if not hasattr(object, '__name__'):
61 if not hasattr(object, '__name__'):
62 return None
62 return None
63 if hasattr(main, object.__name__):
63 if hasattr(main, object.__name__):
64 mainobject = getattr(main, object.__name__)
64 mainobject = getattr(main, object.__name__)
65 if mainobject is object:
65 if mainobject is object:
66 return main
66 return main
67 builtin = sys.modules['__builtin__']
67 builtin = sys.modules['__builtin__']
68 if hasattr(builtin, object.__name__):
68 if hasattr(builtin, object.__name__):
69 builtinobject = getattr(builtin, object.__name__)
69 builtinobject = getattr(builtin, object.__name__)
70 if builtinobject is object:
70 if builtinobject is object:
71 return builtin
71 return builtin
72
72
73 inspect.getmodule = getmodule
73 inspect.getmodule = getmodule
74
74
75 #****************************************************************************
75 #****************************************************************************
76 # Builtin color schemes
76 # Builtin color schemes
77
77
78 Colors = TermColors # just a shorthand
78 Colors = TermColors # just a shorthand
79
79
80 # Build a few color schemes
80 # Build a few color schemes
81 NoColor = ColorScheme(
81 NoColor = ColorScheme(
82 'NoColor',{
82 'NoColor',{
83 'header' : Colors.NoColor,
83 'header' : Colors.NoColor,
84 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
84 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
85 } )
85 } )
86
86
87 LinuxColors = ColorScheme(
87 LinuxColors = ColorScheme(
88 'Linux',{
88 'Linux',{
89 'header' : Colors.LightRed,
89 'header' : Colors.LightRed,
90 'normal' : Colors.Normal # color off (usu. Colors.Normal)
90 'normal' : Colors.Normal # color off (usu. Colors.Normal)
91 } )
91 } )
92
92
93 LightBGColors = ColorScheme(
93 LightBGColors = ColorScheme(
94 'LightBG',{
94 'LightBG',{
95 'header' : Colors.Red,
95 'header' : Colors.Red,
96 'normal' : Colors.Normal # color off (usu. Colors.Normal)
96 'normal' : Colors.Normal # color off (usu. Colors.Normal)
97 } )
97 } )
98
98
99 # Build table of color schemes (needed by the parser)
99 # Build table of color schemes (needed by the parser)
100 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
100 InspectColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
101 'Linux')
101 'Linux')
102
102
103 #****************************************************************************
103 #****************************************************************************
104 # Auxiliary functions
104 # Auxiliary functions
105 def getdoc(obj):
105 def getdoc(obj):
106 """Stable wrapper around inspect.getdoc.
106 """Stable wrapper around inspect.getdoc.
107
107
108 This can't crash because of attribute problems.
108 This can't crash because of attribute problems.
109
109
110 It also attempts to call a getdoc() method on the given object. This
110 It also attempts to call a getdoc() method on the given object. This
111 allows objects which provide their docstrings via non-standard mechanisms
111 allows objects which provide their docstrings via non-standard mechanisms
112 (like Pyro proxies) to still be inspected by ipython's ? system."""
112 (like Pyro proxies) to still be inspected by ipython's ? system."""
113
113
114 ds = None # default return value
114 ds = None # default return value
115 try:
115 try:
116 ds = inspect.getdoc(obj)
116 ds = inspect.getdoc(obj)
117 except:
117 except:
118 # Harden against an inspect failure, which can occur with
118 # Harden against an inspect failure, which can occur with
119 # SWIG-wrapped extensions.
119 # SWIG-wrapped extensions.
120 pass
120 pass
121 # Allow objects to offer customized documentation via a getdoc method:
121 # Allow objects to offer customized documentation via a getdoc method:
122 try:
122 try:
123 ds2 = obj.getdoc()
123 ds2 = obj.getdoc()
124 except:
124 except:
125 pass
125 pass
126 else:
126 else:
127 # if we get extra info, we add it to the normal docstring.
127 # if we get extra info, we add it to the normal docstring.
128 if ds is None:
128 if ds is None:
129 ds = ds2
129 ds = ds2
130 else:
130 else:
131 ds = '%s\n%s' % (ds,ds2)
131 ds = '%s\n%s' % (ds,ds2)
132 return ds
132 return ds
133
133
134
134
135 def getsource(obj,is_binary=False):
135 def getsource(obj,is_binary=False):
136 """Wrapper around inspect.getsource.
136 """Wrapper around inspect.getsource.
137
137
138 This can be modified by other projects to provide customized source
138 This can be modified by other projects to provide customized source
139 extraction.
139 extraction.
140
140
141 Inputs:
141 Inputs:
142
142
143 - obj: an object whose source code we will attempt to extract.
143 - obj: an object whose source code we will attempt to extract.
144
144
145 Optional inputs:
145 Optional inputs:
146
146
147 - is_binary: whether the object is known to come from a binary source.
147 - is_binary: whether the object is known to come from a binary source.
148 This implementation will skip returning any output for binary objects, but
148 This implementation will skip returning any output for binary objects, but
149 custom extractors may know how to meaningfully process them."""
149 custom extractors may know how to meaningfully process them."""
150
150
151 if is_binary:
151 if is_binary:
152 return None
152 return None
153 else:
153 else:
154 try:
154 try:
155 src = inspect.getsource(obj)
155 src = inspect.getsource(obj)
156 except TypeError:
156 except TypeError:
157 if hasattr(obj,'__class__'):
157 if hasattr(obj,'__class__'):
158 src = inspect.getsource(obj.__class__)
158 src = inspect.getsource(obj.__class__)
159 return src
159 return src
160
160
161 def getargspec(obj):
161 def getargspec(obj):
162 """Get the names and default values of a function's arguments.
162 """Get the names and default values of a function's arguments.
163
163
164 A tuple of four things is returned: (args, varargs, varkw, defaults).
164 A tuple of four things is returned: (args, varargs, varkw, defaults).
165 'args' is a list of the argument names (it may contain nested lists).
165 'args' is a list of the argument names (it may contain nested lists).
166 'varargs' and 'varkw' are the names of the * and ** arguments or None.
166 'varargs' and 'varkw' are the names of the * and ** arguments or None.
167 'defaults' is an n-tuple of the default values of the last n arguments.
167 'defaults' is an n-tuple of the default values of the last n arguments.
168
168
169 Modified version of inspect.getargspec from the Python Standard
169 Modified version of inspect.getargspec from the Python Standard
170 Library."""
170 Library."""
171
171
172 if inspect.isfunction(obj):
172 if inspect.isfunction(obj):
173 func_obj = obj
173 func_obj = obj
174 elif inspect.ismethod(obj):
174 elif inspect.ismethod(obj):
175 func_obj = obj.im_func
175 func_obj = obj.im_func
176 else:
176 else:
177 raise TypeError, 'arg is not a Python function'
177 raise TypeError, 'arg is not a Python function'
178 args, varargs, varkw = inspect.getargs(func_obj.func_code)
178 args, varargs, varkw = inspect.getargs(func_obj.func_code)
179 return args, varargs, varkw, func_obj.func_defaults
179 return args, varargs, varkw, func_obj.func_defaults
180
180
181 #****************************************************************************
181 #****************************************************************************
182 # Class definitions
182 # Class definitions
183
183
184 class myStringIO(StringIO.StringIO):
184 class myStringIO(StringIO.StringIO):
185 """Adds a writeln method to normal StringIO."""
185 """Adds a writeln method to normal StringIO."""
186 def writeln(self,*arg,**kw):
186 def writeln(self,*arg,**kw):
187 """Does a write() and then a write('\n')"""
187 """Does a write() and then a write('\n')"""
188 self.write(*arg,**kw)
188 self.write(*arg,**kw)
189 self.write('\n')
189 self.write('\n')
190
190
191
191
192 class Inspector:
192 class Inspector:
193 def __init__(self,color_table,code_color_table,scheme,
193 def __init__(self,color_table,code_color_table,scheme,
194 str_detail_level=0):
194 str_detail_level=0):
195 self.color_table = color_table
195 self.color_table = color_table
196 self.parser = PyColorize.Parser(code_color_table,out='str')
196 self.parser = PyColorize.Parser(code_color_table,out='str')
197 self.format = self.parser.format
197 self.format = self.parser.format
198 self.str_detail_level = str_detail_level
198 self.str_detail_level = str_detail_level
199 self.set_active_scheme(scheme)
199 self.set_active_scheme(scheme)
200
200
201 def __getdef(self,obj,oname=''):
201 def __getdef(self,obj,oname=''):
202 """Return the definition header for any callable object.
202 """Return the definition header for any callable object.
203
203
204 If any exception is generated, None is returned instead and the
204 If any exception is generated, None is returned instead and the
205 exception is suppressed."""
205 exception is suppressed."""
206
206
207 try:
207 try:
208 return oname + inspect.formatargspec(*getargspec(obj))
208 return oname + inspect.formatargspec(*getargspec(obj))
209 except:
209 except:
210 return None
210 return None
211
211
212 def __head(self,h):
212 def __head(self,h):
213 """Return a header string with proper colors."""
213 """Return a header string with proper colors."""
214 return '%s%s%s' % (self.color_table.active_colors.header,h,
214 return '%s%s%s' % (self.color_table.active_colors.header,h,
215 self.color_table.active_colors.normal)
215 self.color_table.active_colors.normal)
216
216
217 def set_active_scheme(self,scheme):
217 def set_active_scheme(self,scheme):
218 self.color_table.set_active_scheme(scheme)
218 self.color_table.set_active_scheme(scheme)
219 self.parser.color_table.set_active_scheme(scheme)
219 self.parser.color_table.set_active_scheme(scheme)
220
220
221 def noinfo(self,msg,oname):
221 def noinfo(self,msg,oname):
222 """Generic message when no information is found."""
222 """Generic message when no information is found."""
223 print 'No %s found' % msg,
223 print 'No %s found' % msg,
224 if oname:
224 if oname:
225 print 'for %s' % oname
225 print 'for %s' % oname
226 else:
226 else:
227 print
227 print
228
228
229 def pdef(self,obj,oname=''):
229 def pdef(self,obj,oname=''):
230 """Print the definition header for any callable object.
230 """Print the definition header for any callable object.
231
231
232 If the object is a class, print the constructor information."""
232 If the object is a class, print the constructor information."""
233
233
234 if not callable(obj):
234 if not callable(obj):
235 print 'Object is not callable.'
235 print 'Object is not callable.'
236 return
236 return
237
237
238 header = ''
238 header = ''
239
239
240 if inspect.isclass(obj):
240 if inspect.isclass(obj):
241 header = self.__head('Class constructor information:\n')
241 header = self.__head('Class constructor information:\n')
242 obj = obj.__init__
242 obj = obj.__init__
243 elif type(obj) is types.InstanceType:
243 elif type(obj) is types.InstanceType:
244 obj = obj.__call__
244 obj = obj.__call__
245
245
246 output = self.__getdef(obj,oname)
246 output = self.__getdef(obj,oname)
247 if output is None:
247 if output is None:
248 self.noinfo('definition header',oname)
248 self.noinfo('definition header',oname)
249 else:
249 else:
250 print >>Term.cout, header,self.format(output),
250 print >>Term.cout, header,self.format(output),
251
251
252 def pdoc(self,obj,oname='',formatter = None):
252 def pdoc(self,obj,oname='',formatter = None):
253 """Print the docstring for any object.
253 """Print the docstring for any object.
254
254
255 Optional:
255 Optional:
256 -formatter: a function to run the docstring through for specially
256 -formatter: a function to run the docstring through for specially
257 formatted docstrings."""
257 formatted docstrings."""
258
258
259 head = self.__head # so that itpl can find it even if private
259 head = self.__head # so that itpl can find it even if private
260 ds = getdoc(obj)
260 ds = getdoc(obj)
261 if formatter:
261 if formatter:
262 ds = formatter(ds)
262 ds = formatter(ds)
263 if inspect.isclass(obj):
263 if inspect.isclass(obj):
264 init_ds = getdoc(obj.__init__)
264 init_ds = getdoc(obj.__init__)
265 output = itpl('$head("Class Docstring:")\n'
265 output = itpl('$head("Class Docstring:")\n'
266 '$indent(ds)\n'
266 '$indent(ds)\n'
267 '$head("Constructor Docstring"):\n'
267 '$head("Constructor Docstring"):\n'
268 '$indent(init_ds)')
268 '$indent(init_ds)')
269 elif (type(obj) is types.InstanceType or isinstance(obj,object)) \
269 elif (type(obj) is types.InstanceType or isinstance(obj,object)) \
270 and hasattr(obj,'__call__'):
270 and hasattr(obj,'__call__'):
271 call_ds = getdoc(obj.__call__)
271 call_ds = getdoc(obj.__call__)
272 if call_ds:
272 if call_ds:
273 output = itpl('$head("Class Docstring:")\n$indent(ds)\n'
273 output = itpl('$head("Class Docstring:")\n$indent(ds)\n'
274 '$head("Calling Docstring:")\n$indent(call_ds)')
274 '$head("Calling Docstring:")\n$indent(call_ds)')
275 else:
275 else:
276 output = ds
276 output = ds
277 else:
277 else:
278 output = ds
278 output = ds
279 if output is None:
279 if output is None:
280 self.noinfo('documentation',oname)
280 self.noinfo('documentation',oname)
281 return
281 return
282 page(output)
282 page(output)
283
283
284 def psource(self,obj,oname=''):
284 def psource(self,obj,oname=''):
285 """Print the source code for an object."""
285 """Print the source code for an object."""
286
286
287 # Flush the source cache because inspect can return out-of-date source
287 # Flush the source cache because inspect can return out-of-date source
288 linecache.checkcache()
288 linecache.checkcache()
289 try:
289 try:
290 src = getsource(obj)
290 src = getsource(obj)
291 except:
291 except:
292 self.noinfo('source',oname)
292 self.noinfo('source',oname)
293 else:
293 else:
294 page(self.format(src))
294 page(self.format(src))
295
295
296 def pfile(self,obj,oname=''):
296 def pfile(self,obj,oname=''):
297 """Show the whole file where an object was defined."""
297 """Show the whole file where an object was defined."""
298
298
299 try:
299 try:
300 try:
300 try:
301 lineno = inspect.getsourcelines(obj)[1]
301 lineno = inspect.getsourcelines(obj)[1]
302 except TypeError:
302 except TypeError:
303 # For instances, try the class object like getsource() does
303 # For instances, try the class object like getsource() does
304 if hasattr(obj,'__class__'):
304 if hasattr(obj,'__class__'):
305 lineno = inspect.getsourcelines(obj.__class__)[1]
305 lineno = inspect.getsourcelines(obj.__class__)[1]
306 # Adjust the inspected object so getabsfile() below works
306 # Adjust the inspected object so getabsfile() below works
307 obj = obj.__class__
307 obj = obj.__class__
308 except:
308 except:
309 self.noinfo('file',oname)
309 self.noinfo('file',oname)
310 return
310 return
311
311
312 # We only reach this point if object was successfully queried
312 # We only reach this point if object was successfully queried
313
313
314 # run contents of file through pager starting at line
314 # run contents of file through pager starting at line
315 # where the object is defined
315 # where the object is defined
316 ofile = inspect.getabsfile(obj)
316 ofile = inspect.getabsfile(obj)
317
317
318 if (ofile.endswith('.so') or ofile.endswith('.dll')):
318 if (ofile.endswith('.so') or ofile.endswith('.dll')):
319 print 'File %r is binary, not printing.' % ofile
319 print 'File %r is binary, not printing.' % ofile
320 elif not os.path.isfile(ofile):
320 elif not os.path.isfile(ofile):
321 print 'File %r does not exist, not printing.' % ofile
321 print 'File %r does not exist, not printing.' % ofile
322 else:
322 else:
323 # Print only text files, not extension binaries. Note that
323 # Print only text files, not extension binaries. Note that
324 # getsourcelines returns lineno with 1-offset and page() uses
324 # getsourcelines returns lineno with 1-offset and page() uses
325 # 0-offset, so we must adjust.
325 # 0-offset, so we must adjust.
326 page(self.format(open(ofile).read()),lineno-1)
326 page(self.format(open(ofile).read()),lineno-1)
327
327
328 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
328 def pinfo(self,obj,oname='',formatter=None,info=None,detail_level=0):
329 """Show detailed information about an object.
329 """Show detailed information about an object.
330
330
331 Optional arguments:
331 Optional arguments:
332
332
333 - oname: name of the variable pointing to the object.
333 - oname: name of the variable pointing to the object.
334
334
335 - formatter: special formatter for docstrings (see pdoc)
335 - formatter: special formatter for docstrings (see pdoc)
336
336
337 - info: a structure with some information fields which may have been
337 - info: a structure with some information fields which may have been
338 precomputed already.
338 precomputed already.
339
339
340 - detail_level: if set to 1, more information is given.
340 - detail_level: if set to 1, more information is given.
341 """
341 """
342
342
343 obj_type = type(obj)
343 obj_type = type(obj)
344
344
345 header = self.__head
345 header = self.__head
346 if info is None:
346 if info is None:
347 ismagic = 0
347 ismagic = 0
348 isalias = 0
348 isalias = 0
349 ospace = ''
349 ospace = ''
350 else:
350 else:
351 ismagic = info.ismagic
351 ismagic = info.ismagic
352 isalias = info.isalias
352 isalias = info.isalias
353 ospace = info.namespace
353 ospace = info.namespace
354 # Get docstring, special-casing aliases:
354 # Get docstring, special-casing aliases:
355 if isalias:
355 if isalias:
356 if not callable(obj):
356 if not callable(obj):
357 try:
357 try:
358 ds = "Alias to the system command:\n %s" % obj[1]
358 ds = "Alias to the system command:\n %s" % obj[1]
359 except:
359 except:
360 ds = "Alias: " + str(obj)
360 ds = "Alias: " + str(obj)
361 else:
361 else:
362 ds = "Alias to " + str(obj)
362 ds = "Alias to " + str(obj)
363 if obj.__doc__:
363 if obj.__doc__:
364 ds += "\nDocstring:\n" + obj.__doc__
364 ds += "\nDocstring:\n" + obj.__doc__
365 else:
365 else:
366 ds = getdoc(obj)
366 ds = getdoc(obj)
367 if ds is None:
367 if ds is None:
368 ds = '<no docstring>'
368 ds = '<no docstring>'
369 if formatter is not None:
369 if formatter is not None:
370 ds = formatter(ds)
370 ds = formatter(ds)
371
371
372 # store output in a list which gets joined with \n at the end.
372 # store output in a list which gets joined with \n at the end.
373 out = myStringIO()
373 out = myStringIO()
374
374
375 string_max = 200 # max size of strings to show (snipped if longer)
375 string_max = 200 # max size of strings to show (snipped if longer)
376 shalf = int((string_max -5)/2)
376 shalf = int((string_max -5)/2)
377
377
378 if ismagic:
378 if ismagic:
379 obj_type_name = 'Magic function'
379 obj_type_name = 'Magic function'
380 elif isalias:
380 elif isalias:
381 obj_type_name = 'System alias'
381 obj_type_name = 'System alias'
382 else:
382 else:
383 obj_type_name = obj_type.__name__
383 obj_type_name = obj_type.__name__
384 out.writeln(header('Type:\t\t')+obj_type_name)
384 out.writeln(header('Type:\t\t')+obj_type_name)
385
385
386 try:
386 try:
387 bclass = obj.__class__
387 bclass = obj.__class__
388 out.writeln(header('Base Class:\t')+str(bclass))
388 out.writeln(header('Base Class:\t')+str(bclass))
389 except: pass
389 except: pass
390
390
391 # String form, but snip if too long in ? form (full in ??)
391 # String form, but snip if too long in ? form (full in ??)
392 if detail_level >= self.str_detail_level:
392 if detail_level >= self.str_detail_level:
393 try:
393 try:
394 ostr = str(obj)
394 ostr = str(obj)
395 str_head = 'String Form:'
395 str_head = 'String Form:'
396 if not detail_level and len(ostr)>string_max:
396 if not detail_level and len(ostr)>string_max:
397 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
397 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
398 ostr = ("\n" + " " * len(str_head.expandtabs())).\
398 ostr = ("\n" + " " * len(str_head.expandtabs())).\
399 join(map(string.strip,ostr.split("\n")))
399 join(map(string.strip,ostr.split("\n")))
400 if ostr.find('\n') > -1:
400 if ostr.find('\n') > -1:
401 # Print multi-line strings starting at the next line.
401 # Print multi-line strings starting at the next line.
402 str_sep = '\n'
402 str_sep = '\n'
403 else:
403 else:
404 str_sep = '\t'
404 str_sep = '\t'
405 out.writeln("%s%s%s" % (header(str_head),str_sep,ostr))
405 out.writeln("%s%s%s" % (header(str_head),str_sep,ostr))
406 except:
406 except:
407 pass
407 pass
408
408
409 if ospace:
409 if ospace:
410 out.writeln(header('Namespace:\t')+ospace)
410 out.writeln(header('Namespace:\t')+ospace)
411
411
412 # Length (for strings and lists)
412 # Length (for strings and lists)
413 try:
413 try:
414 length = str(len(obj))
414 length = str(len(obj))
415 out.writeln(header('Length:\t\t')+length)
415 out.writeln(header('Length:\t\t')+length)
416 except: pass
416 except: pass
417
417
418 # Filename where object was defined
418 # Filename where object was defined
419 binary_file = False
419 binary_file = False
420 try:
420 try:
421 try:
421 try:
422 fname = inspect.getabsfile(obj)
422 fname = inspect.getabsfile(obj)
423 except TypeError:
423 except TypeError:
424 # For an instance, the file that matters is where its class was
424 # For an instance, the file that matters is where its class was
425 # declared.
425 # declared.
426 if hasattr(obj,'__class__'):
426 if hasattr(obj,'__class__'):
427 fname = inspect.getabsfile(obj.__class__)
427 fname = inspect.getabsfile(obj.__class__)
428 if fname.endswith('<string>'):
428 if fname.endswith('<string>'):
429 fname = 'Dynamically generated function. No source code available.'
429 fname = 'Dynamically generated function. No source code available.'
430 if (fname.endswith('.so') or fname.endswith('.dll')):
430 if (fname.endswith('.so') or fname.endswith('.dll')):
431 binary_file = True
431 binary_file = True
432 out.writeln(header('File:\t\t')+fname)
432 out.writeln(header('File:\t\t')+fname)
433 except:
433 except:
434 # if anything goes wrong, we don't want to show source, so it's as
434 # if anything goes wrong, we don't want to show source, so it's as
435 # if the file was binary
435 # if the file was binary
436 binary_file = True
436 binary_file = True
437
437
438 # reconstruct the function definition and print it:
438 # reconstruct the function definition and print it:
439 defln = self.__getdef(obj,oname)
439 defln = self.__getdef(obj,oname)
440 if defln:
440 if defln:
441 out.write(header('Definition:\t')+self.format(defln))
441 out.write(header('Definition:\t')+self.format(defln))
442
442
443 # Docstrings only in detail 0 mode, since source contains them (we
443 # Docstrings only in detail 0 mode, since source contains them (we
444 # avoid repetitions). If source fails, we add them back, see below.
444 # avoid repetitions). If source fails, we add them back, see below.
445 if ds and detail_level == 0:
445 if ds and detail_level == 0:
446 out.writeln(header('Docstring:\n') + indent(ds))
446 out.writeln(header('Docstring:\n') + indent(ds))
447
447
448 # Original source code for any callable
448 # Original source code for any callable
449 if detail_level:
449 if detail_level:
450 # Flush the source cache because inspect can return out-of-date
450 # Flush the source cache because inspect can return out-of-date
451 # source
451 # source
452 linecache.checkcache()
452 linecache.checkcache()
453 source_success = False
453 source_success = False
454 try:
454 try:
455 try:
455 try:
456 src = getsource(obj,binary_file)
456 src = getsource(obj,binary_file)
457 except TypeError:
457 except TypeError:
458 if hasattr(obj,'__class__'):
458 if hasattr(obj,'__class__'):
459 src = getsource(obj.__class__,binary_file)
459 src = getsource(obj.__class__,binary_file)
460 if src is not None:
460 if src is not None:
461 source = self.format(src)
461 source = self.format(src)
462 out.write(header('Source:\n')+source.rstrip())
462 out.write(header('Source:\n')+source.rstrip())
463 source_success = True
463 source_success = True
464 except Exception, msg:
464 except Exception, msg:
465 pass
465 pass
466
466
467 if ds and not source_success:
467 if ds and not source_success:
468 out.writeln(header('Docstring [source file open failed]:\n')
468 out.writeln(header('Docstring [source file open failed]:\n')
469 + indent(ds))
469 + indent(ds))
470
470
471 # Constructor docstring for classes
471 # Constructor docstring for classes
472 if inspect.isclass(obj):
472 if inspect.isclass(obj):
473 # reconstruct the function definition and print it:
473 # reconstruct the function definition and print it:
474 try:
474 try:
475 obj_init = obj.__init__
475 obj_init = obj.__init__
476 except AttributeError:
476 except AttributeError:
477 init_def = init_ds = None
477 init_def = init_ds = None
478 else:
478 else:
479 init_def = self.__getdef(obj_init,oname)
479 init_def = self.__getdef(obj_init,oname)
480 init_ds = getdoc(obj_init)
480 init_ds = getdoc(obj_init)
481 # Skip Python's auto-generated docstrings
481 # Skip Python's auto-generated docstrings
482 if init_ds and \
482 if init_ds and \
483 init_ds.startswith('x.__init__(...) initializes'):
483 init_ds.startswith('x.__init__(...) initializes'):
484 init_ds = None
484 init_ds = None
485
485
486 if init_def or init_ds:
486 if init_def or init_ds:
487 out.writeln(header('\nConstructor information:'))
487 out.writeln(header('\nConstructor information:'))
488 if init_def:
488 if init_def:
489 out.write(header('Definition:\t')+ self.format(init_def))
489 out.write(header('Definition:\t')+ self.format(init_def))
490 if init_ds:
490 if init_ds:
491 out.writeln(header('Docstring:\n') + indent(init_ds))
491 out.writeln(header('Docstring:\n') + indent(init_ds))
492 # and class docstring for instances:
492 # and class docstring for instances:
493 elif obj_type is types.InstanceType or \
493 elif obj_type is types.InstanceType or \
494 isinstance(obj,object):
494 isinstance(obj,object):
495
495
496 # First, check whether the instance docstring is identical to the
496 # First, check whether the instance docstring is identical to the
497 # class one, and print it separately if they don't coincide. In
497 # class one, and print it separately if they don't coincide. In
498 # most cases they will, but it's nice to print all the info for
498 # most cases they will, but it's nice to print all the info for
499 # objects which use instance-customized docstrings.
499 # objects which use instance-customized docstrings.
500 if ds:
500 if ds:
501 try:
501 try:
502 cls = getattr(obj,'__class__')
502 cls = getattr(obj,'__class__')
503 except:
503 except:
504 class_ds = None
504 class_ds = None
505 else:
505 else:
506 class_ds = getdoc(cls)
506 class_ds = getdoc(cls)
507 # Skip Python's auto-generated docstrings
507 # Skip Python's auto-generated docstrings
508 if class_ds and \
508 if class_ds and \
509 (class_ds.startswith('function(code, globals[,') or \
509 (class_ds.startswith('function(code, globals[,') or \
510 class_ds.startswith('instancemethod(function, instance,') or \
510 class_ds.startswith('instancemethod(function, instance,') or \
511 class_ds.startswith('module(name[,') ):
511 class_ds.startswith('module(name[,') ):
512 class_ds = None
512 class_ds = None
513 if class_ds and ds != class_ds:
513 if class_ds and ds != class_ds:
514 out.writeln(header('Class Docstring:\n') +
514 out.writeln(header('Class Docstring:\n') +
515 indent(class_ds))
515 indent(class_ds))
516
516
517 # Next, try to show constructor docstrings
517 # Next, try to show constructor docstrings
518 try:
518 try:
519 init_ds = getdoc(obj.__init__)
519 init_ds = getdoc(obj.__init__)
520 # Skip Python's auto-generated docstrings
520 # Skip Python's auto-generated docstrings
521 if init_ds and \
521 if init_ds and \
522 init_ds.startswith('x.__init__(...) initializes'):
522 init_ds.startswith('x.__init__(...) initializes'):
523 init_ds = None
523 init_ds = None
524 except AttributeError:
524 except AttributeError:
525 init_ds = None
525 init_ds = None
526 if init_ds:
526 if init_ds:
527 out.writeln(header('Constructor Docstring:\n') +
527 out.writeln(header('Constructor Docstring:\n') +
528 indent(init_ds))
528 indent(init_ds))
529
529
530 # Call form docstring for callable instances
530 # Call form docstring for callable instances
531 if hasattr(obj,'__call__'):
531 if hasattr(obj,'__call__'):
532 #out.writeln(header('Callable:\t')+'Yes')
532 #out.writeln(header('Callable:\t')+'Yes')
533 call_def = self.__getdef(obj.__call__,oname)
533 call_def = self.__getdef(obj.__call__,oname)
534 #if call_def is None:
534 #if call_def is None:
535 # out.writeln(header('Call def:\t')+
535 # out.writeln(header('Call def:\t')+
536 # 'Calling definition not available.')
536 # 'Calling definition not available.')
537 if call_def is not None:
537 if call_def is not None:
538 out.writeln(header('Call def:\t')+self.format(call_def))
538 out.writeln(header('Call def:\t')+self.format(call_def))
539 call_ds = getdoc(obj.__call__)
539 call_ds = getdoc(obj.__call__)
540 # Skip Python's auto-generated docstrings
540 # Skip Python's auto-generated docstrings
541 if call_ds and call_ds.startswith('x.__call__(...) <==> x(...)'):
541 if call_ds and call_ds.startswith('x.__call__(...) <==> x(...)'):
542 call_ds = None
542 call_ds = None
543 if call_ds:
543 if call_ds:
544 out.writeln(header('Call docstring:\n') + indent(call_ds))
544 out.writeln(header('Call docstring:\n') + indent(call_ds))
545
545
546 # Finally send to printer/pager
546 # Finally send to printer/pager
547 output = out.getvalue()
547 output = out.getvalue()
548 if output:
548 if output:
549 page(output)
549 page(output)
550 # end pinfo
550 # end pinfo
551
551
552 def psearch(self,pattern,ns_table,ns_search=[],
552 def psearch(self,pattern,ns_table,ns_search=[],
553 ignore_case=False,show_all=False):
553 ignore_case=False,show_all=False):
554 """Search namespaces with wildcards for objects.
554 """Search namespaces with wildcards for objects.
555
555
556 Arguments:
556 Arguments:
557
557
558 - pattern: string containing shell-like wildcards to use in namespace
558 - pattern: string containing shell-like wildcards to use in namespace
559 searches and optionally a type specification to narrow the search to
559 searches and optionally a type specification to narrow the search to
560 objects of that type.
560 objects of that type.
561
561
562 - ns_table: dict of name->namespaces for search.
562 - ns_table: dict of name->namespaces for search.
563
563
564 Optional arguments:
564 Optional arguments:
565
565
566 - ns_search: list of namespace names to include in search.
566 - ns_search: list of namespace names to include in search.
567
567
568 - ignore_case(False): make the search case-insensitive.
568 - ignore_case(False): make the search case-insensitive.
569
569
570 - show_all(False): show all names, including those starting with
570 - show_all(False): show all names, including those starting with
571 underscores.
571 underscores.
572 """
572 """
573 #print 'ps pattern:<%r>' % pattern # dbg
573 #print 'ps pattern:<%r>' % pattern # dbg
574
574
575 # defaults
575 # defaults
576 type_pattern = 'all'
576 type_pattern = 'all'
577 filter = ''
577 filter = ''
578
578
579 cmds = pattern.split()
579 cmds = pattern.split()
580 len_cmds = len(cmds)
580 len_cmds = len(cmds)
581 if len_cmds == 1:
581 if len_cmds == 1:
582 # Only filter pattern given
582 # Only filter pattern given
583 filter = cmds[0]
583 filter = cmds[0]
584 elif len_cmds == 2:
584 elif len_cmds == 2:
585 # Both filter and type specified
585 # Both filter and type specified
586 filter,type_pattern = cmds
586 filter,type_pattern = cmds
587 else:
587 else:
588 raise ValueError('invalid argument string for psearch: <%s>' %
588 raise ValueError('invalid argument string for psearch: <%s>' %
589 pattern)
589 pattern)
590
590
591 # filter search namespaces
591 # filter search namespaces
592 for name in ns_search:
592 for name in ns_search:
593 if name not in ns_table:
593 if name not in ns_table:
594 raise ValueError('invalid namespace <%s>. Valid names: %s' %
594 raise ValueError('invalid namespace <%s>. Valid names: %s' %
595 (name,ns_table.keys()))
595 (name,ns_table.keys()))
596
596
597 #print 'type_pattern:',type_pattern # dbg
597 #print 'type_pattern:',type_pattern # dbg
598 search_result = []
598 search_result = []
599 for ns_name in ns_search:
599 for ns_name in ns_search:
600 ns = ns_table[ns_name]
600 ns = ns_table[ns_name]
601 tmp_res = list(list_namespace(ns,type_pattern,filter,
601 tmp_res = list(list_namespace(ns,type_pattern,filter,
602 ignore_case=ignore_case,
602 ignore_case=ignore_case,
603 show_all=show_all))
603 show_all=show_all))
604 search_result.extend(tmp_res)
604 search_result.extend(tmp_res)
605 search_result.sort()
605 search_result.sort()
606
606
607 page('\n'.join(search_result))
607 page('\n'.join(search_result))
@@ -1,626 +1,626 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Classes for handling input/output prompts.
3 Classes for handling input/output prompts.
4 """
4 """
5
5
6 #*****************************************************************************
6 #*****************************************************************************
7 # Copyright (C) 2008-2009 The IPython Development Team
7 # Copyright (C) 2008-2009 The IPython Development Team
8 # Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
8 # Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #*****************************************************************************
12 #*****************************************************************************
13
13
14 #****************************************************************************
14 #****************************************************************************
15 # Required modules
15 # Required modules
16 import __builtin__
16 import __builtin__
17 import os
17 import os
18 import socket
18 import socket
19 import sys
19 import sys
20 import time
20 import time
21
21
22 # IPython's own
22 # IPython's own
23 from IPython import ColorANSI
23 from IPython.utils import coloransi
24 from IPython import Release
24 from IPython import Release
25 from IPython.external.Itpl import ItplNS
25 from IPython.external.Itpl import ItplNS
26 from IPython.ipapi import TryNext
26 from IPython.ipapi import TryNext
27 from IPython.ipstruct import Struct
27 from IPython.ipstruct import Struct
28 from IPython.macro import Macro
28 from IPython.macro import Macro
29
29
30 from IPython.genutils import *
30 from IPython.genutils import *
31
31
32 #****************************************************************************
32 #****************************************************************************
33 #Color schemes for Prompts.
33 #Color schemes for Prompts.
34
34
35 PromptColors = ColorANSI.ColorSchemeTable()
35 PromptColors = coloransi.ColorSchemeTable()
36 InputColors = ColorANSI.InputTermColors # just a shorthand
36 InputColors = coloransi.InputTermColors # just a shorthand
37 Colors = ColorANSI.TermColors # just a shorthand
37 Colors = coloransi.TermColors # just a shorthand
38
38
39 PromptColors.add_scheme(ColorANSI.ColorScheme(
39 PromptColors.add_scheme(coloransi.ColorScheme(
40 'NoColor',
40 'NoColor',
41 in_prompt = InputColors.NoColor, # Input prompt
41 in_prompt = InputColors.NoColor, # Input prompt
42 in_number = InputColors.NoColor, # Input prompt number
42 in_number = InputColors.NoColor, # Input prompt number
43 in_prompt2 = InputColors.NoColor, # Continuation prompt
43 in_prompt2 = InputColors.NoColor, # Continuation prompt
44 in_normal = InputColors.NoColor, # color off (usu. Colors.Normal)
44 in_normal = InputColors.NoColor, # color off (usu. Colors.Normal)
45
45
46 out_prompt = Colors.NoColor, # Output prompt
46 out_prompt = Colors.NoColor, # Output prompt
47 out_number = Colors.NoColor, # Output prompt number
47 out_number = Colors.NoColor, # Output prompt number
48
48
49 normal = Colors.NoColor # color off (usu. Colors.Normal)
49 normal = Colors.NoColor # color off (usu. Colors.Normal)
50 ))
50 ))
51
51
52 # make some schemes as instances so we can copy them for modification easily:
52 # make some schemes as instances so we can copy them for modification easily:
53 __PColLinux = ColorANSI.ColorScheme(
53 __PColLinux = coloransi.ColorScheme(
54 'Linux',
54 'Linux',
55 in_prompt = InputColors.Green,
55 in_prompt = InputColors.Green,
56 in_number = InputColors.LightGreen,
56 in_number = InputColors.LightGreen,
57 in_prompt2 = InputColors.Green,
57 in_prompt2 = InputColors.Green,
58 in_normal = InputColors.Normal, # color off (usu. Colors.Normal)
58 in_normal = InputColors.Normal, # color off (usu. Colors.Normal)
59
59
60 out_prompt = Colors.Red,
60 out_prompt = Colors.Red,
61 out_number = Colors.LightRed,
61 out_number = Colors.LightRed,
62
62
63 normal = Colors.Normal
63 normal = Colors.Normal
64 )
64 )
65 # Don't forget to enter it into the table!
65 # Don't forget to enter it into the table!
66 PromptColors.add_scheme(__PColLinux)
66 PromptColors.add_scheme(__PColLinux)
67
67
68 # Slightly modified Linux for light backgrounds
68 # Slightly modified Linux for light backgrounds
69 __PColLightBG = __PColLinux.copy('LightBG')
69 __PColLightBG = __PColLinux.copy('LightBG')
70
70
71 __PColLightBG.colors.update(
71 __PColLightBG.colors.update(
72 in_prompt = InputColors.Blue,
72 in_prompt = InputColors.Blue,
73 in_number = InputColors.LightBlue,
73 in_number = InputColors.LightBlue,
74 in_prompt2 = InputColors.Blue
74 in_prompt2 = InputColors.Blue
75 )
75 )
76 PromptColors.add_scheme(__PColLightBG)
76 PromptColors.add_scheme(__PColLightBG)
77
77
78 del Colors,InputColors
78 del Colors,InputColors
79
79
80 #-----------------------------------------------------------------------------
80 #-----------------------------------------------------------------------------
81 def multiple_replace(dict, text):
81 def multiple_replace(dict, text):
82 """ Replace in 'text' all occurences of any key in the given
82 """ Replace in 'text' all occurences of any key in the given
83 dictionary by its corresponding value. Returns the new string."""
83 dictionary by its corresponding value. Returns the new string."""
84
84
85 # Function by Xavier Defrang, originally found at:
85 # Function by Xavier Defrang, originally found at:
86 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
86 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
87
87
88 # Create a regular expression from the dictionary keys
88 # Create a regular expression from the dictionary keys
89 regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
89 regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
90 # For each match, look-up corresponding value in dictionary
90 # For each match, look-up corresponding value in dictionary
91 return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
91 return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
92
92
93 #-----------------------------------------------------------------------------
93 #-----------------------------------------------------------------------------
94 # Special characters that can be used in prompt templates, mainly bash-like
94 # Special characters that can be used in prompt templates, mainly bash-like
95
95
96 # If $HOME isn't defined (Windows), make it an absurd string so that it can
96 # If $HOME isn't defined (Windows), make it an absurd string so that it can
97 # never be expanded out into '~'. Basically anything which can never be a
97 # never be expanded out into '~'. Basically anything which can never be a
98 # reasonable directory name will do, we just want the $HOME -> '~' operation
98 # reasonable directory name will do, we just want the $HOME -> '~' operation
99 # to become a no-op. We pre-compute $HOME here so it's not done on every
99 # to become a no-op. We pre-compute $HOME here so it's not done on every
100 # prompt call.
100 # prompt call.
101
101
102 # FIXME:
102 # FIXME:
103
103
104 # - This should be turned into a class which does proper namespace management,
104 # - This should be turned into a class which does proper namespace management,
105 # since the prompt specials need to be evaluated in a certain namespace.
105 # since the prompt specials need to be evaluated in a certain namespace.
106 # Currently it's just globals, which need to be managed manually by code
106 # Currently it's just globals, which need to be managed manually by code
107 # below.
107 # below.
108
108
109 # - I also need to split up the color schemes from the prompt specials
109 # - I also need to split up the color schemes from the prompt specials
110 # somehow. I don't have a clean design for that quite yet.
110 # somehow. I don't have a clean design for that quite yet.
111
111
112 HOME = os.environ.get("HOME","//////:::::ZZZZZ,,,~~~")
112 HOME = os.environ.get("HOME","//////:::::ZZZZZ,,,~~~")
113
113
114 # We precompute a few more strings here for the prompt_specials, which are
114 # We precompute a few more strings here for the prompt_specials, which are
115 # fixed once ipython starts. This reduces the runtime overhead of computing
115 # fixed once ipython starts. This reduces the runtime overhead of computing
116 # prompt strings.
116 # prompt strings.
117 USER = os.environ.get("USER")
117 USER = os.environ.get("USER")
118 HOSTNAME = socket.gethostname()
118 HOSTNAME = socket.gethostname()
119 HOSTNAME_SHORT = HOSTNAME.split(".")[0]
119 HOSTNAME_SHORT = HOSTNAME.split(".")[0]
120 ROOT_SYMBOL = "$#"[os.name=='nt' or os.getuid()==0]
120 ROOT_SYMBOL = "$#"[os.name=='nt' or os.getuid()==0]
121
121
122 prompt_specials_color = {
122 prompt_specials_color = {
123 # Prompt/history count
123 # Prompt/history count
124 '%n' : '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
124 '%n' : '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
125 r'\#': '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
125 r'\#': '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
126 # Just the prompt counter number, WITHOUT any coloring wrappers, so users
126 # Just the prompt counter number, WITHOUT any coloring wrappers, so users
127 # can get numbers displayed in whatever color they want.
127 # can get numbers displayed in whatever color they want.
128 r'\N': '${self.cache.prompt_count}',
128 r'\N': '${self.cache.prompt_count}',
129
129
130 # Prompt/history count, with the actual digits replaced by dots. Used
130 # Prompt/history count, with the actual digits replaced by dots. Used
131 # mainly in continuation prompts (prompt_in2)
131 # mainly in continuation prompts (prompt_in2)
132 #r'\D': '${"."*len(str(self.cache.prompt_count))}',
132 #r'\D': '${"."*len(str(self.cache.prompt_count))}',
133 # More robust form of the above expression, that uses __builtins__
133 # More robust form of the above expression, that uses __builtins__
134 r'\D': '${"."*__builtins__.len(__builtins__.str(self.cache.prompt_count))}',
134 r'\D': '${"."*__builtins__.len(__builtins__.str(self.cache.prompt_count))}',
135
135
136 # Current working directory
136 # Current working directory
137 r'\w': '${os.getcwd()}',
137 r'\w': '${os.getcwd()}',
138 # Current time
138 # Current time
139 r'\t' : '${time.strftime("%H:%M:%S")}',
139 r'\t' : '${time.strftime("%H:%M:%S")}',
140 # Basename of current working directory.
140 # Basename of current working directory.
141 # (use os.sep to make this portable across OSes)
141 # (use os.sep to make this portable across OSes)
142 r'\W' : '${os.getcwd().split("%s")[-1]}' % os.sep,
142 r'\W' : '${os.getcwd().split("%s")[-1]}' % os.sep,
143 # These X<N> are an extension to the normal bash prompts. They return
143 # These X<N> are an extension to the normal bash prompts. They return
144 # N terms of the path, after replacing $HOME with '~'
144 # N terms of the path, after replacing $HOME with '~'
145 r'\X0': '${os.getcwd().replace("%s","~")}' % HOME,
145 r'\X0': '${os.getcwd().replace("%s","~")}' % HOME,
146 r'\X1': '${self.cwd_filt(1)}',
146 r'\X1': '${self.cwd_filt(1)}',
147 r'\X2': '${self.cwd_filt(2)}',
147 r'\X2': '${self.cwd_filt(2)}',
148 r'\X3': '${self.cwd_filt(3)}',
148 r'\X3': '${self.cwd_filt(3)}',
149 r'\X4': '${self.cwd_filt(4)}',
149 r'\X4': '${self.cwd_filt(4)}',
150 r'\X5': '${self.cwd_filt(5)}',
150 r'\X5': '${self.cwd_filt(5)}',
151 # Y<N> are similar to X<N>, but they show '~' if it's the directory
151 # Y<N> are similar to X<N>, but they show '~' if it's the directory
152 # N+1 in the list. Somewhat like %cN in tcsh.
152 # N+1 in the list. Somewhat like %cN in tcsh.
153 r'\Y0': '${self.cwd_filt2(0)}',
153 r'\Y0': '${self.cwd_filt2(0)}',
154 r'\Y1': '${self.cwd_filt2(1)}',
154 r'\Y1': '${self.cwd_filt2(1)}',
155 r'\Y2': '${self.cwd_filt2(2)}',
155 r'\Y2': '${self.cwd_filt2(2)}',
156 r'\Y3': '${self.cwd_filt2(3)}',
156 r'\Y3': '${self.cwd_filt2(3)}',
157 r'\Y4': '${self.cwd_filt2(4)}',
157 r'\Y4': '${self.cwd_filt2(4)}',
158 r'\Y5': '${self.cwd_filt2(5)}',
158 r'\Y5': '${self.cwd_filt2(5)}',
159 # Hostname up to first .
159 # Hostname up to first .
160 r'\h': HOSTNAME_SHORT,
160 r'\h': HOSTNAME_SHORT,
161 # Full hostname
161 # Full hostname
162 r'\H': HOSTNAME,
162 r'\H': HOSTNAME,
163 # Username of current user
163 # Username of current user
164 r'\u': USER,
164 r'\u': USER,
165 # Escaped '\'
165 # Escaped '\'
166 '\\\\': '\\',
166 '\\\\': '\\',
167 # Newline
167 # Newline
168 r'\n': '\n',
168 r'\n': '\n',
169 # Carriage return
169 # Carriage return
170 r'\r': '\r',
170 r'\r': '\r',
171 # Release version
171 # Release version
172 r'\v': Release.version,
172 r'\v': Release.version,
173 # Root symbol ($ or #)
173 # Root symbol ($ or #)
174 r'\$': ROOT_SYMBOL,
174 r'\$': ROOT_SYMBOL,
175 }
175 }
176
176
177 # A copy of the prompt_specials dictionary but with all color escapes removed,
177 # A copy of the prompt_specials dictionary but with all color escapes removed,
178 # so we can correctly compute the prompt length for the auto_rewrite method.
178 # so we can correctly compute the prompt length for the auto_rewrite method.
179 prompt_specials_nocolor = prompt_specials_color.copy()
179 prompt_specials_nocolor = prompt_specials_color.copy()
180 prompt_specials_nocolor['%n'] = '${self.cache.prompt_count}'
180 prompt_specials_nocolor['%n'] = '${self.cache.prompt_count}'
181 prompt_specials_nocolor[r'\#'] = '${self.cache.prompt_count}'
181 prompt_specials_nocolor[r'\#'] = '${self.cache.prompt_count}'
182
182
183 # Add in all the InputTermColors color escapes as valid prompt characters.
183 # Add in all the InputTermColors color escapes as valid prompt characters.
184 # They all get added as \\C_COLORNAME, so that we don't have any conflicts
184 # They all get added as \\C_COLORNAME, so that we don't have any conflicts
185 # with a color name which may begin with a letter used by any other of the
185 # with a color name which may begin with a letter used by any other of the
186 # allowed specials. This of course means that \\C will never be allowed for
186 # allowed specials. This of course means that \\C will never be allowed for
187 # anything else.
187 # anything else.
188 input_colors = ColorANSI.InputTermColors
188 input_colors = coloransi.InputTermColors
189 for _color in dir(input_colors):
189 for _color in dir(input_colors):
190 if _color[0] != '_':
190 if _color[0] != '_':
191 c_name = r'\C_'+_color
191 c_name = r'\C_'+_color
192 prompt_specials_color[c_name] = getattr(input_colors,_color)
192 prompt_specials_color[c_name] = getattr(input_colors,_color)
193 prompt_specials_nocolor[c_name] = ''
193 prompt_specials_nocolor[c_name] = ''
194
194
195 # we default to no color for safety. Note that prompt_specials is a global
195 # we default to no color for safety. Note that prompt_specials is a global
196 # variable used by all prompt objects.
196 # variable used by all prompt objects.
197 prompt_specials = prompt_specials_nocolor
197 prompt_specials = prompt_specials_nocolor
198
198
199 #-----------------------------------------------------------------------------
199 #-----------------------------------------------------------------------------
200 def str_safe(arg):
200 def str_safe(arg):
201 """Convert to a string, without ever raising an exception.
201 """Convert to a string, without ever raising an exception.
202
202
203 If str(arg) fails, <ERROR: ... > is returned, where ... is the exception
203 If str(arg) fails, <ERROR: ... > is returned, where ... is the exception
204 error message."""
204 error message."""
205
205
206 try:
206 try:
207 out = str(arg)
207 out = str(arg)
208 except UnicodeError:
208 except UnicodeError:
209 try:
209 try:
210 out = arg.encode('utf_8','replace')
210 out = arg.encode('utf_8','replace')
211 except Exception,msg:
211 except Exception,msg:
212 # let's keep this little duplication here, so that the most common
212 # let's keep this little duplication here, so that the most common
213 # case doesn't suffer from a double try wrapping.
213 # case doesn't suffer from a double try wrapping.
214 out = '<ERROR: %s>' % msg
214 out = '<ERROR: %s>' % msg
215 except Exception,msg:
215 except Exception,msg:
216 out = '<ERROR: %s>' % msg
216 out = '<ERROR: %s>' % msg
217 return out
217 return out
218
218
219 class BasePrompt(object):
219 class BasePrompt(object):
220 """Interactive prompt similar to Mathematica's."""
220 """Interactive prompt similar to Mathematica's."""
221
221
222 def _get_p_template(self):
222 def _get_p_template(self):
223 return self._p_template
223 return self._p_template
224
224
225 def _set_p_template(self,val):
225 def _set_p_template(self,val):
226 self._p_template = val
226 self._p_template = val
227 self.set_p_str()
227 self.set_p_str()
228
228
229 p_template = property(_get_p_template,_set_p_template,
229 p_template = property(_get_p_template,_set_p_template,
230 doc='Template for prompt string creation')
230 doc='Template for prompt string creation')
231
231
232 def __init__(self,cache,sep,prompt,pad_left=False):
232 def __init__(self,cache,sep,prompt,pad_left=False):
233
233
234 # Hack: we access information about the primary prompt through the
234 # Hack: we access information about the primary prompt through the
235 # cache argument. We need this, because we want the secondary prompt
235 # cache argument. We need this, because we want the secondary prompt
236 # to be aligned with the primary one. Color table info is also shared
236 # to be aligned with the primary one. Color table info is also shared
237 # by all prompt classes through the cache. Nice OO spaghetti code!
237 # by all prompt classes through the cache. Nice OO spaghetti code!
238 self.cache = cache
238 self.cache = cache
239 self.sep = sep
239 self.sep = sep
240
240
241 # regexp to count the number of spaces at the end of a prompt
241 # regexp to count the number of spaces at the end of a prompt
242 # expression, useful for prompt auto-rewriting
242 # expression, useful for prompt auto-rewriting
243 self.rspace = re.compile(r'(\s*)$')
243 self.rspace = re.compile(r'(\s*)$')
244 # Flag to left-pad prompt strings to match the length of the primary
244 # Flag to left-pad prompt strings to match the length of the primary
245 # prompt
245 # prompt
246 self.pad_left = pad_left
246 self.pad_left = pad_left
247
247
248 # Set template to create each actual prompt (where numbers change).
248 # Set template to create each actual prompt (where numbers change).
249 # Use a property
249 # Use a property
250 self.p_template = prompt
250 self.p_template = prompt
251 self.set_p_str()
251 self.set_p_str()
252
252
253 def set_p_str(self):
253 def set_p_str(self):
254 """ Set the interpolating prompt strings.
254 """ Set the interpolating prompt strings.
255
255
256 This must be called every time the color settings change, because the
256 This must be called every time the color settings change, because the
257 prompt_specials global may have changed."""
257 prompt_specials global may have changed."""
258
258
259 import os,time # needed in locals for prompt string handling
259 import os,time # needed in locals for prompt string handling
260 loc = locals()
260 loc = locals()
261 try:
261 try:
262 self.p_str = ItplNS('%s%s%s' %
262 self.p_str = ItplNS('%s%s%s' %
263 ('${self.sep}${self.col_p}',
263 ('${self.sep}${self.col_p}',
264 multiple_replace(prompt_specials, self.p_template),
264 multiple_replace(prompt_specials, self.p_template),
265 '${self.col_norm}'),self.cache.user_ns,loc)
265 '${self.col_norm}'),self.cache.user_ns,loc)
266
266
267 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
267 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
268 self.p_template),
268 self.p_template),
269 self.cache.user_ns,loc)
269 self.cache.user_ns,loc)
270 except:
270 except:
271 print "Illegal prompt template (check $ usage!):",self.p_template
271 print "Illegal prompt template (check $ usage!):",self.p_template
272 self.p_str = self.p_template
272 self.p_str = self.p_template
273 self.p_str_nocolor = self.p_template
273 self.p_str_nocolor = self.p_template
274
274
275 def write(self,msg): # dbg
275 def write(self,msg): # dbg
276 sys.stdout.write(msg)
276 sys.stdout.write(msg)
277 return ''
277 return ''
278
278
279 def __str__(self):
279 def __str__(self):
280 """Return a string form of the prompt.
280 """Return a string form of the prompt.
281
281
282 This for is useful for continuation and output prompts, since it is
282 This for is useful for continuation and output prompts, since it is
283 left-padded to match lengths with the primary one (if the
283 left-padded to match lengths with the primary one (if the
284 self.pad_left attribute is set)."""
284 self.pad_left attribute is set)."""
285
285
286 out_str = str_safe(self.p_str)
286 out_str = str_safe(self.p_str)
287 if self.pad_left:
287 if self.pad_left:
288 # We must find the amount of padding required to match lengths,
288 # We must find the amount of padding required to match lengths,
289 # taking the color escapes (which are invisible on-screen) into
289 # taking the color escapes (which are invisible on-screen) into
290 # account.
290 # account.
291 esc_pad = len(out_str) - len(str_safe(self.p_str_nocolor))
291 esc_pad = len(out_str) - len(str_safe(self.p_str_nocolor))
292 format = '%%%ss' % (len(str(self.cache.last_prompt))+esc_pad)
292 format = '%%%ss' % (len(str(self.cache.last_prompt))+esc_pad)
293 return format % out_str
293 return format % out_str
294 else:
294 else:
295 return out_str
295 return out_str
296
296
297 # these path filters are put in as methods so that we can control the
297 # these path filters are put in as methods so that we can control the
298 # namespace where the prompt strings get evaluated
298 # namespace where the prompt strings get evaluated
299 def cwd_filt(self,depth):
299 def cwd_filt(self,depth):
300 """Return the last depth elements of the current working directory.
300 """Return the last depth elements of the current working directory.
301
301
302 $HOME is always replaced with '~'.
302 $HOME is always replaced with '~'.
303 If depth==0, the full path is returned."""
303 If depth==0, the full path is returned."""
304
304
305 cwd = os.getcwd().replace(HOME,"~")
305 cwd = os.getcwd().replace(HOME,"~")
306 out = os.sep.join(cwd.split(os.sep)[-depth:])
306 out = os.sep.join(cwd.split(os.sep)[-depth:])
307 if out:
307 if out:
308 return out
308 return out
309 else:
309 else:
310 return os.sep
310 return os.sep
311
311
312 def cwd_filt2(self,depth):
312 def cwd_filt2(self,depth):
313 """Return the last depth elements of the current working directory.
313 """Return the last depth elements of the current working directory.
314
314
315 $HOME is always replaced with '~'.
315 $HOME is always replaced with '~'.
316 If depth==0, the full path is returned."""
316 If depth==0, the full path is returned."""
317
317
318 full_cwd = os.getcwd()
318 full_cwd = os.getcwd()
319 cwd = full_cwd.replace(HOME,"~").split(os.sep)
319 cwd = full_cwd.replace(HOME,"~").split(os.sep)
320 if '~' in cwd and len(cwd) == depth+1:
320 if '~' in cwd and len(cwd) == depth+1:
321 depth += 1
321 depth += 1
322 drivepart = ''
322 drivepart = ''
323 if sys.platform == 'win32' and len(cwd) > depth:
323 if sys.platform == 'win32' and len(cwd) > depth:
324 drivepart = os.path.splitdrive(full_cwd)[0]
324 drivepart = os.path.splitdrive(full_cwd)[0]
325 out = drivepart + '/'.join(cwd[-depth:])
325 out = drivepart + '/'.join(cwd[-depth:])
326
326
327 if out:
327 if out:
328 return out
328 return out
329 else:
329 else:
330 return os.sep
330 return os.sep
331
331
332 def __nonzero__(self):
332 def __nonzero__(self):
333 """Implement boolean behavior.
333 """Implement boolean behavior.
334
334
335 Checks whether the p_str attribute is non-empty"""
335 Checks whether the p_str attribute is non-empty"""
336
336
337 return bool(self.p_template)
337 return bool(self.p_template)
338
338
339 class Prompt1(BasePrompt):
339 class Prompt1(BasePrompt):
340 """Input interactive prompt similar to Mathematica's."""
340 """Input interactive prompt similar to Mathematica's."""
341
341
342 def __init__(self,cache,sep='\n',prompt='In [\\#]: ',pad_left=True):
342 def __init__(self,cache,sep='\n',prompt='In [\\#]: ',pad_left=True):
343 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
343 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
344
344
345 def set_colors(self):
345 def set_colors(self):
346 self.set_p_str()
346 self.set_p_str()
347 Colors = self.cache.color_table.active_colors # shorthand
347 Colors = self.cache.color_table.active_colors # shorthand
348 self.col_p = Colors.in_prompt
348 self.col_p = Colors.in_prompt
349 self.col_num = Colors.in_number
349 self.col_num = Colors.in_number
350 self.col_norm = Colors.in_normal
350 self.col_norm = Colors.in_normal
351 # We need a non-input version of these escapes for the '--->'
351 # We need a non-input version of these escapes for the '--->'
352 # auto-call prompts used in the auto_rewrite() method.
352 # auto-call prompts used in the auto_rewrite() method.
353 self.col_p_ni = self.col_p.replace('\001','').replace('\002','')
353 self.col_p_ni = self.col_p.replace('\001','').replace('\002','')
354 self.col_norm_ni = Colors.normal
354 self.col_norm_ni = Colors.normal
355
355
356 def __str__(self):
356 def __str__(self):
357 self.cache.prompt_count += 1
357 self.cache.prompt_count += 1
358 self.cache.last_prompt = str_safe(self.p_str_nocolor).split('\n')[-1]
358 self.cache.last_prompt = str_safe(self.p_str_nocolor).split('\n')[-1]
359 return str_safe(self.p_str)
359 return str_safe(self.p_str)
360
360
361 def auto_rewrite(self):
361 def auto_rewrite(self):
362 """Print a string of the form '--->' which lines up with the previous
362 """Print a string of the form '--->' which lines up with the previous
363 input string. Useful for systems which re-write the user input when
363 input string. Useful for systems which re-write the user input when
364 handling automatically special syntaxes."""
364 handling automatically special syntaxes."""
365
365
366 curr = str(self.cache.last_prompt)
366 curr = str(self.cache.last_prompt)
367 nrspaces = len(self.rspace.search(curr).group())
367 nrspaces = len(self.rspace.search(curr).group())
368 return '%s%s>%s%s' % (self.col_p_ni,'-'*(len(curr)-nrspaces-1),
368 return '%s%s>%s%s' % (self.col_p_ni,'-'*(len(curr)-nrspaces-1),
369 ' '*nrspaces,self.col_norm_ni)
369 ' '*nrspaces,self.col_norm_ni)
370
370
371 class PromptOut(BasePrompt):
371 class PromptOut(BasePrompt):
372 """Output interactive prompt similar to Mathematica's."""
372 """Output interactive prompt similar to Mathematica's."""
373
373
374 def __init__(self,cache,sep='',prompt='Out[\\#]: ',pad_left=True):
374 def __init__(self,cache,sep='',prompt='Out[\\#]: ',pad_left=True):
375 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
375 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
376 if not self.p_template:
376 if not self.p_template:
377 self.__str__ = lambda: ''
377 self.__str__ = lambda: ''
378
378
379 def set_colors(self):
379 def set_colors(self):
380 self.set_p_str()
380 self.set_p_str()
381 Colors = self.cache.color_table.active_colors # shorthand
381 Colors = self.cache.color_table.active_colors # shorthand
382 self.col_p = Colors.out_prompt
382 self.col_p = Colors.out_prompt
383 self.col_num = Colors.out_number
383 self.col_num = Colors.out_number
384 self.col_norm = Colors.normal
384 self.col_norm = Colors.normal
385
385
386 class Prompt2(BasePrompt):
386 class Prompt2(BasePrompt):
387 """Interactive continuation prompt."""
387 """Interactive continuation prompt."""
388
388
389 def __init__(self,cache,prompt=' .\\D.: ',pad_left=True):
389 def __init__(self,cache,prompt=' .\\D.: ',pad_left=True):
390 self.cache = cache
390 self.cache = cache
391 self.p_template = prompt
391 self.p_template = prompt
392 self.pad_left = pad_left
392 self.pad_left = pad_left
393 self.set_p_str()
393 self.set_p_str()
394
394
395 def set_p_str(self):
395 def set_p_str(self):
396 import os,time # needed in locals for prompt string handling
396 import os,time # needed in locals for prompt string handling
397 loc = locals()
397 loc = locals()
398 self.p_str = ItplNS('%s%s%s' %
398 self.p_str = ItplNS('%s%s%s' %
399 ('${self.col_p2}',
399 ('${self.col_p2}',
400 multiple_replace(prompt_specials, self.p_template),
400 multiple_replace(prompt_specials, self.p_template),
401 '$self.col_norm'),
401 '$self.col_norm'),
402 self.cache.user_ns,loc)
402 self.cache.user_ns,loc)
403 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
403 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
404 self.p_template),
404 self.p_template),
405 self.cache.user_ns,loc)
405 self.cache.user_ns,loc)
406
406
407 def set_colors(self):
407 def set_colors(self):
408 self.set_p_str()
408 self.set_p_str()
409 Colors = self.cache.color_table.active_colors
409 Colors = self.cache.color_table.active_colors
410 self.col_p2 = Colors.in_prompt2
410 self.col_p2 = Colors.in_prompt2
411 self.col_norm = Colors.in_normal
411 self.col_norm = Colors.in_normal
412 # FIXME (2004-06-16) HACK: prevent crashes for users who haven't
412 # FIXME (2004-06-16) HACK: prevent crashes for users who haven't
413 # updated their prompt_in2 definitions. Remove eventually.
413 # updated their prompt_in2 definitions. Remove eventually.
414 self.col_p = Colors.out_prompt
414 self.col_p = Colors.out_prompt
415 self.col_num = Colors.out_number
415 self.col_num = Colors.out_number
416
416
417
417
418 #-----------------------------------------------------------------------------
418 #-----------------------------------------------------------------------------
419 class CachedOutput:
419 class CachedOutput:
420 """Class for printing output from calculations while keeping a cache of
420 """Class for printing output from calculations while keeping a cache of
421 reults. It dynamically creates global variables prefixed with _ which
421 reults. It dynamically creates global variables prefixed with _ which
422 contain these results.
422 contain these results.
423
423
424 Meant to be used as a sys.displayhook replacement, providing numbered
424 Meant to be used as a sys.displayhook replacement, providing numbered
425 prompts and cache services.
425 prompts and cache services.
426
426
427 Initialize with initial and final values for cache counter (this defines
427 Initialize with initial and final values for cache counter (this defines
428 the maximum size of the cache."""
428 the maximum size of the cache."""
429
429
430 def __init__(self,shell,cache_size,Pprint,
430 def __init__(self,shell,cache_size,Pprint,
431 colors='NoColor',input_sep='\n',
431 colors='NoColor',input_sep='\n',
432 output_sep='\n',output_sep2='',
432 output_sep='\n',output_sep2='',
433 ps1 = None, ps2 = None,ps_out = None,pad_left=True):
433 ps1 = None, ps2 = None,ps_out = None,pad_left=True):
434
434
435 cache_size_min = 3
435 cache_size_min = 3
436 if cache_size <= 0:
436 if cache_size <= 0:
437 self.do_full_cache = 0
437 self.do_full_cache = 0
438 cache_size = 0
438 cache_size = 0
439 elif cache_size < cache_size_min:
439 elif cache_size < cache_size_min:
440 self.do_full_cache = 0
440 self.do_full_cache = 0
441 cache_size = 0
441 cache_size = 0
442 warn('caching was disabled (min value for cache size is %s).' %
442 warn('caching was disabled (min value for cache size is %s).' %
443 cache_size_min,level=3)
443 cache_size_min,level=3)
444 else:
444 else:
445 self.do_full_cache = 1
445 self.do_full_cache = 1
446
446
447 self.cache_size = cache_size
447 self.cache_size = cache_size
448 self.input_sep = input_sep
448 self.input_sep = input_sep
449
449
450 # we need a reference to the user-level namespace
450 # we need a reference to the user-level namespace
451 self.shell = shell
451 self.shell = shell
452 self.user_ns = shell.user_ns
452 self.user_ns = shell.user_ns
453 # and to the user's input
453 # and to the user's input
454 self.input_hist = shell.input_hist
454 self.input_hist = shell.input_hist
455 # and to the user's logger, for logging output
455 # and to the user's logger, for logging output
456 self.logger = shell.logger
456 self.logger = shell.logger
457
457
458 # Set input prompt strings and colors
458 # Set input prompt strings and colors
459 if cache_size == 0:
459 if cache_size == 0:
460 if ps1.find('%n') > -1 or ps1.find(r'\#') > -1 \
460 if ps1.find('%n') > -1 or ps1.find(r'\#') > -1 \
461 or ps1.find(r'\N') > -1:
461 or ps1.find(r'\N') > -1:
462 ps1 = '>>> '
462 ps1 = '>>> '
463 if ps2.find('%n') > -1 or ps2.find(r'\#') > -1 \
463 if ps2.find('%n') > -1 or ps2.find(r'\#') > -1 \
464 or ps2.find(r'\N') > -1:
464 or ps2.find(r'\N') > -1:
465 ps2 = '... '
465 ps2 = '... '
466 self.ps1_str = self._set_prompt_str(ps1,'In [\\#]: ','>>> ')
466 self.ps1_str = self._set_prompt_str(ps1,'In [\\#]: ','>>> ')
467 self.ps2_str = self._set_prompt_str(ps2,' .\\D.: ','... ')
467 self.ps2_str = self._set_prompt_str(ps2,' .\\D.: ','... ')
468 self.ps_out_str = self._set_prompt_str(ps_out,'Out[\\#]: ','')
468 self.ps_out_str = self._set_prompt_str(ps_out,'Out[\\#]: ','')
469
469
470 self.color_table = PromptColors
470 self.color_table = PromptColors
471 self.prompt1 = Prompt1(self,sep=input_sep,prompt=self.ps1_str,
471 self.prompt1 = Prompt1(self,sep=input_sep,prompt=self.ps1_str,
472 pad_left=pad_left)
472 pad_left=pad_left)
473 self.prompt2 = Prompt2(self,prompt=self.ps2_str,pad_left=pad_left)
473 self.prompt2 = Prompt2(self,prompt=self.ps2_str,pad_left=pad_left)
474 self.prompt_out = PromptOut(self,sep='',prompt=self.ps_out_str,
474 self.prompt_out = PromptOut(self,sep='',prompt=self.ps_out_str,
475 pad_left=pad_left)
475 pad_left=pad_left)
476 self.set_colors(colors)
476 self.set_colors(colors)
477
477
478 # other more normal stuff
478 # other more normal stuff
479 # b/c each call to the In[] prompt raises it by 1, even the first.
479 # b/c each call to the In[] prompt raises it by 1, even the first.
480 self.prompt_count = 0
480 self.prompt_count = 0
481 # Store the last prompt string each time, we need it for aligning
481 # Store the last prompt string each time, we need it for aligning
482 # continuation and auto-rewrite prompts
482 # continuation and auto-rewrite prompts
483 self.last_prompt = ''
483 self.last_prompt = ''
484 self.Pprint = Pprint
484 self.Pprint = Pprint
485 self.output_sep = output_sep
485 self.output_sep = output_sep
486 self.output_sep2 = output_sep2
486 self.output_sep2 = output_sep2
487 self._,self.__,self.___ = '','',''
487 self._,self.__,self.___ = '','',''
488 self.pprint_types = map(type,[(),[],{}])
488 self.pprint_types = map(type,[(),[],{}])
489
489
490 # these are deliberately global:
490 # these are deliberately global:
491 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
491 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
492 self.user_ns.update(to_user_ns)
492 self.user_ns.update(to_user_ns)
493
493
494 def _set_prompt_str(self,p_str,cache_def,no_cache_def):
494 def _set_prompt_str(self,p_str,cache_def,no_cache_def):
495 if p_str is None:
495 if p_str is None:
496 if self.do_full_cache:
496 if self.do_full_cache:
497 return cache_def
497 return cache_def
498 else:
498 else:
499 return no_cache_def
499 return no_cache_def
500 else:
500 else:
501 return p_str
501 return p_str
502
502
503 def set_colors(self,colors):
503 def set_colors(self,colors):
504 """Set the active color scheme and configure colors for the three
504 """Set the active color scheme and configure colors for the three
505 prompt subsystems."""
505 prompt subsystems."""
506
506
507 # FIXME: the prompt_specials global should be gobbled inside this
507 # FIXME: the prompt_specials global should be gobbled inside this
508 # class instead. Do it when cleaning up the whole 3-prompt system.
508 # class instead. Do it when cleaning up the whole 3-prompt system.
509 global prompt_specials
509 global prompt_specials
510 if colors.lower()=='nocolor':
510 if colors.lower()=='nocolor':
511 prompt_specials = prompt_specials_nocolor
511 prompt_specials = prompt_specials_nocolor
512 else:
512 else:
513 prompt_specials = prompt_specials_color
513 prompt_specials = prompt_specials_color
514
514
515 self.color_table.set_active_scheme(colors)
515 self.color_table.set_active_scheme(colors)
516 self.prompt1.set_colors()
516 self.prompt1.set_colors()
517 self.prompt2.set_colors()
517 self.prompt2.set_colors()
518 self.prompt_out.set_colors()
518 self.prompt_out.set_colors()
519
519
520 def __call__(self,arg=None):
520 def __call__(self,arg=None):
521 """Printing with history cache management.
521 """Printing with history cache management.
522
522
523 This is invoked everytime the interpreter needs to print, and is
523 This is invoked everytime the interpreter needs to print, and is
524 activated by setting the variable sys.displayhook to it."""
524 activated by setting the variable sys.displayhook to it."""
525
525
526 # If something injected a '_' variable in __builtin__, delete
526 # If something injected a '_' variable in __builtin__, delete
527 # ipython's automatic one so we don't clobber that. gettext() in
527 # ipython's automatic one so we don't clobber that. gettext() in
528 # particular uses _, so we need to stay away from it.
528 # particular uses _, so we need to stay away from it.
529 if '_' in __builtin__.__dict__:
529 if '_' in __builtin__.__dict__:
530 try:
530 try:
531 del self.user_ns['_']
531 del self.user_ns['_']
532 except KeyError:
532 except KeyError:
533 pass
533 pass
534 if arg is not None:
534 if arg is not None:
535 cout_write = Term.cout.write # fast lookup
535 cout_write = Term.cout.write # fast lookup
536 # first handle the cache and counters
536 # first handle the cache and counters
537
537
538 # do not print output if input ends in ';'
538 # do not print output if input ends in ';'
539 try:
539 try:
540 if self.input_hist[self.prompt_count].endswith(';\n'):
540 if self.input_hist[self.prompt_count].endswith(';\n'):
541 return
541 return
542 except IndexError:
542 except IndexError:
543 # some uses of ipshellembed may fail here
543 # some uses of ipshellembed may fail here
544 pass
544 pass
545 # don't use print, puts an extra space
545 # don't use print, puts an extra space
546 cout_write(self.output_sep)
546 cout_write(self.output_sep)
547 outprompt = self.shell.hooks.generate_output_prompt()
547 outprompt = self.shell.hooks.generate_output_prompt()
548 if self.do_full_cache:
548 if self.do_full_cache:
549 cout_write(outprompt)
549 cout_write(outprompt)
550
550
551 # and now call a possibly user-defined print mechanism
551 # and now call a possibly user-defined print mechanism
552 manipulated_val = self.display(arg)
552 manipulated_val = self.display(arg)
553
553
554 # user display hooks can change the variable to be stored in
554 # user display hooks can change the variable to be stored in
555 # output history
555 # output history
556
556
557 if manipulated_val is not None:
557 if manipulated_val is not None:
558 arg = manipulated_val
558 arg = manipulated_val
559
559
560 # avoid recursive reference when displaying _oh/Out
560 # avoid recursive reference when displaying _oh/Out
561 if arg is not self.user_ns['_oh']:
561 if arg is not self.user_ns['_oh']:
562 self.update(arg)
562 self.update(arg)
563
563
564 if self.logger.log_output:
564 if self.logger.log_output:
565 self.logger.log_write(repr(arg),'output')
565 self.logger.log_write(repr(arg),'output')
566 cout_write(self.output_sep2)
566 cout_write(self.output_sep2)
567 Term.cout.flush()
567 Term.cout.flush()
568
568
569 def _display(self,arg):
569 def _display(self,arg):
570 """Default printer method, uses pprint.
570 """Default printer method, uses pprint.
571
571
572 Do ip.set_hook("result_display", my_displayhook) for custom result
572 Do ip.set_hook("result_display", my_displayhook) for custom result
573 display, e.g. when your own objects need special formatting.
573 display, e.g. when your own objects need special formatting.
574 """
574 """
575 try:
575 try:
576 return IPython.generics.result_display(arg)
576 return IPython.generics.result_display(arg)
577 except TryNext:
577 except TryNext:
578 return self.shell.hooks.result_display(arg)
578 return self.shell.hooks.result_display(arg)
579
579
580 # Assign the default display method:
580 # Assign the default display method:
581 display = _display
581 display = _display
582
582
583 def update(self,arg):
583 def update(self,arg):
584 #print '***cache_count', self.cache_count # dbg
584 #print '***cache_count', self.cache_count # dbg
585 if len(self.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
585 if len(self.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
586 warn('Output cache limit (currently '+
586 warn('Output cache limit (currently '+
587 `self.cache_size`+' entries) hit.\n'
587 `self.cache_size`+' entries) hit.\n'
588 'Flushing cache and resetting history counter...\n'
588 'Flushing cache and resetting history counter...\n'
589 'The only history variables available will be _,__,___ and _1\n'
589 'The only history variables available will be _,__,___ and _1\n'
590 'with the current result.')
590 'with the current result.')
591
591
592 self.flush()
592 self.flush()
593 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
593 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
594 # we cause buggy behavior for things like gettext).
594 # we cause buggy behavior for things like gettext).
595 if '_' not in __builtin__.__dict__:
595 if '_' not in __builtin__.__dict__:
596 self.___ = self.__
596 self.___ = self.__
597 self.__ = self._
597 self.__ = self._
598 self._ = arg
598 self._ = arg
599 self.user_ns.update({'_':self._,'__':self.__,'___':self.___})
599 self.user_ns.update({'_':self._,'__':self.__,'___':self.___})
600
600
601 # hackish access to top-level namespace to create _1,_2... dynamically
601 # hackish access to top-level namespace to create _1,_2... dynamically
602 to_main = {}
602 to_main = {}
603 if self.do_full_cache:
603 if self.do_full_cache:
604 new_result = '_'+`self.prompt_count`
604 new_result = '_'+`self.prompt_count`
605 to_main[new_result] = arg
605 to_main[new_result] = arg
606 self.user_ns.update(to_main)
606 self.user_ns.update(to_main)
607 self.user_ns['_oh'][self.prompt_count] = arg
607 self.user_ns['_oh'][self.prompt_count] = arg
608
608
609 def flush(self):
609 def flush(self):
610 if not self.do_full_cache:
610 if not self.do_full_cache:
611 raise ValueError,"You shouldn't have reached the cache flush "\
611 raise ValueError,"You shouldn't have reached the cache flush "\
612 "if full caching is not enabled!"
612 "if full caching is not enabled!"
613 # delete auto-generated vars from global namespace
613 # delete auto-generated vars from global namespace
614
614
615 for n in range(1,self.prompt_count + 1):
615 for n in range(1,self.prompt_count + 1):
616 key = '_'+`n`
616 key = '_'+`n`
617 try:
617 try:
618 del self.user_ns[key]
618 del self.user_ns[key]
619 except: pass
619 except: pass
620 self.user_ns['_oh'].clear()
620 self.user_ns['_oh'].clear()
621
621
622 if '_' not in __builtin__.__dict__:
622 if '_' not in __builtin__.__dict__:
623 self.user_ns.update({'_':None,'__':None, '___':None})
623 self.user_ns.update({'_':None,'__':None, '___':None})
624 import gc
624 import gc
625 gc.collect() # xxx needed?
625 gc.collect() # xxx needed?
626
626
@@ -1,300 +1,299 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Class and program to colorize python source code for ANSI terminals.
3 Class and program to colorize python source code for ANSI terminals.
4
4
5 Based on an HTML code highlighter by Jurgen Hermann found at:
5 Based on an HTML code highlighter by Jurgen Hermann found at:
6 http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52298
6 http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52298
7
7
8 Modifications by Fernando Perez (fperez@colorado.edu).
8 Modifications by Fernando Perez (fperez@colorado.edu).
9
9
10 Information on the original HTML highlighter follows:
10 Information on the original HTML highlighter follows:
11
11
12 MoinMoin - Python Source Parser
12 MoinMoin - Python Source Parser
13
13
14 Title: Colorize Python source using the built-in tokenizer
14 Title: Colorize Python source using the built-in tokenizer
15
15
16 Submitter: Jurgen Hermann
16 Submitter: Jurgen Hermann
17 Last Updated:2001/04/06
17 Last Updated:2001/04/06
18
18
19 Version no:1.2
19 Version no:1.2
20
20
21 Description:
21 Description:
22
22
23 This code is part of MoinMoin (http://moin.sourceforge.net/) and converts
23 This code is part of MoinMoin (http://moin.sourceforge.net/) and converts
24 Python source code to HTML markup, rendering comments, keywords,
24 Python source code to HTML markup, rendering comments, keywords,
25 operators, numeric and string literals in different colors.
25 operators, numeric and string literals in different colors.
26
26
27 It shows how to use the built-in keyword, token and tokenize modules to
27 It shows how to use the built-in keyword, token and tokenize modules to
28 scan Python source code and re-emit it with no changes to its original
28 scan Python source code and re-emit it with no changes to its original
29 formatting (which is the hard part).
29 formatting (which is the hard part).
30 """
30 """
31
31
32 __all__ = ['ANSICodeColors','Parser']
32 __all__ = ['ANSICodeColors','Parser']
33
33
34 _scheme_default = 'Linux'
34 _scheme_default = 'Linux'
35
35
36 # Imports
36 # Imports
37 import cStringIO
37 import cStringIO
38 import keyword
38 import keyword
39 import os
39 import os
40 import optparse
40 import optparse
41 import string
42 import sys
41 import sys
43 import token
42 import token
44 import tokenize
43 import tokenize
45
44
46 from IPython.ColorANSI import *
45 from IPython.utils.coloransi import *
47
46
48 #############################################################################
47 #############################################################################
49 ### Python Source Parser (does Hilighting)
48 ### Python Source Parser (does Hilighting)
50 #############################################################################
49 #############################################################################
51
50
52 _KEYWORD = token.NT_OFFSET + 1
51 _KEYWORD = token.NT_OFFSET + 1
53 _TEXT = token.NT_OFFSET + 2
52 _TEXT = token.NT_OFFSET + 2
54
53
55 #****************************************************************************
54 #****************************************************************************
56 # Builtin color schemes
55 # Builtin color schemes
57
56
58 Colors = TermColors # just a shorthand
57 Colors = TermColors # just a shorthand
59
58
60 # Build a few color schemes
59 # Build a few color schemes
61 NoColor = ColorScheme(
60 NoColor = ColorScheme(
62 'NoColor',{
61 'NoColor',{
63 token.NUMBER : Colors.NoColor,
62 token.NUMBER : Colors.NoColor,
64 token.OP : Colors.NoColor,
63 token.OP : Colors.NoColor,
65 token.STRING : Colors.NoColor,
64 token.STRING : Colors.NoColor,
66 tokenize.COMMENT : Colors.NoColor,
65 tokenize.COMMENT : Colors.NoColor,
67 token.NAME : Colors.NoColor,
66 token.NAME : Colors.NoColor,
68 token.ERRORTOKEN : Colors.NoColor,
67 token.ERRORTOKEN : Colors.NoColor,
69
68
70 _KEYWORD : Colors.NoColor,
69 _KEYWORD : Colors.NoColor,
71 _TEXT : Colors.NoColor,
70 _TEXT : Colors.NoColor,
72
71
73 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
72 'normal' : Colors.NoColor # color off (usu. Colors.Normal)
74 } )
73 } )
75
74
76 LinuxColors = ColorScheme(
75 LinuxColors = ColorScheme(
77 'Linux',{
76 'Linux',{
78 token.NUMBER : Colors.LightCyan,
77 token.NUMBER : Colors.LightCyan,
79 token.OP : Colors.Yellow,
78 token.OP : Colors.Yellow,
80 token.STRING : Colors.LightBlue,
79 token.STRING : Colors.LightBlue,
81 tokenize.COMMENT : Colors.LightRed,
80 tokenize.COMMENT : Colors.LightRed,
82 token.NAME : Colors.White,
81 token.NAME : Colors.White,
83 token.ERRORTOKEN : Colors.Red,
82 token.ERRORTOKEN : Colors.Red,
84
83
85 _KEYWORD : Colors.LightGreen,
84 _KEYWORD : Colors.LightGreen,
86 _TEXT : Colors.Yellow,
85 _TEXT : Colors.Yellow,
87
86
88 'normal' : Colors.Normal # color off (usu. Colors.Normal)
87 'normal' : Colors.Normal # color off (usu. Colors.Normal)
89 } )
88 } )
90
89
91 LightBGColors = ColorScheme(
90 LightBGColors = ColorScheme(
92 'LightBG',{
91 'LightBG',{
93 token.NUMBER : Colors.Cyan,
92 token.NUMBER : Colors.Cyan,
94 token.OP : Colors.Blue,
93 token.OP : Colors.Blue,
95 token.STRING : Colors.Blue,
94 token.STRING : Colors.Blue,
96 tokenize.COMMENT : Colors.Red,
95 tokenize.COMMENT : Colors.Red,
97 token.NAME : Colors.Black,
96 token.NAME : Colors.Black,
98 token.ERRORTOKEN : Colors.Red,
97 token.ERRORTOKEN : Colors.Red,
99
98
100 _KEYWORD : Colors.Green,
99 _KEYWORD : Colors.Green,
101 _TEXT : Colors.Blue,
100 _TEXT : Colors.Blue,
102
101
103 'normal' : Colors.Normal # color off (usu. Colors.Normal)
102 'normal' : Colors.Normal # color off (usu. Colors.Normal)
104 } )
103 } )
105
104
106 # Build table of color schemes (needed by the parser)
105 # Build table of color schemes (needed by the parser)
107 ANSICodeColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
106 ANSICodeColors = ColorSchemeTable([NoColor,LinuxColors,LightBGColors],
108 _scheme_default)
107 _scheme_default)
109
108
110 class Parser:
109 class Parser:
111 """ Format colored Python source.
110 """ Format colored Python source.
112 """
111 """
113
112
114 def __init__(self, color_table=None,out = sys.stdout):
113 def __init__(self, color_table=None,out = sys.stdout):
115 """ Create a parser with a specified color table and output channel.
114 """ Create a parser with a specified color table and output channel.
116
115
117 Call format() to process code.
116 Call format() to process code.
118 """
117 """
119 self.color_table = color_table and color_table or ANSICodeColors
118 self.color_table = color_table and color_table or ANSICodeColors
120 self.out = out
119 self.out = out
121
120
122 def format(self, raw, out = None, scheme = ''):
121 def format(self, raw, out = None, scheme = ''):
123 return self.format2(raw, out, scheme)[0]
122 return self.format2(raw, out, scheme)[0]
124
123
125 def format2(self, raw, out = None, scheme = ''):
124 def format2(self, raw, out = None, scheme = ''):
126 """ Parse and send the colored source.
125 """ Parse and send the colored source.
127
126
128 If out and scheme are not specified, the defaults (given to
127 If out and scheme are not specified, the defaults (given to
129 constructor) are used.
128 constructor) are used.
130
129
131 out should be a file-type object. Optionally, out can be given as the
130 out should be a file-type object. Optionally, out can be given as the
132 string 'str' and the parser will automatically return the output in a
131 string 'str' and the parser will automatically return the output in a
133 string."""
132 string."""
134
133
135 string_output = 0
134 string_output = 0
136 if out == 'str' or self.out == 'str' or \
135 if out == 'str' or self.out == 'str' or \
137 isinstance(self.out,cStringIO.OutputType):
136 isinstance(self.out,cStringIO.OutputType):
138 # XXX - I don't really like this state handling logic, but at this
137 # XXX - I don't really like this state handling logic, but at this
139 # point I don't want to make major changes, so adding the
138 # point I don't want to make major changes, so adding the
140 # isinstance() check is the simplest I can do to ensure correct
139 # isinstance() check is the simplest I can do to ensure correct
141 # behavior.
140 # behavior.
142 out_old = self.out
141 out_old = self.out
143 self.out = cStringIO.StringIO()
142 self.out = cStringIO.StringIO()
144 string_output = 1
143 string_output = 1
145 elif out is not None:
144 elif out is not None:
146 self.out = out
145 self.out = out
147
146
148 # Fast return of the unmodified input for NoColor scheme
147 # Fast return of the unmodified input for NoColor scheme
149 if scheme == 'NoColor':
148 if scheme == 'NoColor':
150 error = False
149 error = False
151 self.out.write(raw)
150 self.out.write(raw)
152 if string_output:
151 if string_output:
153 return raw,error
152 return raw,error
154 else:
153 else:
155 return None,error
154 return None,error
156
155
157 # local shorthands
156 # local shorthands
158 colors = self.color_table[scheme].colors
157 colors = self.color_table[scheme].colors
159 self.colors = colors # put in object so __call__ sees it
158 self.colors = colors # put in object so __call__ sees it
160
159
161 # Remove trailing whitespace and normalize tabs
160 # Remove trailing whitespace and normalize tabs
162 self.raw = raw.expandtabs().rstrip()
161 self.raw = raw.expandtabs().rstrip()
163
162
164 # store line offsets in self.lines
163 # store line offsets in self.lines
165 self.lines = [0, 0]
164 self.lines = [0, 0]
166 pos = 0
165 pos = 0
167 raw_find = self.raw.find
166 raw_find = self.raw.find
168 lines_append = self.lines.append
167 lines_append = self.lines.append
169 while 1:
168 while 1:
170 pos = raw_find('\n', pos) + 1
169 pos = raw_find('\n', pos) + 1
171 if not pos: break
170 if not pos: break
172 lines_append(pos)
171 lines_append(pos)
173 lines_append(len(self.raw))
172 lines_append(len(self.raw))
174
173
175 # parse the source and write it
174 # parse the source and write it
176 self.pos = 0
175 self.pos = 0
177 text = cStringIO.StringIO(self.raw)
176 text = cStringIO.StringIO(self.raw)
178
177
179 error = False
178 error = False
180 try:
179 try:
181 tokenize.tokenize(text.readline, self)
180 tokenize.tokenize(text.readline, self)
182 except tokenize.TokenError, ex:
181 except tokenize.TokenError, ex:
183 msg = ex[0]
182 msg = ex[0]
184 line = ex[1][0]
183 line = ex[1][0]
185 self.out.write("%s\n\n*** ERROR: %s%s%s\n" %
184 self.out.write("%s\n\n*** ERROR: %s%s%s\n" %
186 (colors[token.ERRORTOKEN],
185 (colors[token.ERRORTOKEN],
187 msg, self.raw[self.lines[line]:],
186 msg, self.raw[self.lines[line]:],
188 colors.normal)
187 colors.normal)
189 )
188 )
190 error = True
189 error = True
191 self.out.write(colors.normal+'\n')
190 self.out.write(colors.normal+'\n')
192 if string_output:
191 if string_output:
193 output = self.out.getvalue()
192 output = self.out.getvalue()
194 self.out = out_old
193 self.out = out_old
195 return (output, error)
194 return (output, error)
196 return (None, error)
195 return (None, error)
197
196
198 def __call__(self, toktype, toktext, (srow,scol), (erow,ecol), line):
197 def __call__(self, toktype, toktext, (srow,scol), (erow,ecol), line):
199 """ Token handler, with syntax highlighting."""
198 """ Token handler, with syntax highlighting."""
200
199
201 # local shorthands
200 # local shorthands
202 colors = self.colors
201 colors = self.colors
203 owrite = self.out.write
202 owrite = self.out.write
204
203
205 # line separator, so this works across platforms
204 # line separator, so this works across platforms
206 linesep = os.linesep
205 linesep = os.linesep
207
206
208 # calculate new positions
207 # calculate new positions
209 oldpos = self.pos
208 oldpos = self.pos
210 newpos = self.lines[srow] + scol
209 newpos = self.lines[srow] + scol
211 self.pos = newpos + len(toktext)
210 self.pos = newpos + len(toktext)
212
211
213 # handle newlines
212 # handle newlines
214 if toktype in [token.NEWLINE, tokenize.NL]:
213 if toktype in [token.NEWLINE, tokenize.NL]:
215 owrite(linesep)
214 owrite(linesep)
216 return
215 return
217
216
218 # send the original whitespace, if needed
217 # send the original whitespace, if needed
219 if newpos > oldpos:
218 if newpos > oldpos:
220 owrite(self.raw[oldpos:newpos])
219 owrite(self.raw[oldpos:newpos])
221
220
222 # skip indenting tokens
221 # skip indenting tokens
223 if toktype in [token.INDENT, token.DEDENT]:
222 if toktype in [token.INDENT, token.DEDENT]:
224 self.pos = newpos
223 self.pos = newpos
225 return
224 return
226
225
227 # map token type to a color group
226 # map token type to a color group
228 if token.LPAR <= toktype and toktype <= token.OP:
227 if token.LPAR <= toktype and toktype <= token.OP:
229 toktype = token.OP
228 toktype = token.OP
230 elif toktype == token.NAME and keyword.iskeyword(toktext):
229 elif toktype == token.NAME and keyword.iskeyword(toktext):
231 toktype = _KEYWORD
230 toktype = _KEYWORD
232 color = colors.get(toktype, colors[_TEXT])
231 color = colors.get(toktype, colors[_TEXT])
233
232
234 #print '<%s>' % toktext, # dbg
233 #print '<%s>' % toktext, # dbg
235
234
236 # Triple quoted strings must be handled carefully so that backtracking
235 # Triple quoted strings must be handled carefully so that backtracking
237 # in pagers works correctly. We need color terminators on _each_ line.
236 # in pagers works correctly. We need color terminators on _each_ line.
238 if linesep in toktext:
237 if linesep in toktext:
239 toktext = toktext.replace(linesep, '%s%s%s' %
238 toktext = toktext.replace(linesep, '%s%s%s' %
240 (colors.normal,linesep,color))
239 (colors.normal,linesep,color))
241
240
242 # send text
241 # send text
243 owrite('%s%s%s' % (color,toktext,colors.normal))
242 owrite('%s%s%s' % (color,toktext,colors.normal))
244
243
245 def main(argv=None):
244 def main(argv=None):
246 """Run as a command-line script: colorize a python file or stdin using ANSI
245 """Run as a command-line script: colorize a python file or stdin using ANSI
247 color escapes and print to stdout.
246 color escapes and print to stdout.
248
247
249 Inputs:
248 Inputs:
250
249
251 - argv(None): a list of strings like sys.argv[1:] giving the command-line
250 - argv(None): a list of strings like sys.argv[1:] giving the command-line
252 arguments. If None, use sys.argv[1:].
251 arguments. If None, use sys.argv[1:].
253 """
252 """
254
253
255 usage_msg = """%prog [options] [filename]
254 usage_msg = """%prog [options] [filename]
256
255
257 Colorize a python file or stdin using ANSI color escapes and print to stdout.
256 Colorize a python file or stdin using ANSI color escapes and print to stdout.
258 If no filename is given, or if filename is -, read standard input."""
257 If no filename is given, or if filename is -, read standard input."""
259
258
260 parser = optparse.OptionParser(usage=usage_msg)
259 parser = optparse.OptionParser(usage=usage_msg)
261 newopt = parser.add_option
260 newopt = parser.add_option
262 newopt('-s','--scheme',metavar='NAME',dest='scheme_name',action='store',
261 newopt('-s','--scheme',metavar='NAME',dest='scheme_name',action='store',
263 choices=['Linux','LightBG','NoColor'],default=_scheme_default,
262 choices=['Linux','LightBG','NoColor'],default=_scheme_default,
264 help="give the color scheme to use. Currently only 'Linux'\
263 help="give the color scheme to use. Currently only 'Linux'\
265 (default) and 'LightBG' and 'NoColor' are implemented (give without\
264 (default) and 'LightBG' and 'NoColor' are implemented (give without\
266 quotes)")
265 quotes)")
267
266
268 opts,args = parser.parse_args(argv)
267 opts,args = parser.parse_args(argv)
269
268
270 if len(args) > 1:
269 if len(args) > 1:
271 parser.error("you must give at most one filename.")
270 parser.error("you must give at most one filename.")
272
271
273 if len(args) == 0:
272 if len(args) == 0:
274 fname = '-' # no filename given; setup to read from stdin
273 fname = '-' # no filename given; setup to read from stdin
275 else:
274 else:
276 fname = args[0]
275 fname = args[0]
277
276
278 if fname == '-':
277 if fname == '-':
279 stream = sys.stdin
278 stream = sys.stdin
280 else:
279 else:
281 stream = file(fname)
280 stream = file(fname)
282
281
283 parser = Parser()
282 parser = Parser()
284
283
285 # we need nested try blocks because pre-2.5 python doesn't support unified
284 # we need nested try blocks because pre-2.5 python doesn't support unified
286 # try-except-finally
285 # try-except-finally
287 try:
286 try:
288 try:
287 try:
289 # write colorized version to stdout
288 # write colorized version to stdout
290 parser.format(stream.read(),scheme=opts.scheme_name)
289 parser.format(stream.read(),scheme=opts.scheme_name)
291 except IOError,msg:
290 except IOError,msg:
292 # if user reads through a pager and quits, don't print traceback
291 # if user reads through a pager and quits, don't print traceback
293 if msg.args != (32,'Broken pipe'):
292 if msg.args != (32,'Broken pipe'):
294 raise
293 raise
295 finally:
294 finally:
296 if stream is not sys.stdin:
295 if stream is not sys.stdin:
297 stream.close() # in case a non-handled exception happened above
296 stream.close() # in case a non-handled exception happened above
298
297
299 if __name__ == "__main__":
298 if __name__ == "__main__":
300 main()
299 main()
@@ -1,72 +1,72 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 IPython -- An enhanced Interactive Python
3 IPython -- An enhanced Interactive Python
4
4
5 One of Python's nicest features is its interactive interpreter. This allows
5 One of Python's nicest features is its interactive interpreter. This allows
6 very fast testing of ideas without the overhead of creating test files as is
6 very fast testing of ideas without the overhead of creating test files as is
7 typical in most programming languages. However, the interpreter supplied with
7 typical in most programming languages. However, the interpreter supplied with
8 the standard Python distribution is fairly primitive (and IDLE isn't really
8 the standard Python distribution is fairly primitive (and IDLE isn't really
9 much better).
9 much better).
10
10
11 IPython tries to:
11 IPython tries to:
12
12
13 i - provide an efficient environment for interactive work in Python
13 i - provide an efficient environment for interactive work in Python
14 programming. It tries to address what we see as shortcomings of the standard
14 programming. It tries to address what we see as shortcomings of the standard
15 Python prompt, and adds many features to make interactive work much more
15 Python prompt, and adds many features to make interactive work much more
16 efficient.
16 efficient.
17
17
18 ii - offer a flexible framework so that it can be used as the base
18 ii - offer a flexible framework so that it can be used as the base
19 environment for other projects and problems where Python can be the
19 environment for other projects and problems where Python can be the
20 underlying language. Specifically scientific environments like Mathematica,
20 underlying language. Specifically scientific environments like Mathematica,
21 IDL and Mathcad inspired its design, but similar ideas can be useful in many
21 IDL and Mathcad inspired its design, but similar ideas can be useful in many
22 fields. Python is a fabulous language for implementing this kind of system
22 fields. Python is a fabulous language for implementing this kind of system
23 (due to its dynamic and introspective features), and with suitable libraries
23 (due to its dynamic and introspective features), and with suitable libraries
24 entire systems could be built leveraging Python's power.
24 entire systems could be built leveraging Python's power.
25
25
26 iii - serve as an embeddable, ready to go interpreter for your own programs.
26 iii - serve as an embeddable, ready to go interpreter for your own programs.
27
27
28 IPython requires Python 2.4 or newer.
28 IPython requires Python 2.4 or newer.
29 """
29 """
30
30
31 #*****************************************************************************
31 #*****************************************************************************
32 # Copyright (C) 2008-2009 The IPython Development Team
32 # Copyright (C) 2008-2009 The IPython Development Team
33 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
33 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
34 #
34 #
35 # Distributed under the terms of the BSD License. The full license is in
35 # Distributed under the terms of the BSD License. The full license is in
36 # the file COPYING, distributed as part of this software.
36 # the file COPYING, distributed as part of this software.
37 #*****************************************************************************
37 #*****************************************************************************
38
38
39 # Enforce proper version requirements
39 # Enforce proper version requirements
40 import sys
40 import sys
41
41
42 if sys.version[0:3] < '2.4':
42 if sys.version[0:3] < '2.4':
43 raise ImportError('Python Version 2.4 or above is required for IPython.')
43 raise ImportError('Python Version 2.4 or above is required for IPython.')
44
44
45 # Make it easy to import extensions - they are always directly on pythonpath.
45 # Make it easy to import extensions - they are always directly on pythonpath.
46 # Therefore, non-IPython modules can be added to Extensions directory
46 # Therefore, non-IPython modules can be added to Extensions directory
47 import os
47 import os
48 sys.path.append(os.path.dirname(__file__) + "/Extensions")
48 sys.path.append(os.path.dirname(__file__) + "/Extensions")
49
49
50 # Define what gets imported with a 'from IPython import *'
50 # Define what gets imported with a 'from IPython import *'
51 __all__ = ['ipapi','generics','ipstruct','Release','Shell']
51 __all__ = ['ipapi','generics','ipstruct','Release','Shell']
52
52
53 # Load __all__ in IPython namespace so that a simple 'import IPython' gives
53 # Load __all__ in IPython namespace so that a simple 'import IPython' gives
54 # access to them via IPython.<name>
54 # access to them via IPython.<name>
55 glob,loc = globals(),locals()
55 glob,loc = globals(),locals()
56 for name in __all__:
56 for name in __all__:
57 #print 'Importing: ',name # dbg
57 #print 'Importing: ',name # dbg
58 __import__(name,glob,loc,[])
58 __import__(name,glob,loc,[])
59
59
60 import Shell
60 import Shell
61
61
62 # Release data
62 # Release data
63 from IPython import Release # do it explicitly so pydoc can see it - pydoc bug
63 from IPython import Release # do it explicitly so pydoc can see it - pydoc bug
64 __author__ = '%s <%s>\n%s <%s>\n%s <%s>' % \
64 __author__ = '%s <%s>\n%s <%s>\n%s <%s>' % \
65 ( Release.authors['Fernando'] + Release.authors['Janko'] + \
65 ( Release.authors['Fernando'] + Release.authors['Janko'] + \
66 Release.authors['Nathan'] )
66 Release.authors['Nathan'] )
67 __license__ = Release.license
67 __license__ = Release.license
68 __version__ = Release.version
68 __version__ = Release.version
69 __revision__ = Release.revision
69 __revision__ = Release.revision
70
70
71 # Namespace cleanup
71 # Namespace cleanup
72 del name,glob,loc
72 del name,glob,loc
@@ -1,137 +1,137 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Color schemes for exception handling code in IPython.
3 Color schemes for exception handling code in IPython.
4 """
4 """
5
5
6 #*****************************************************************************
6 #*****************************************************************************
7 # Copyright (C) 2005-2006 Fernando Perez <fperez@colorado.edu>
7 # Copyright (C) 2005-2006 Fernando Perez <fperez@colorado.edu>
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #*****************************************************************************
11 #*****************************************************************************
12
12
13 #****************************************************************************
13 #****************************************************************************
14 # Required modules
14 # Required modules
15 from IPython.ColorANSI import ColorSchemeTable, TermColors, ColorScheme
15 from IPython.utils.coloransi import ColorSchemeTable, TermColors, ColorScheme
16
16
17 def exception_colors():
17 def exception_colors():
18 """Return a color table with fields for exception reporting.
18 """Return a color table with fields for exception reporting.
19
19
20 The table is an instance of ColorSchemeTable with schemes added for
20 The table is an instance of ColorSchemeTable with schemes added for
21 'Linux', 'LightBG' and 'NoColor' and fields for exception handling filled
21 'Linux', 'LightBG' and 'NoColor' and fields for exception handling filled
22 in.
22 in.
23
23
24 Examples:
24 Examples:
25
25
26 >>> ec = exception_colors()
26 >>> ec = exception_colors()
27 >>> ec.active_scheme_name
27 >>> ec.active_scheme_name
28 ''
28 ''
29 >>> print ec.active_colors
29 >>> print ec.active_colors
30 None
30 None
31
31
32 Now we activate a color scheme:
32 Now we activate a color scheme:
33 >>> ec.set_active_scheme('NoColor')
33 >>> ec.set_active_scheme('NoColor')
34 >>> ec.active_scheme_name
34 >>> ec.active_scheme_name
35 'NoColor'
35 'NoColor'
36 >>> ec.active_colors.keys()
36 >>> ec.active_colors.keys()
37 ['em', 'caret', '__allownew', 'name', 'val', 'vName', 'Normal', 'normalEm',
37 ['em', 'caret', '__allownew', 'name', 'val', 'vName', 'Normal', 'normalEm',
38 'filename', 'linenoEm', 'excName', 'lineno', 'valEm', 'filenameEm',
38 'filename', 'linenoEm', 'excName', 'lineno', 'valEm', 'filenameEm',
39 'nameEm', 'line', 'topline']
39 'nameEm', 'line', 'topline']
40 """
40 """
41
41
42 ex_colors = ColorSchemeTable()
42 ex_colors = ColorSchemeTable()
43
43
44 # Populate it with color schemes
44 # Populate it with color schemes
45 C = TermColors # shorthand and local lookup
45 C = TermColors # shorthand and local lookup
46 ex_colors.add_scheme(ColorScheme(
46 ex_colors.add_scheme(ColorScheme(
47 'NoColor',
47 'NoColor',
48 # The color to be used for the top line
48 # The color to be used for the top line
49 topline = C.NoColor,
49 topline = C.NoColor,
50
50
51 # The colors to be used in the traceback
51 # The colors to be used in the traceback
52 filename = C.NoColor,
52 filename = C.NoColor,
53 lineno = C.NoColor,
53 lineno = C.NoColor,
54 name = C.NoColor,
54 name = C.NoColor,
55 vName = C.NoColor,
55 vName = C.NoColor,
56 val = C.NoColor,
56 val = C.NoColor,
57 em = C.NoColor,
57 em = C.NoColor,
58
58
59 # Emphasized colors for the last frame of the traceback
59 # Emphasized colors for the last frame of the traceback
60 normalEm = C.NoColor,
60 normalEm = C.NoColor,
61 filenameEm = C.NoColor,
61 filenameEm = C.NoColor,
62 linenoEm = C.NoColor,
62 linenoEm = C.NoColor,
63 nameEm = C.NoColor,
63 nameEm = C.NoColor,
64 valEm = C.NoColor,
64 valEm = C.NoColor,
65
65
66 # Colors for printing the exception
66 # Colors for printing the exception
67 excName = C.NoColor,
67 excName = C.NoColor,
68 line = C.NoColor,
68 line = C.NoColor,
69 caret = C.NoColor,
69 caret = C.NoColor,
70 Normal = C.NoColor
70 Normal = C.NoColor
71 ))
71 ))
72
72
73 # make some schemes as instances so we can copy them for modification easily
73 # make some schemes as instances so we can copy them for modification easily
74 ex_colors.add_scheme(ColorScheme(
74 ex_colors.add_scheme(ColorScheme(
75 'Linux',
75 'Linux',
76 # The color to be used for the top line
76 # The color to be used for the top line
77 topline = C.LightRed,
77 topline = C.LightRed,
78
78
79 # The colors to be used in the traceback
79 # The colors to be used in the traceback
80 filename = C.Green,
80 filename = C.Green,
81 lineno = C.Green,
81 lineno = C.Green,
82 name = C.Purple,
82 name = C.Purple,
83 vName = C.Cyan,
83 vName = C.Cyan,
84 val = C.Green,
84 val = C.Green,
85 em = C.LightCyan,
85 em = C.LightCyan,
86
86
87 # Emphasized colors for the last frame of the traceback
87 # Emphasized colors for the last frame of the traceback
88 normalEm = C.LightCyan,
88 normalEm = C.LightCyan,
89 filenameEm = C.LightGreen,
89 filenameEm = C.LightGreen,
90 linenoEm = C.LightGreen,
90 linenoEm = C.LightGreen,
91 nameEm = C.LightPurple,
91 nameEm = C.LightPurple,
92 valEm = C.LightBlue,
92 valEm = C.LightBlue,
93
93
94 # Colors for printing the exception
94 # Colors for printing the exception
95 excName = C.LightRed,
95 excName = C.LightRed,
96 line = C.Yellow,
96 line = C.Yellow,
97 caret = C.White,
97 caret = C.White,
98 Normal = C.Normal
98 Normal = C.Normal
99 ))
99 ))
100
100
101 # For light backgrounds, swap dark/light colors
101 # For light backgrounds, swap dark/light colors
102 ex_colors.add_scheme(ColorScheme(
102 ex_colors.add_scheme(ColorScheme(
103 'LightBG',
103 'LightBG',
104 # The color to be used for the top line
104 # The color to be used for the top line
105 topline = C.Red,
105 topline = C.Red,
106
106
107 # The colors to be used in the traceback
107 # The colors to be used in the traceback
108 filename = C.LightGreen,
108 filename = C.LightGreen,
109 lineno = C.LightGreen,
109 lineno = C.LightGreen,
110 name = C.LightPurple,
110 name = C.LightPurple,
111 vName = C.Cyan,
111 vName = C.Cyan,
112 val = C.LightGreen,
112 val = C.LightGreen,
113 em = C.Cyan,
113 em = C.Cyan,
114
114
115 # Emphasized colors for the last frame of the traceback
115 # Emphasized colors for the last frame of the traceback
116 normalEm = C.Cyan,
116 normalEm = C.Cyan,
117 filenameEm = C.Green,
117 filenameEm = C.Green,
118 linenoEm = C.Green,
118 linenoEm = C.Green,
119 nameEm = C.Purple,
119 nameEm = C.Purple,
120 valEm = C.Blue,
120 valEm = C.Blue,
121
121
122 # Colors for printing the exception
122 # Colors for printing the exception
123 excName = C.Red,
123 excName = C.Red,
124 #line = C.Brown, # brown often is displayed as yellow
124 #line = C.Brown, # brown often is displayed as yellow
125 line = C.Red,
125 line = C.Red,
126 caret = C.Normal,
126 caret = C.Normal,
127 Normal = C.Normal,
127 Normal = C.Normal,
128 ))
128 ))
129
129
130 return ex_colors
130 return ex_colors
131
131
132
132
133 # For backwards compatibility, keep around a single global object. Note that
133 # For backwards compatibility, keep around a single global object. Note that
134 # this should NOT be used, the factory function should be used instead, since
134 # this should NOT be used, the factory function should be used instead, since
135 # these objects are stateful and it's very easy to get strange bugs if any code
135 # these objects are stateful and it's very easy to get strange bugs if any code
136 # modifies the module-level object's state.
136 # modifies the module-level object's state.
137 ExceptionColors = exception_colors()
137 ExceptionColors = exception_colors()
@@ -1,625 +1,625 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 A Wx widget to act as a console and input commands.
3 A Wx widget to act as a console and input commands.
4
4
5 This widget deals with prompts and provides an edit buffer
5 This widget deals with prompts and provides an edit buffer
6 restricted to after the last prompt.
6 restricted to after the last prompt.
7 """
7 """
8
8
9 __docformat__ = "restructuredtext en"
9 __docformat__ = "restructuredtext en"
10
10
11 #-------------------------------------------------------------------------------
11 #-------------------------------------------------------------------------------
12 # Copyright (C) 2008 The IPython Development Team
12 # Copyright (C) 2008 The IPython Development Team
13 #
13 #
14 # Distributed under the terms of the BSD License. The full license is
14 # Distributed under the terms of the BSD License. The full license is
15 # in the file COPYING, distributed as part of this software.
15 # in the file COPYING, distributed as part of this software.
16 #-------------------------------------------------------------------------------
16 #-------------------------------------------------------------------------------
17
17
18 #-------------------------------------------------------------------------------
18 #-------------------------------------------------------------------------------
19 # Imports
19 # Imports
20 #-------------------------------------------------------------------------------
20 #-------------------------------------------------------------------------------
21
21
22 import wx
22 import wx
23 import wx.stc as stc
23 import wx.stc as stc
24
24
25 from wx.py import editwindow
25 from wx.py import editwindow
26 import time
26 import time
27 import sys
27 import sys
28 import string
28 import string
29
29
30 LINESEP = '\n'
30 LINESEP = '\n'
31 if sys.platform == 'win32':
31 if sys.platform == 'win32':
32 LINESEP = '\n\r'
32 LINESEP = '\n\r'
33
33
34 import re
34 import re
35
35
36 # FIXME: Need to provide an API for non user-generated display on the
36 # FIXME: Need to provide an API for non user-generated display on the
37 # screen: this should not be editable by the user.
37 # screen: this should not be editable by the user.
38 #-------------------------------------------------------------------------------
38 #-------------------------------------------------------------------------------
39 # Constants
39 # Constants
40 #-------------------------------------------------------------------------------
40 #-------------------------------------------------------------------------------
41 _COMPLETE_BUFFER_MARKER = 31
41 _COMPLETE_BUFFER_MARKER = 31
42 _ERROR_MARKER = 30
42 _ERROR_MARKER = 30
43 _INPUT_MARKER = 29
43 _INPUT_MARKER = 29
44
44
45 _DEFAULT_SIZE = 10
45 _DEFAULT_SIZE = 10
46 if sys.platform == 'darwin':
46 if sys.platform == 'darwin':
47 _DEFAULT_SIZE = 12
47 _DEFAULT_SIZE = 12
48
48
49 _DEFAULT_STYLE = {
49 _DEFAULT_STYLE = {
50 #background definition
50 #background definition
51 'default' : 'size:%d' % _DEFAULT_SIZE,
51 'default' : 'size:%d' % _DEFAULT_SIZE,
52 'bracegood' : 'fore:#00AA00,back:#000000,bold',
52 'bracegood' : 'fore:#00AA00,back:#000000,bold',
53 'bracebad' : 'fore:#FF0000,back:#000000,bold',
53 'bracebad' : 'fore:#FF0000,back:#000000,bold',
54
54
55 # Edge column: a number of None
55 # Edge column: a number of None
56 'edge_column' : -1,
56 'edge_column' : -1,
57
57
58 # properties for the various Python lexer styles
58 # properties for the various Python lexer styles
59 'comment' : 'fore:#007F00',
59 'comment' : 'fore:#007F00',
60 'number' : 'fore:#007F7F',
60 'number' : 'fore:#007F7F',
61 'string' : 'fore:#7F007F,italic',
61 'string' : 'fore:#7F007F,italic',
62 'char' : 'fore:#7F007F,italic',
62 'char' : 'fore:#7F007F,italic',
63 'keyword' : 'fore:#00007F,bold',
63 'keyword' : 'fore:#00007F,bold',
64 'triple' : 'fore:#7F0000',
64 'triple' : 'fore:#7F0000',
65 'tripledouble' : 'fore:#7F0000',
65 'tripledouble' : 'fore:#7F0000',
66 'class' : 'fore:#0000FF,bold,underline',
66 'class' : 'fore:#0000FF,bold,underline',
67 'def' : 'fore:#007F7F,bold',
67 'def' : 'fore:#007F7F,bold',
68 'operator' : 'bold',
68 'operator' : 'bold',
69
69
70 # Default colors
70 # Default colors
71 'trace' : '#FAFAF1', # Nice green
71 'trace' : '#FAFAF1', # Nice green
72 'stdout' : '#FDFFD3', # Nice yellow
72 'stdout' : '#FDFFD3', # Nice yellow
73 'stderr' : '#FFF1F1', # Nice red
73 'stderr' : '#FFF1F1', # Nice red
74
74
75 # Default scintilla settings
75 # Default scintilla settings
76 'antialiasing' : True,
76 'antialiasing' : True,
77 'carret_color' : 'BLACK',
77 'carret_color' : 'BLACK',
78 'background_color' :'WHITE',
78 'background_color' :'WHITE',
79
79
80 #prompt definition
80 #prompt definition
81 'prompt_in1' : \
81 'prompt_in1' : \
82 '\n\x01\x1b[0;34m\x02In [\x01\x1b[1;34m\x02$number\x01\x1b[0;34m\x02]: \x01\x1b[0m\x02',
82 '\n\x01\x1b[0;34m\x02In [\x01\x1b[1;34m\x02$number\x01\x1b[0;34m\x02]: \x01\x1b[0m\x02',
83
83
84 'prompt_out': \
84 'prompt_out': \
85 '\x01\x1b[0;31m\x02Out[\x01\x1b[1;31m\x02$number\x01\x1b[0;31m\x02]: \x01\x1b[0m\x02',
85 '\x01\x1b[0;31m\x02Out[\x01\x1b[1;31m\x02$number\x01\x1b[0;31m\x02]: \x01\x1b[0m\x02',
86 }
86 }
87
87
88 # new style numbers
88 # new style numbers
89 _STDOUT_STYLE = 15
89 _STDOUT_STYLE = 15
90 _STDERR_STYLE = 16
90 _STDERR_STYLE = 16
91 _TRACE_STYLE = 17
91 _TRACE_STYLE = 17
92
92
93
93
94 # system colors
94 # system colors
95 #SYS_COLOUR_BACKGROUND = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BACKGROUND)
95 #SYS_COLOUR_BACKGROUND = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BACKGROUND)
96
96
97 # Translation table from ANSI escape sequences to color.
97 # Translation table from ANSI escape sequences to color.
98 ANSI_STYLES = {'0;30': [0, 'BLACK'], '0;31': [1, 'RED'],
98 ANSI_STYLES = {'0;30': [0, 'BLACK'], '0;31': [1, 'RED'],
99 '0;32': [2, 'GREEN'], '0;33': [3, 'BROWN'],
99 '0;32': [2, 'GREEN'], '0;33': [3, 'BROWN'],
100 '0;34': [4, 'BLUE'], '0;35': [5, 'PURPLE'],
100 '0;34': [4, 'BLUE'], '0;35': [5, 'PURPLE'],
101 '0;36': [6, 'CYAN'], '0;37': [7, 'LIGHT GREY'],
101 '0;36': [6, 'CYAN'], '0;37': [7, 'LIGHT GREY'],
102 '1;30': [8, 'DARK GREY'], '1;31': [9, 'RED'],
102 '1;30': [8, 'DARK GREY'], '1;31': [9, 'RED'],
103 '1;32': [10, 'SEA GREEN'], '1;33': [11, 'YELLOW'],
103 '1;32': [10, 'SEA GREEN'], '1;33': [11, 'YELLOW'],
104 '1;34': [12, 'LIGHT BLUE'], '1;35':
104 '1;34': [12, 'LIGHT BLUE'], '1;35':
105 [13, 'MEDIUM VIOLET RED'],
105 [13, 'MEDIUM VIOLET RED'],
106 '1;36': [14, 'LIGHT STEEL BLUE'], '1;37': [15, 'YELLOW']}
106 '1;36': [14, 'LIGHT STEEL BLUE'], '1;37': [15, 'YELLOW']}
107
107
108 # XXX: Maybe one day we should factor this code with ColorANSI. Right now
108 # XXX: Maybe one day we should factor this code with coloransi. Right now
109 # ColorANSI is hard to reuse and makes our code more complex.
109 # coloransi is hard to reuse and makes our code more complex.
110
110
111 #we define platform specific fonts
111 #we define platform specific fonts
112 if wx.Platform == '__WXMSW__':
112 if wx.Platform == '__WXMSW__':
113 FACES = { 'times': 'Times New Roman',
113 FACES = { 'times': 'Times New Roman',
114 'mono' : 'Courier New',
114 'mono' : 'Courier New',
115 'helv' : 'Arial',
115 'helv' : 'Arial',
116 'other': 'Comic Sans MS',
116 'other': 'Comic Sans MS',
117 'size' : 10,
117 'size' : 10,
118 'size2': 8,
118 'size2': 8,
119 }
119 }
120 elif wx.Platform == '__WXMAC__':
120 elif wx.Platform == '__WXMAC__':
121 FACES = { 'times': 'Times New Roman',
121 FACES = { 'times': 'Times New Roman',
122 'mono' : 'Monaco',
122 'mono' : 'Monaco',
123 'helv' : 'Arial',
123 'helv' : 'Arial',
124 'other': 'Comic Sans MS',
124 'other': 'Comic Sans MS',
125 'size' : 10,
125 'size' : 10,
126 'size2': 8,
126 'size2': 8,
127 }
127 }
128 else:
128 else:
129 FACES = { 'times': 'Times',
129 FACES = { 'times': 'Times',
130 'mono' : 'Courier',
130 'mono' : 'Courier',
131 'helv' : 'Helvetica',
131 'helv' : 'Helvetica',
132 'other': 'new century schoolbook',
132 'other': 'new century schoolbook',
133 'size' : 10,
133 'size' : 10,
134 'size2': 8,
134 'size2': 8,
135 }
135 }
136
136
137
137
138 #-------------------------------------------------------------------------------
138 #-------------------------------------------------------------------------------
139 # The console widget class
139 # The console widget class
140 #-------------------------------------------------------------------------------
140 #-------------------------------------------------------------------------------
141 class ConsoleWidget(editwindow.EditWindow):
141 class ConsoleWidget(editwindow.EditWindow):
142 """ Specialized styled text control view for console-like workflow.
142 """ Specialized styled text control view for console-like workflow.
143
143
144 This widget is mainly interested in dealing with the prompt and
144 This widget is mainly interested in dealing with the prompt and
145 keeping the cursor inside the editing line.
145 keeping the cursor inside the editing line.
146 """
146 """
147
147
148 # This is where the title captured from the ANSI escape sequences are
148 # This is where the title captured from the ANSI escape sequences are
149 # stored.
149 # stored.
150 title = 'Console'
150 title = 'Console'
151
151
152 # Last prompt printed
152 # Last prompt printed
153 last_prompt = ''
153 last_prompt = ''
154
154
155 # The buffer being edited.
155 # The buffer being edited.
156 def _set_input_buffer(self, string):
156 def _set_input_buffer(self, string):
157 self.SetSelection(self.current_prompt_pos, self.GetLength())
157 self.SetSelection(self.current_prompt_pos, self.GetLength())
158 self.ReplaceSelection(string)
158 self.ReplaceSelection(string)
159 self.GotoPos(self.GetLength())
159 self.GotoPos(self.GetLength())
160
160
161 def _get_input_buffer(self):
161 def _get_input_buffer(self):
162 """ Returns the text in current edit buffer.
162 """ Returns the text in current edit buffer.
163 """
163 """
164 input_buffer = self.GetTextRange(self.current_prompt_pos,
164 input_buffer = self.GetTextRange(self.current_prompt_pos,
165 self.GetLength())
165 self.GetLength())
166 input_buffer = input_buffer.replace(LINESEP, '\n')
166 input_buffer = input_buffer.replace(LINESEP, '\n')
167 return input_buffer
167 return input_buffer
168
168
169 input_buffer = property(_get_input_buffer, _set_input_buffer)
169 input_buffer = property(_get_input_buffer, _set_input_buffer)
170
170
171 style = _DEFAULT_STYLE.copy()
171 style = _DEFAULT_STYLE.copy()
172
172
173 # Translation table from ANSI escape sequences to color. Override
173 # Translation table from ANSI escape sequences to color. Override
174 # this to specify your colors.
174 # this to specify your colors.
175 ANSI_STYLES = ANSI_STYLES.copy()
175 ANSI_STYLES = ANSI_STYLES.copy()
176
176
177 # Font faces
177 # Font faces
178 faces = FACES.copy()
178 faces = FACES.copy()
179
179
180 # Store the last time a refresh was done
180 # Store the last time a refresh was done
181 _last_refresh_time = 0
181 _last_refresh_time = 0
182
182
183 #--------------------------------------------------------------------------
183 #--------------------------------------------------------------------------
184 # Public API
184 # Public API
185 #--------------------------------------------------------------------------
185 #--------------------------------------------------------------------------
186
186
187 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
187 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
188 size=wx.DefaultSize, style=wx.WANTS_CHARS, ):
188 size=wx.DefaultSize, style=wx.WANTS_CHARS, ):
189 editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
189 editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
190 self.configure_scintilla()
190 self.configure_scintilla()
191 # Track if 'enter' key as ever been processed
191 # Track if 'enter' key as ever been processed
192 # This variable will only be reallowed until key goes up
192 # This variable will only be reallowed until key goes up
193 self.enter_catched = False
193 self.enter_catched = False
194 self.current_prompt_pos = 0
194 self.current_prompt_pos = 0
195
195
196 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
196 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
197 self.Bind(wx.EVT_KEY_UP, self._on_key_up)
197 self.Bind(wx.EVT_KEY_UP, self._on_key_up)
198
198
199
199
200 def write(self, text, refresh=True):
200 def write(self, text, refresh=True):
201 """ Write given text to buffer, while translating the ansi escape
201 """ Write given text to buffer, while translating the ansi escape
202 sequences.
202 sequences.
203 """
203 """
204 # XXX: do not put print statements to sys.stdout/sys.stderr in
204 # XXX: do not put print statements to sys.stdout/sys.stderr in
205 # this method, the print statements will call this method, as
205 # this method, the print statements will call this method, as
206 # you will end up with an infinit loop
206 # you will end up with an infinit loop
207 title = self.title_pat.split(text)
207 title = self.title_pat.split(text)
208 if len(title)>1:
208 if len(title)>1:
209 self.title = title[-2]
209 self.title = title[-2]
210
210
211 text = self.title_pat.sub('', text)
211 text = self.title_pat.sub('', text)
212 segments = self.color_pat.split(text)
212 segments = self.color_pat.split(text)
213 segment = segments.pop(0)
213 segment = segments.pop(0)
214 self.GotoPos(self.GetLength())
214 self.GotoPos(self.GetLength())
215 self.StartStyling(self.GetLength(), 0xFF)
215 self.StartStyling(self.GetLength(), 0xFF)
216 try:
216 try:
217 self.AppendText(segment)
217 self.AppendText(segment)
218 except UnicodeDecodeError:
218 except UnicodeDecodeError:
219 # XXX: Do I really want to skip the exception?
219 # XXX: Do I really want to skip the exception?
220 pass
220 pass
221
221
222 if segments:
222 if segments:
223 for ansi_tag, text in zip(segments[::2], segments[1::2]):
223 for ansi_tag, text in zip(segments[::2], segments[1::2]):
224 self.StartStyling(self.GetLength(), 0xFF)
224 self.StartStyling(self.GetLength(), 0xFF)
225 try:
225 try:
226 self.AppendText(text)
226 self.AppendText(text)
227 except UnicodeDecodeError:
227 except UnicodeDecodeError:
228 # XXX: Do I really want to skip the exception?
228 # XXX: Do I really want to skip the exception?
229 pass
229 pass
230
230
231 if ansi_tag not in self.ANSI_STYLES:
231 if ansi_tag not in self.ANSI_STYLES:
232 style = 0
232 style = 0
233 else:
233 else:
234 style = self.ANSI_STYLES[ansi_tag][0]
234 style = self.ANSI_STYLES[ansi_tag][0]
235
235
236 self.SetStyling(len(text), style)
236 self.SetStyling(len(text), style)
237
237
238 self.GotoPos(self.GetLength())
238 self.GotoPos(self.GetLength())
239 if refresh:
239 if refresh:
240 current_time = time.time()
240 current_time = time.time()
241 if current_time - self._last_refresh_time > 0.03:
241 if current_time - self._last_refresh_time > 0.03:
242 if sys.platform == 'win32':
242 if sys.platform == 'win32':
243 wx.SafeYield()
243 wx.SafeYield()
244 else:
244 else:
245 wx.Yield()
245 wx.Yield()
246 # self.ProcessEvent(wx.PaintEvent())
246 # self.ProcessEvent(wx.PaintEvent())
247 self._last_refresh_time = current_time
247 self._last_refresh_time = current_time
248
248
249
249
250 def new_prompt(self, prompt):
250 def new_prompt(self, prompt):
251 """ Prints a prompt at start of line, and move the start of the
251 """ Prints a prompt at start of line, and move the start of the
252 current block there.
252 current block there.
253
253
254 The prompt can be given with ascii escape sequences.
254 The prompt can be given with ascii escape sequences.
255 """
255 """
256 self.write(prompt, refresh=False)
256 self.write(prompt, refresh=False)
257 # now we update our cursor giving end of prompt
257 # now we update our cursor giving end of prompt
258 self.current_prompt_pos = self.GetLength()
258 self.current_prompt_pos = self.GetLength()
259 self.current_prompt_line = self.GetCurrentLine()
259 self.current_prompt_line = self.GetCurrentLine()
260 self.EnsureCaretVisible()
260 self.EnsureCaretVisible()
261 self.last_prompt = prompt
261 self.last_prompt = prompt
262
262
263
263
264 def continuation_prompt(self):
264 def continuation_prompt(self):
265 """ Returns the current continuation prompt.
265 """ Returns the current continuation prompt.
266 We need to implement this method here to deal with the
266 We need to implement this method here to deal with the
267 ascii escape sequences cleaning up.
267 ascii escape sequences cleaning up.
268 """
268 """
269 # ASCII-less prompt
269 # ASCII-less prompt
270 ascii_less = ''.join(self.color_pat.split(self.last_prompt)[2::2])
270 ascii_less = ''.join(self.color_pat.split(self.last_prompt)[2::2])
271 return "."*(len(ascii_less)-2) + ': '
271 return "."*(len(ascii_less)-2) + ': '
272
272
273
273
274 def scroll_to_bottom(self):
274 def scroll_to_bottom(self):
275 maxrange = self.GetScrollRange(wx.VERTICAL)
275 maxrange = self.GetScrollRange(wx.VERTICAL)
276 self.ScrollLines(maxrange)
276 self.ScrollLines(maxrange)
277
277
278
278
279 def pop_completion(self, possibilities, offset=0):
279 def pop_completion(self, possibilities, offset=0):
280 """ Pops up an autocompletion menu. Offset is the offset
280 """ Pops up an autocompletion menu. Offset is the offset
281 in characters of the position at which the menu should
281 in characters of the position at which the menu should
282 appear, relativ to the cursor.
282 appear, relativ to the cursor.
283 """
283 """
284 self.AutoCompSetIgnoreCase(False)
284 self.AutoCompSetIgnoreCase(False)
285 self.AutoCompSetAutoHide(False)
285 self.AutoCompSetAutoHide(False)
286 self.AutoCompSetMaxHeight(len(possibilities))
286 self.AutoCompSetMaxHeight(len(possibilities))
287 self.AutoCompShow(offset, " ".join(possibilities))
287 self.AutoCompShow(offset, " ".join(possibilities))
288
288
289
289
290 def get_line_width(self):
290 def get_line_width(self):
291 """ Return the width of the line in characters.
291 """ Return the width of the line in characters.
292 """
292 """
293 return self.GetSize()[0]/self.GetCharWidth()
293 return self.GetSize()[0]/self.GetCharWidth()
294
294
295
295
296 def configure_scintilla(self):
296 def configure_scintilla(self):
297 """ Set up all the styling option of the embedded scintilla
297 """ Set up all the styling option of the embedded scintilla
298 widget.
298 widget.
299 """
299 """
300 p = self.style.copy()
300 p = self.style.copy()
301
301
302 # Marker for complete buffer.
302 # Marker for complete buffer.
303 self.MarkerDefine(_COMPLETE_BUFFER_MARKER, stc.STC_MARK_BACKGROUND,
303 self.MarkerDefine(_COMPLETE_BUFFER_MARKER, stc.STC_MARK_BACKGROUND,
304 background=p['trace'])
304 background=p['trace'])
305
305
306 # Marker for current input buffer.
306 # Marker for current input buffer.
307 self.MarkerDefine(_INPUT_MARKER, stc.STC_MARK_BACKGROUND,
307 self.MarkerDefine(_INPUT_MARKER, stc.STC_MARK_BACKGROUND,
308 background=p['stdout'])
308 background=p['stdout'])
309 # Marker for tracebacks.
309 # Marker for tracebacks.
310 self.MarkerDefine(_ERROR_MARKER, stc.STC_MARK_BACKGROUND,
310 self.MarkerDefine(_ERROR_MARKER, stc.STC_MARK_BACKGROUND,
311 background=p['stderr'])
311 background=p['stderr'])
312
312
313 self.SetEOLMode(stc.STC_EOL_LF)
313 self.SetEOLMode(stc.STC_EOL_LF)
314
314
315 # Ctrl"+" or Ctrl "-" can be used to zoomin/zoomout the text inside
315 # Ctrl"+" or Ctrl "-" can be used to zoomin/zoomout the text inside
316 # the widget
316 # the widget
317 self.CmdKeyAssign(ord('+'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
317 self.CmdKeyAssign(ord('+'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
318 self.CmdKeyAssign(ord('-'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
318 self.CmdKeyAssign(ord('-'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
319 # Also allow Ctrl Shift "=" for poor non US keyboard users.
319 # Also allow Ctrl Shift "=" for poor non US keyboard users.
320 self.CmdKeyAssign(ord('='), stc.STC_SCMOD_CTRL|stc.STC_SCMOD_SHIFT,
320 self.CmdKeyAssign(ord('='), stc.STC_SCMOD_CTRL|stc.STC_SCMOD_SHIFT,
321 stc.STC_CMD_ZOOMIN)
321 stc.STC_CMD_ZOOMIN)
322
322
323 # Keys: we need to clear some of the keys the that don't play
323 # Keys: we need to clear some of the keys the that don't play
324 # well with a console.
324 # well with a console.
325 self.CmdKeyClear(ord('D'), stc.STC_SCMOD_CTRL)
325 self.CmdKeyClear(ord('D'), stc.STC_SCMOD_CTRL)
326 self.CmdKeyClear(ord('L'), stc.STC_SCMOD_CTRL)
326 self.CmdKeyClear(ord('L'), stc.STC_SCMOD_CTRL)
327 self.CmdKeyClear(ord('T'), stc.STC_SCMOD_CTRL)
327 self.CmdKeyClear(ord('T'), stc.STC_SCMOD_CTRL)
328 self.CmdKeyClear(ord('A'), stc.STC_SCMOD_CTRL)
328 self.CmdKeyClear(ord('A'), stc.STC_SCMOD_CTRL)
329
329
330 self.SetEOLMode(stc.STC_EOL_CRLF)
330 self.SetEOLMode(stc.STC_EOL_CRLF)
331 self.SetWrapMode(stc.STC_WRAP_CHAR)
331 self.SetWrapMode(stc.STC_WRAP_CHAR)
332 self.SetWrapMode(stc.STC_WRAP_WORD)
332 self.SetWrapMode(stc.STC_WRAP_WORD)
333 self.SetBufferedDraw(True)
333 self.SetBufferedDraw(True)
334
334
335 self.SetUseAntiAliasing(p['antialiasing'])
335 self.SetUseAntiAliasing(p['antialiasing'])
336
336
337 self.SetLayoutCache(stc.STC_CACHE_PAGE)
337 self.SetLayoutCache(stc.STC_CACHE_PAGE)
338 self.SetUndoCollection(False)
338 self.SetUndoCollection(False)
339 self.SetUseTabs(True)
339 self.SetUseTabs(True)
340 self.SetIndent(4)
340 self.SetIndent(4)
341 self.SetTabWidth(4)
341 self.SetTabWidth(4)
342
342
343 # we don't want scintilla's autocompletion to choose
343 # we don't want scintilla's autocompletion to choose
344 # automaticaly out of a single choice list, as we pop it up
344 # automaticaly out of a single choice list, as we pop it up
345 # automaticaly
345 # automaticaly
346 self.AutoCompSetChooseSingle(False)
346 self.AutoCompSetChooseSingle(False)
347 self.AutoCompSetMaxHeight(10)
347 self.AutoCompSetMaxHeight(10)
348 # XXX: this doesn't seem to have an effect.
348 # XXX: this doesn't seem to have an effect.
349 self.AutoCompSetFillUps('\n')
349 self.AutoCompSetFillUps('\n')
350
350
351 self.SetMargins(3, 3) #text is moved away from border with 3px
351 self.SetMargins(3, 3) #text is moved away from border with 3px
352 # Suppressing Scintilla margins
352 # Suppressing Scintilla margins
353 self.SetMarginWidth(0, 0)
353 self.SetMarginWidth(0, 0)
354 self.SetMarginWidth(1, 0)
354 self.SetMarginWidth(1, 0)
355 self.SetMarginWidth(2, 0)
355 self.SetMarginWidth(2, 0)
356
356
357 # Xterm escape sequences
357 # Xterm escape sequences
358 self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?')
358 self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?')
359 self.title_pat = re.compile('\x1b]0;(.*?)\x07')
359 self.title_pat = re.compile('\x1b]0;(.*?)\x07')
360
360
361 # styles
361 # styles
362
362
363 self.SetCaretForeground(p['carret_color'])
363 self.SetCaretForeground(p['carret_color'])
364
364
365 background_color = p['background_color']
365 background_color = p['background_color']
366
366
367 if 'default' in p:
367 if 'default' in p:
368 if 'back' not in p['default']:
368 if 'back' not in p['default']:
369 p['default'] += ',back:%s' % background_color
369 p['default'] += ',back:%s' % background_color
370 if 'size' not in p['default']:
370 if 'size' not in p['default']:
371 p['default'] += ',size:%s' % self.faces['size']
371 p['default'] += ',size:%s' % self.faces['size']
372 if 'face' not in p['default']:
372 if 'face' not in p['default']:
373 p['default'] += ',face:%s' % self.faces['mono']
373 p['default'] += ',face:%s' % self.faces['mono']
374
374
375 self.StyleSetSpec(stc.STC_STYLE_DEFAULT, p['default'])
375 self.StyleSetSpec(stc.STC_STYLE_DEFAULT, p['default'])
376 else:
376 else:
377 self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
377 self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
378 "fore:%s,back:%s,size:%d,face:%s"
378 "fore:%s,back:%s,size:%d,face:%s"
379 % (self.ANSI_STYLES['0;30'][1],
379 % (self.ANSI_STYLES['0;30'][1],
380 background_color,
380 background_color,
381 self.faces['size'], self.faces['mono']))
381 self.faces['size'], self.faces['mono']))
382
382
383 self.StyleClearAll()
383 self.StyleClearAll()
384
384
385 # XXX: two lines below are usefull if not using the lexer
385 # XXX: two lines below are usefull if not using the lexer
386 #for style in self.ANSI_STYLES.values():
386 #for style in self.ANSI_STYLES.values():
387 # self.StyleSetSpec(style[0], "bold,fore:%s" % style[1])
387 # self.StyleSetSpec(style[0], "bold,fore:%s" % style[1])
388
388
389 # prompt definition
389 # prompt definition
390 self.prompt_in1 = p['prompt_in1']
390 self.prompt_in1 = p['prompt_in1']
391 self.prompt_out = p['prompt_out']
391 self.prompt_out = p['prompt_out']
392
392
393 self.output_prompt_template = string.Template(self.prompt_out)
393 self.output_prompt_template = string.Template(self.prompt_out)
394 self.input_prompt_template = string.Template(self.prompt_in1)
394 self.input_prompt_template = string.Template(self.prompt_in1)
395
395
396 self.StyleSetSpec(_STDOUT_STYLE, p['stdout'])
396 self.StyleSetSpec(_STDOUT_STYLE, p['stdout'])
397 self.StyleSetSpec(_STDERR_STYLE, p['stderr'])
397 self.StyleSetSpec(_STDERR_STYLE, p['stderr'])
398 self.StyleSetSpec(_TRACE_STYLE, p['trace'])
398 self.StyleSetSpec(_TRACE_STYLE, p['trace'])
399 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, p['bracegood'])
399 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, p['bracegood'])
400 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, p['bracebad'])
400 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, p['bracebad'])
401 self.StyleSetSpec(stc.STC_P_COMMENTLINE, p['comment'])
401 self.StyleSetSpec(stc.STC_P_COMMENTLINE, p['comment'])
402 self.StyleSetSpec(stc.STC_P_NUMBER, p['number'])
402 self.StyleSetSpec(stc.STC_P_NUMBER, p['number'])
403 self.StyleSetSpec(stc.STC_P_STRING, p['string'])
403 self.StyleSetSpec(stc.STC_P_STRING, p['string'])
404 self.StyleSetSpec(stc.STC_P_CHARACTER, p['char'])
404 self.StyleSetSpec(stc.STC_P_CHARACTER, p['char'])
405 self.StyleSetSpec(stc.STC_P_WORD, p['keyword'])
405 self.StyleSetSpec(stc.STC_P_WORD, p['keyword'])
406 self.StyleSetSpec(stc.STC_P_WORD2, p['keyword'])
406 self.StyleSetSpec(stc.STC_P_WORD2, p['keyword'])
407 self.StyleSetSpec(stc.STC_P_TRIPLE, p['triple'])
407 self.StyleSetSpec(stc.STC_P_TRIPLE, p['triple'])
408 self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, p['tripledouble'])
408 self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, p['tripledouble'])
409 self.StyleSetSpec(stc.STC_P_CLASSNAME, p['class'])
409 self.StyleSetSpec(stc.STC_P_CLASSNAME, p['class'])
410 self.StyleSetSpec(stc.STC_P_DEFNAME, p['def'])
410 self.StyleSetSpec(stc.STC_P_DEFNAME, p['def'])
411 self.StyleSetSpec(stc.STC_P_OPERATOR, p['operator'])
411 self.StyleSetSpec(stc.STC_P_OPERATOR, p['operator'])
412 self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, p['comment'])
412 self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, p['comment'])
413
413
414 edge_column = p['edge_column']
414 edge_column = p['edge_column']
415 if edge_column is not None and edge_column > 0:
415 if edge_column is not None and edge_column > 0:
416 #we add a vertical line to console widget
416 #we add a vertical line to console widget
417 self.SetEdgeMode(stc.STC_EDGE_LINE)
417 self.SetEdgeMode(stc.STC_EDGE_LINE)
418 self.SetEdgeColumn(edge_column)
418 self.SetEdgeColumn(edge_column)
419
419
420
420
421 #--------------------------------------------------------------------------
421 #--------------------------------------------------------------------------
422 # EditWindow API
422 # EditWindow API
423 #--------------------------------------------------------------------------
423 #--------------------------------------------------------------------------
424
424
425 def OnUpdateUI(self, event):
425 def OnUpdateUI(self, event):
426 """ Override the OnUpdateUI of the EditWindow class, to prevent
426 """ Override the OnUpdateUI of the EditWindow class, to prevent
427 syntax highlighting both for faster redraw, and for more
427 syntax highlighting both for faster redraw, and for more
428 consistent look and feel.
428 consistent look and feel.
429 """
429 """
430
430
431
431
432 #--------------------------------------------------------------------------
432 #--------------------------------------------------------------------------
433 # Private API
433 # Private API
434 #--------------------------------------------------------------------------
434 #--------------------------------------------------------------------------
435
435
436 def _on_key_down(self, event, skip=True):
436 def _on_key_down(self, event, skip=True):
437 """ Key press callback used for correcting behavior for
437 """ Key press callback used for correcting behavior for
438 console-like interfaces: the cursor is constraint to be after
438 console-like interfaces: the cursor is constraint to be after
439 the last prompt.
439 the last prompt.
440
440
441 Return True if event as been catched.
441 Return True if event as been catched.
442 """
442 """
443 catched = True
443 catched = True
444 # XXX: Would the right way to do this be to have a
444 # XXX: Would the right way to do this be to have a
445 # dictionary at the instance level associating keys with
445 # dictionary at the instance level associating keys with
446 # callbacks? How would we deal with inheritance? And Do the
446 # callbacks? How would we deal with inheritance? And Do the
447 # different callbacks share local variables?
447 # different callbacks share local variables?
448
448
449 # Intercept some specific keys.
449 # Intercept some specific keys.
450 if event.KeyCode == ord('L') and event.ControlDown() :
450 if event.KeyCode == ord('L') and event.ControlDown() :
451 self.scroll_to_bottom()
451 self.scroll_to_bottom()
452 elif event.KeyCode == ord('K') and event.ControlDown() :
452 elif event.KeyCode == ord('K') and event.ControlDown() :
453 self.input_buffer = ''
453 self.input_buffer = ''
454 elif event.KeyCode == ord('A') and event.ControlDown() :
454 elif event.KeyCode == ord('A') and event.ControlDown() :
455 self.GotoPos(self.GetLength())
455 self.GotoPos(self.GetLength())
456 self.SetSelectionStart(self.current_prompt_pos)
456 self.SetSelectionStart(self.current_prompt_pos)
457 self.SetSelectionEnd(self.GetCurrentPos())
457 self.SetSelectionEnd(self.GetCurrentPos())
458 catched = True
458 catched = True
459 elif event.KeyCode == ord('E') and event.ControlDown() :
459 elif event.KeyCode == ord('E') and event.ControlDown() :
460 self.GotoPos(self.GetLength())
460 self.GotoPos(self.GetLength())
461 catched = True
461 catched = True
462 elif event.KeyCode == wx.WXK_PAGEUP:
462 elif event.KeyCode == wx.WXK_PAGEUP:
463 self.ScrollPages(-1)
463 self.ScrollPages(-1)
464 elif event.KeyCode == wx.WXK_PAGEDOWN:
464 elif event.KeyCode == wx.WXK_PAGEDOWN:
465 self.ScrollPages(1)
465 self.ScrollPages(1)
466 elif event.KeyCode == wx.WXK_HOME:
466 elif event.KeyCode == wx.WXK_HOME:
467 self.GotoPos(self.GetLength())
467 self.GotoPos(self.GetLength())
468 elif event.KeyCode == wx.WXK_END:
468 elif event.KeyCode == wx.WXK_END:
469 self.GotoPos(self.GetLength())
469 self.GotoPos(self.GetLength())
470 elif event.KeyCode == wx.WXK_UP and event.ShiftDown():
470 elif event.KeyCode == wx.WXK_UP and event.ShiftDown():
471 self.ScrollLines(-1)
471 self.ScrollLines(-1)
472 elif event.KeyCode == wx.WXK_DOWN and event.ShiftDown():
472 elif event.KeyCode == wx.WXK_DOWN and event.ShiftDown():
473 self.ScrollLines(1)
473 self.ScrollLines(1)
474 else:
474 else:
475 catched = False
475 catched = False
476
476
477 if self.AutoCompActive():
477 if self.AutoCompActive():
478 event.Skip()
478 event.Skip()
479 else:
479 else:
480 if event.KeyCode in (13, wx.WXK_NUMPAD_ENTER) and \
480 if event.KeyCode in (13, wx.WXK_NUMPAD_ENTER) and \
481 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN,
481 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN,
482 wx.MOD_SHIFT):
482 wx.MOD_SHIFT):
483 catched = True
483 catched = True
484 if not self.enter_catched:
484 if not self.enter_catched:
485 self.CallTipCancel()
485 self.CallTipCancel()
486 if event.Modifiers == wx.MOD_SHIFT:
486 if event.Modifiers == wx.MOD_SHIFT:
487 # Try to force execution
487 # Try to force execution
488 self.GotoPos(self.GetLength())
488 self.GotoPos(self.GetLength())
489 self.write('\n' + self.continuation_prompt(),
489 self.write('\n' + self.continuation_prompt(),
490 refresh=False)
490 refresh=False)
491 self._on_enter()
491 self._on_enter()
492 else:
492 else:
493 self._on_enter()
493 self._on_enter()
494 self.enter_catched = True
494 self.enter_catched = True
495
495
496 elif event.KeyCode == wx.WXK_HOME:
496 elif event.KeyCode == wx.WXK_HOME:
497 if event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
497 if event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
498 self.GotoPos(self.current_prompt_pos)
498 self.GotoPos(self.current_prompt_pos)
499 catched = True
499 catched = True
500
500
501 elif event.Modifiers == wx.MOD_SHIFT:
501 elif event.Modifiers == wx.MOD_SHIFT:
502 # FIXME: This behavior is not ideal: if the selection
502 # FIXME: This behavior is not ideal: if the selection
503 # is already started, it will jump.
503 # is already started, it will jump.
504 self.SetSelectionStart(self.current_prompt_pos)
504 self.SetSelectionStart(self.current_prompt_pos)
505 self.SetSelectionEnd(self.GetCurrentPos())
505 self.SetSelectionEnd(self.GetCurrentPos())
506 catched = True
506 catched = True
507
507
508 elif event.KeyCode == wx.WXK_UP:
508 elif event.KeyCode == wx.WXK_UP:
509 if self.GetCurrentLine() > self.current_prompt_line:
509 if self.GetCurrentLine() > self.current_prompt_line:
510 if self.GetCurrentLine() == self.current_prompt_line + 1 \
510 if self.GetCurrentLine() == self.current_prompt_line + 1 \
511 and self.GetColumn(self.GetCurrentPos()) < \
511 and self.GetColumn(self.GetCurrentPos()) < \
512 self.GetColumn(self.current_prompt_pos):
512 self.GetColumn(self.current_prompt_pos):
513 self.GotoPos(self.current_prompt_pos)
513 self.GotoPos(self.current_prompt_pos)
514 else:
514 else:
515 event.Skip()
515 event.Skip()
516 catched = True
516 catched = True
517
517
518 elif event.KeyCode in (wx.WXK_LEFT, wx.WXK_BACK):
518 elif event.KeyCode in (wx.WXK_LEFT, wx.WXK_BACK):
519 if not self._keep_cursor_in_buffer(self.GetCurrentPos() - 1):
519 if not self._keep_cursor_in_buffer(self.GetCurrentPos() - 1):
520 event.Skip()
520 event.Skip()
521 catched = True
521 catched = True
522
522
523 elif event.KeyCode == wx.WXK_RIGHT:
523 elif event.KeyCode == wx.WXK_RIGHT:
524 if not self._keep_cursor_in_buffer(self.GetCurrentPos() + 1):
524 if not self._keep_cursor_in_buffer(self.GetCurrentPos() + 1):
525 event.Skip()
525 event.Skip()
526 catched = True
526 catched = True
527
527
528
528
529 elif event.KeyCode == wx.WXK_DELETE:
529 elif event.KeyCode == wx.WXK_DELETE:
530 if not self._keep_cursor_in_buffer(self.GetCurrentPos() - 1):
530 if not self._keep_cursor_in_buffer(self.GetCurrentPos() - 1):
531 event.Skip()
531 event.Skip()
532 catched = True
532 catched = True
533
533
534 if skip and not catched:
534 if skip and not catched:
535 # Put the cursor back in the edit region
535 # Put the cursor back in the edit region
536 if not self._keep_cursor_in_buffer():
536 if not self._keep_cursor_in_buffer():
537 if not (self.GetCurrentPos() == self.GetLength()
537 if not (self.GetCurrentPos() == self.GetLength()
538 and event.KeyCode == wx.WXK_DELETE):
538 and event.KeyCode == wx.WXK_DELETE):
539 event.Skip()
539 event.Skip()
540 catched = True
540 catched = True
541
541
542 return catched
542 return catched
543
543
544
544
545 def _on_key_up(self, event, skip=True):
545 def _on_key_up(self, event, skip=True):
546 """ If cursor is outside the editing region, put it back.
546 """ If cursor is outside the editing region, put it back.
547 """
547 """
548 if skip:
548 if skip:
549 event.Skip()
549 event.Skip()
550 self._keep_cursor_in_buffer()
550 self._keep_cursor_in_buffer()
551
551
552
552
553 # XXX: I need to avoid the problem of having an empty glass;
553 # XXX: I need to avoid the problem of having an empty glass;
554 def _keep_cursor_in_buffer(self, pos=None):
554 def _keep_cursor_in_buffer(self, pos=None):
555 """ Checks if the cursor is where it is allowed to be. If not,
555 """ Checks if the cursor is where it is allowed to be. If not,
556 put it back.
556 put it back.
557
557
558 Returns
558 Returns
559 -------
559 -------
560 cursor_moved: Boolean
560 cursor_moved: Boolean
561 whether or not the cursor was moved by this routine.
561 whether or not the cursor was moved by this routine.
562
562
563 Notes
563 Notes
564 ------
564 ------
565 WARNING: This does proper checks only for horizontal
565 WARNING: This does proper checks only for horizontal
566 movements.
566 movements.
567 """
567 """
568 if pos is None:
568 if pos is None:
569 current_pos = self.GetCurrentPos()
569 current_pos = self.GetCurrentPos()
570 else:
570 else:
571 current_pos = pos
571 current_pos = pos
572 if current_pos < self.current_prompt_pos:
572 if current_pos < self.current_prompt_pos:
573 self.GotoPos(self.current_prompt_pos)
573 self.GotoPos(self.current_prompt_pos)
574 return True
574 return True
575 line_num = self.LineFromPosition(current_pos)
575 line_num = self.LineFromPosition(current_pos)
576 if not current_pos > self.GetLength():
576 if not current_pos > self.GetLength():
577 line_pos = self.GetColumn(current_pos)
577 line_pos = self.GetColumn(current_pos)
578 else:
578 else:
579 line_pos = self.GetColumn(self.GetLength())
579 line_pos = self.GetColumn(self.GetLength())
580 line = self.GetLine(line_num)
580 line = self.GetLine(line_num)
581 # Jump the continuation prompt
581 # Jump the continuation prompt
582 continuation_prompt = self.continuation_prompt()
582 continuation_prompt = self.continuation_prompt()
583 if ( line.startswith(continuation_prompt)
583 if ( line.startswith(continuation_prompt)
584 and line_pos < len(continuation_prompt)):
584 and line_pos < len(continuation_prompt)):
585 if line_pos < 2:
585 if line_pos < 2:
586 # We are at the beginning of the line, trying to move
586 # We are at the beginning of the line, trying to move
587 # forward: jump forward.
587 # forward: jump forward.
588 self.GotoPos(current_pos + 1 +
588 self.GotoPos(current_pos + 1 +
589 len(continuation_prompt) - line_pos)
589 len(continuation_prompt) - line_pos)
590 else:
590 else:
591 # Jump back up
591 # Jump back up
592 self.GotoPos(self.GetLineEndPosition(line_num-1))
592 self.GotoPos(self.GetLineEndPosition(line_num-1))
593 return True
593 return True
594 elif ( current_pos > self.GetLineEndPosition(line_num)
594 elif ( current_pos > self.GetLineEndPosition(line_num)
595 and not current_pos == self.GetLength()):
595 and not current_pos == self.GetLength()):
596 # Jump to next line
596 # Jump to next line
597 self.GotoPos(current_pos + 1 +
597 self.GotoPos(current_pos + 1 +
598 len(continuation_prompt))
598 len(continuation_prompt))
599 return True
599 return True
600
600
601 # We re-allow enter event processing
601 # We re-allow enter event processing
602 self.enter_catched = False
602 self.enter_catched = False
603 return False
603 return False
604
604
605
605
606 if __name__ == '__main__':
606 if __name__ == '__main__':
607 # Some simple code to test the console widget.
607 # Some simple code to test the console widget.
608 class MainWindow(wx.Frame):
608 class MainWindow(wx.Frame):
609 def __init__(self, parent, id, title):
609 def __init__(self, parent, id, title):
610 wx.Frame.__init__(self, parent, id, title, size=(300, 250))
610 wx.Frame.__init__(self, parent, id, title, size=(300, 250))
611 self._sizer = wx.BoxSizer(wx.VERTICAL)
611 self._sizer = wx.BoxSizer(wx.VERTICAL)
612 self.console_widget = ConsoleWidget(self)
612 self.console_widget = ConsoleWidget(self)
613 self._sizer.Add(self.console_widget, 1, wx.EXPAND)
613 self._sizer.Add(self.console_widget, 1, wx.EXPAND)
614 self.SetSizer(self._sizer)
614 self.SetSizer(self._sizer)
615 self.SetAutoLayout(1)
615 self.SetAutoLayout(1)
616 self.Show(True)
616 self.Show(True)
617
617
618 app = wx.PySimpleApp()
618 app = wx.PySimpleApp()
619 w = MainWindow(None, wx.ID_ANY, 'ConsoleWidget')
619 w = MainWindow(None, wx.ID_ANY, 'ConsoleWidget')
620 w.SetSize((780, 460))
620 w.SetSize((780, 460))
621 w.Show()
621 w.Show()
622
622
623 app.MainLoop()
623 app.MainLoop()
624
624
625
625
@@ -1,2870 +1,2862 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 IPython -- An enhanced Interactive Python
3 IPython -- An enhanced Interactive Python
4
4
5 Requires Python 2.4 or newer.
5 Requires Python 2.4 or newer.
6
6
7 This file contains all the classes and helper functions specific to IPython.
7 This file contains all the classes and helper functions specific to IPython.
8 """
8 """
9
9
10 #*****************************************************************************
10 #*****************************************************************************
11 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
11 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
12 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
12 # Copyright (C) 2001-2006 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 # Note: this code originally subclassed code.InteractiveConsole from the
17 # Note: this code originally subclassed code.InteractiveConsole from the
18 # Python standard library. Over time, all of that class has been copied
18 # Python standard library. Over time, all of that class has been copied
19 # verbatim here for modifications which could not be accomplished by
19 # verbatim here for modifications which could not be accomplished by
20 # subclassing. At this point, there are no dependencies at all on the code
20 # subclassing. At this point, there are no dependencies at all on the code
21 # module anymore (it is not even imported). The Python License (sec. 2)
21 # module anymore (it is not even imported). The Python License (sec. 2)
22 # allows for this, but it's always nice to acknowledge credit where credit is
22 # allows for this, but it's always nice to acknowledge credit where credit is
23 # due.
23 # due.
24 #*****************************************************************************
24 #*****************************************************************************
25
25
26 #****************************************************************************
26 #****************************************************************************
27 # Modules and globals
27 # Modules and globals
28
28
29 # Python standard modules
29 # Python standard modules
30 import __main__
30 import __main__
31 import __builtin__
31 import __builtin__
32 import StringIO
32 import StringIO
33 import bdb
33 import bdb
34 import cPickle as pickle
35 import codeop
34 import codeop
36 import exceptions
35 import exceptions
37 import glob
36 import glob
38 import inspect
39 import keyword
37 import keyword
40 import new
38 import new
41 import os
39 import os
42 import pydoc
43 import re
40 import re
44 import shutil
41 import shutil
45 import string
42 import string
46 import sys
43 import sys
47 import tempfile
44 import tempfile
48 import traceback
49 import types
50 from pprint import pprint, pformat
51
45
52 # IPython's own modules
46 # IPython's own modules
53 #import IPython
47 #import IPython
54 from IPython import Debugger,OInspect,PyColorize,ultraTB
48 from IPython import Debugger,OInspect,PyColorize,ultraTB
55 from IPython.ColorANSI import ColorScheme,ColorSchemeTable # too long names
56 from IPython.Extensions import pickleshare
49 from IPython.Extensions import pickleshare
57 from IPython.FakeModule import FakeModule, init_fakemod_dict
50 from IPython.FakeModule import FakeModule, init_fakemod_dict
58 from IPython.Itpl import Itpl,itpl,printpl,ItplNS,itplns
51 from IPython.Itpl import ItplNS
59 from IPython.Logger import Logger
52 from IPython.Logger import Logger
60 from IPython.Magic import Magic
53 from IPython.Magic import Magic
61 from IPython.Prompts import CachedOutput
54 from IPython.Prompts import CachedOutput
62 from IPython.ipstruct import Struct
55 from IPython.ipstruct import Struct
63 from IPython.background_jobs import BackgroundJobManager
56 from IPython.background_jobs import BackgroundJobManager
64 from IPython.usage import cmd_line_usage,interactive_usage
65 from IPython.genutils import *
57 from IPython.genutils import *
66 from IPython.strdispatch import StrDispatch
58 from IPython.strdispatch import StrDispatch
67 import IPython.ipapi
59 import IPython.ipapi
68 import IPython.history
60 import IPython.history
69 import IPython.prefilter as prefilter
61 import IPython.prefilter as prefilter
70 import IPython.shadowns
62 import IPython.shadowns
71 # Globals
63 # Globals
72
64
73 # store the builtin raw_input globally, and use this always, in case user code
65 # store the builtin raw_input globally, and use this always, in case user code
74 # overwrites it (like wx.py.PyShell does)
66 # overwrites it (like wx.py.PyShell does)
75 raw_input_original = raw_input
67 raw_input_original = raw_input
76
68
77 # compiled regexps for autoindent management
69 # compiled regexps for autoindent management
78 dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass')
70 dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass')
79
71
80
72
81 #****************************************************************************
73 #****************************************************************************
82 # Some utility function definitions
74 # Some utility function definitions
83
75
84 ini_spaces_re = re.compile(r'^(\s+)')
76 ini_spaces_re = re.compile(r'^(\s+)')
85
77
86 def num_ini_spaces(strng):
78 def num_ini_spaces(strng):
87 """Return the number of initial spaces in a string"""
79 """Return the number of initial spaces in a string"""
88
80
89 ini_spaces = ini_spaces_re.match(strng)
81 ini_spaces = ini_spaces_re.match(strng)
90 if ini_spaces:
82 if ini_spaces:
91 return ini_spaces.end()
83 return ini_spaces.end()
92 else:
84 else:
93 return 0
85 return 0
94
86
95 def softspace(file, newvalue):
87 def softspace(file, newvalue):
96 """Copied from code.py, to remove the dependency"""
88 """Copied from code.py, to remove the dependency"""
97
89
98 oldvalue = 0
90 oldvalue = 0
99 try:
91 try:
100 oldvalue = file.softspace
92 oldvalue = file.softspace
101 except AttributeError:
93 except AttributeError:
102 pass
94 pass
103 try:
95 try:
104 file.softspace = newvalue
96 file.softspace = newvalue
105 except (AttributeError, TypeError):
97 except (AttributeError, TypeError):
106 # "attribute-less object" or "read-only attributes"
98 # "attribute-less object" or "read-only attributes"
107 pass
99 pass
108 return oldvalue
100 return oldvalue
109
101
110
102
111 def user_setup(ipythondir,rc_suffix,mode='install',interactive=True):
103 def user_setup(ipythondir,rc_suffix,mode='install',interactive=True):
112 """Install or upgrade the user configuration directory.
104 """Install or upgrade the user configuration directory.
113
105
114 Can be called when running for the first time or to upgrade the user's
106 Can be called when running for the first time or to upgrade the user's
115 .ipython/ directory.
107 .ipython/ directory.
116
108
117 Parameters
109 Parameters
118 ----------
110 ----------
119 ipythondir : path
111 ipythondir : path
120 The directory to be used for installation/upgrade. In 'install' mode,
112 The directory to be used for installation/upgrade. In 'install' mode,
121 if this path already exists, the function exits immediately.
113 if this path already exists, the function exits immediately.
122
114
123 rc_suffix : str
115 rc_suffix : str
124 Extension for the config files. On *nix platforms it is typically the
116 Extension for the config files. On *nix platforms it is typically the
125 empty string, while Windows normally uses '.ini'.
117 empty string, while Windows normally uses '.ini'.
126
118
127 mode : str, optional
119 mode : str, optional
128 Valid modes are 'install' and 'upgrade'.
120 Valid modes are 'install' and 'upgrade'.
129
121
130 interactive : bool, optional
122 interactive : bool, optional
131 If False, do not wait for user input on any errors. Normally after
123 If False, do not wait for user input on any errors. Normally after
132 printing its status information, this function waits for the user to
124 printing its status information, this function waits for the user to
133 hit Return before proceeding. This is because the default use case is
125 hit Return before proceeding. This is because the default use case is
134 when first installing the IPython configuration, so we want the user to
126 when first installing the IPython configuration, so we want the user to
135 acknowledge the initial message, which contains some useful
127 acknowledge the initial message, which contains some useful
136 information.
128 information.
137 """
129 """
138
130
139 # For automatic use, deactivate all i/o
131 # For automatic use, deactivate all i/o
140 if interactive:
132 if interactive:
141 def wait():
133 def wait():
142 try:
134 try:
143 raw_input("Please press <RETURN> to start IPython.")
135 raw_input("Please press <RETURN> to start IPython.")
144 except EOFError:
136 except EOFError:
145 print >> Term.cout
137 print >> Term.cout
146 print '*'*70
138 print '*'*70
147
139
148 def printf(s):
140 def printf(s):
149 print s
141 print s
150 else:
142 else:
151 wait = lambda : None
143 wait = lambda : None
152 printf = lambda s : None
144 printf = lambda s : None
153
145
154 # Install mode should be re-entrant: if the install dir already exists,
146 # Install mode should be re-entrant: if the install dir already exists,
155 # bail out cleanly.
147 # bail out cleanly.
156 # XXX. This is too hasty to return. We need to check to make sure that
148 # XXX. This is too hasty to return. We need to check to make sure that
157 # all the expected config files and directories are actually there. We
149 # all the expected config files and directories are actually there. We
158 # currently have a failure mode if someone deletes a needed config file
150 # currently have a failure mode if someone deletes a needed config file
159 # but still has the ipythondir.
151 # but still has the ipythondir.
160 if mode == 'install' and os.path.isdir(ipythondir):
152 if mode == 'install' and os.path.isdir(ipythondir):
161 return
153 return
162
154
163 cwd = os.getcwd() # remember where we started
155 cwd = os.getcwd() # remember where we started
164 glb = glob.glob
156 glb = glob.glob
165
157
166 printf('*'*70)
158 printf('*'*70)
167 if mode == 'install':
159 if mode == 'install':
168 printf(
160 printf(
169 """Welcome to IPython. I will try to create a personal configuration directory
161 """Welcome to IPython. I will try to create a personal configuration directory
170 where you can customize many aspects of IPython's functionality in:\n""")
162 where you can customize many aspects of IPython's functionality in:\n""")
171 else:
163 else:
172 printf('I am going to upgrade your configuration in:')
164 printf('I am going to upgrade your configuration in:')
173
165
174 printf(ipythondir)
166 printf(ipythondir)
175
167
176 rcdirend = os.path.join('IPython','UserConfig')
168 rcdirend = os.path.join('IPython','UserConfig')
177 cfg = lambda d: os.path.join(d,rcdirend)
169 cfg = lambda d: os.path.join(d,rcdirend)
178 try:
170 try:
179 rcdir = filter(os.path.isdir,map(cfg,sys.path))[0]
171 rcdir = filter(os.path.isdir,map(cfg,sys.path))[0]
180 printf("Initializing from configuration: %s" % rcdir)
172 printf("Initializing from configuration: %s" % rcdir)
181 except IndexError:
173 except IndexError:
182 warning = """
174 warning = """
183 Installation error. IPython's directory was not found.
175 Installation error. IPython's directory was not found.
184
176
185 Check the following:
177 Check the following:
186
178
187 The ipython/IPython directory should be in a directory belonging to your
179 The ipython/IPython directory should be in a directory belonging to your
188 PYTHONPATH environment variable (that is, it should be in a directory
180 PYTHONPATH environment variable (that is, it should be in a directory
189 belonging to sys.path). You can copy it explicitly there or just link to it.
181 belonging to sys.path). You can copy it explicitly there or just link to it.
190
182
191 IPython will create a minimal default configuration for you.
183 IPython will create a minimal default configuration for you.
192
184
193 """
185 """
194 warn(warning)
186 warn(warning)
195 wait()
187 wait()
196
188
197 if sys.platform =='win32':
189 if sys.platform =='win32':
198 inif = 'ipythonrc.ini'
190 inif = 'ipythonrc.ini'
199 else:
191 else:
200 inif = 'ipythonrc'
192 inif = 'ipythonrc'
201 minimal_setup = {'ipy_user_conf.py' : 'import ipy_defaults',
193 minimal_setup = {'ipy_user_conf.py' : 'import ipy_defaults',
202 inif : '# intentionally left blank' }
194 inif : '# intentionally left blank' }
203 os.makedirs(ipythondir, mode = 0777)
195 os.makedirs(ipythondir, mode = 0777)
204 for f, cont in minimal_setup.items():
196 for f, cont in minimal_setup.items():
205 # In 2.5, this can be more cleanly done using 'with'
197 # In 2.5, this can be more cleanly done using 'with'
206 fobj = file(ipythondir + '/' + f,'w')
198 fobj = file(ipythondir + '/' + f,'w')
207 fobj.write(cont)
199 fobj.write(cont)
208 fobj.close()
200 fobj.close()
209
201
210 return
202 return
211
203
212 if mode == 'install':
204 if mode == 'install':
213 try:
205 try:
214 shutil.copytree(rcdir,ipythondir)
206 shutil.copytree(rcdir,ipythondir)
215 os.chdir(ipythondir)
207 os.chdir(ipythondir)
216 rc_files = glb("ipythonrc*")
208 rc_files = glb("ipythonrc*")
217 for rc_file in rc_files:
209 for rc_file in rc_files:
218 os.rename(rc_file,rc_file+rc_suffix)
210 os.rename(rc_file,rc_file+rc_suffix)
219 except:
211 except:
220 warning = """
212 warning = """
221
213
222 There was a problem with the installation:
214 There was a problem with the installation:
223 %s
215 %s
224 Try to correct it or contact the developers if you think it's a bug.
216 Try to correct it or contact the developers if you think it's a bug.
225 IPython will proceed with builtin defaults.""" % sys.exc_info()[1]
217 IPython will proceed with builtin defaults.""" % sys.exc_info()[1]
226 warn(warning)
218 warn(warning)
227 wait()
219 wait()
228 return
220 return
229
221
230 elif mode == 'upgrade':
222 elif mode == 'upgrade':
231 try:
223 try:
232 os.chdir(ipythondir)
224 os.chdir(ipythondir)
233 except:
225 except:
234 printf("""
226 printf("""
235 Can not upgrade: changing to directory %s failed. Details:
227 Can not upgrade: changing to directory %s failed. Details:
236 %s
228 %s
237 """ % (ipythondir,sys.exc_info()[1]) )
229 """ % (ipythondir,sys.exc_info()[1]) )
238 wait()
230 wait()
239 return
231 return
240 else:
232 else:
241 sources = glb(os.path.join(rcdir,'[A-Za-z]*'))
233 sources = glb(os.path.join(rcdir,'[A-Za-z]*'))
242 for new_full_path in sources:
234 for new_full_path in sources:
243 new_filename = os.path.basename(new_full_path)
235 new_filename = os.path.basename(new_full_path)
244 if new_filename.startswith('ipythonrc'):
236 if new_filename.startswith('ipythonrc'):
245 new_filename = new_filename + rc_suffix
237 new_filename = new_filename + rc_suffix
246 # The config directory should only contain files, skip any
238 # The config directory should only contain files, skip any
247 # directories which may be there (like CVS)
239 # directories which may be there (like CVS)
248 if os.path.isdir(new_full_path):
240 if os.path.isdir(new_full_path):
249 continue
241 continue
250 if os.path.exists(new_filename):
242 if os.path.exists(new_filename):
251 old_file = new_filename+'.old'
243 old_file = new_filename+'.old'
252 if os.path.exists(old_file):
244 if os.path.exists(old_file):
253 os.remove(old_file)
245 os.remove(old_file)
254 os.rename(new_filename,old_file)
246 os.rename(new_filename,old_file)
255 shutil.copy(new_full_path,new_filename)
247 shutil.copy(new_full_path,new_filename)
256 else:
248 else:
257 raise ValueError('unrecognized mode for install: %r' % mode)
249 raise ValueError('unrecognized mode for install: %r' % mode)
258
250
259 # Fix line-endings to those native to each platform in the config
251 # Fix line-endings to those native to each platform in the config
260 # directory.
252 # directory.
261 try:
253 try:
262 os.chdir(ipythondir)
254 os.chdir(ipythondir)
263 except:
255 except:
264 printf("""
256 printf("""
265 Problem: changing to directory %s failed.
257 Problem: changing to directory %s failed.
266 Details:
258 Details:
267 %s
259 %s
268
260
269 Some configuration files may have incorrect line endings. This should not
261 Some configuration files may have incorrect line endings. This should not
270 cause any problems during execution. """ % (ipythondir,sys.exc_info()[1]) )
262 cause any problems during execution. """ % (ipythondir,sys.exc_info()[1]) )
271 wait()
263 wait()
272 else:
264 else:
273 for fname in glb('ipythonrc*'):
265 for fname in glb('ipythonrc*'):
274 try:
266 try:
275 native_line_ends(fname,backup=0)
267 native_line_ends(fname,backup=0)
276 except IOError:
268 except IOError:
277 pass
269 pass
278
270
279 if mode == 'install':
271 if mode == 'install':
280 printf("""
272 printf("""
281 Successful installation!
273 Successful installation!
282
274
283 Please read the sections 'Initial Configuration' and 'Quick Tips' in the
275 Please read the sections 'Initial Configuration' and 'Quick Tips' in the
284 IPython manual (there are both HTML and PDF versions supplied with the
276 IPython manual (there are both HTML and PDF versions supplied with the
285 distribution) to make sure that your system environment is properly configured
277 distribution) to make sure that your system environment is properly configured
286 to take advantage of IPython's features.
278 to take advantage of IPython's features.
287
279
288 Important note: the configuration system has changed! The old system is
280 Important note: the configuration system has changed! The old system is
289 still in place, but its setting may be partly overridden by the settings in
281 still in place, but its setting may be partly overridden by the settings in
290 "~/.ipython/ipy_user_conf.py" config file. Please take a look at the file
282 "~/.ipython/ipy_user_conf.py" config file. Please take a look at the file
291 if some of the new settings bother you.
283 if some of the new settings bother you.
292
284
293 """)
285 """)
294 else:
286 else:
295 printf("""
287 printf("""
296 Successful upgrade!
288 Successful upgrade!
297
289
298 All files in your directory:
290 All files in your directory:
299 %(ipythondir)s
291 %(ipythondir)s
300 which would have been overwritten by the upgrade were backed up with a .old
292 which would have been overwritten by the upgrade were backed up with a .old
301 extension. If you had made particular customizations in those files you may
293 extension. If you had made particular customizations in those files you may
302 want to merge them back into the new files.""" % locals() )
294 want to merge them back into the new files.""" % locals() )
303 wait()
295 wait()
304 os.chdir(cwd)
296 os.chdir(cwd)
305
297
306 #****************************************************************************
298 #****************************************************************************
307 # Local use exceptions
299 # Local use exceptions
308 class SpaceInInput(exceptions.Exception): pass
300 class SpaceInInput(exceptions.Exception): pass
309
301
310
302
311 #****************************************************************************
303 #****************************************************************************
312 # Local use classes
304 # Local use classes
313 class Bunch: pass
305 class Bunch: pass
314
306
315 class Undefined: pass
307 class Undefined: pass
316
308
317 class Quitter(object):
309 class Quitter(object):
318 """Simple class to handle exit, similar to Python 2.5's.
310 """Simple class to handle exit, similar to Python 2.5's.
319
311
320 It handles exiting in an ipython-safe manner, which the one in Python 2.5
312 It handles exiting in an ipython-safe manner, which the one in Python 2.5
321 doesn't do (obviously, since it doesn't know about ipython)."""
313 doesn't do (obviously, since it doesn't know about ipython)."""
322
314
323 def __init__(self,shell,name):
315 def __init__(self,shell,name):
324 self.shell = shell
316 self.shell = shell
325 self.name = name
317 self.name = name
326
318
327 def __repr__(self):
319 def __repr__(self):
328 return 'Type %s() to exit.' % self.name
320 return 'Type %s() to exit.' % self.name
329 __str__ = __repr__
321 __str__ = __repr__
330
322
331 def __call__(self):
323 def __call__(self):
332 self.shell.exit()
324 self.shell.exit()
333
325
334 class InputList(list):
326 class InputList(list):
335 """Class to store user input.
327 """Class to store user input.
336
328
337 It's basically a list, but slices return a string instead of a list, thus
329 It's basically a list, but slices return a string instead of a list, thus
338 allowing things like (assuming 'In' is an instance):
330 allowing things like (assuming 'In' is an instance):
339
331
340 exec In[4:7]
332 exec In[4:7]
341
333
342 or
334 or
343
335
344 exec In[5:9] + In[14] + In[21:25]"""
336 exec In[5:9] + In[14] + In[21:25]"""
345
337
346 def __getslice__(self,i,j):
338 def __getslice__(self,i,j):
347 return ''.join(list.__getslice__(self,i,j))
339 return ''.join(list.__getslice__(self,i,j))
348
340
349 class SyntaxTB(ultraTB.ListTB):
341 class SyntaxTB(ultraTB.ListTB):
350 """Extension which holds some state: the last exception value"""
342 """Extension which holds some state: the last exception value"""
351
343
352 def __init__(self,color_scheme = 'NoColor'):
344 def __init__(self,color_scheme = 'NoColor'):
353 ultraTB.ListTB.__init__(self,color_scheme)
345 ultraTB.ListTB.__init__(self,color_scheme)
354 self.last_syntax_error = None
346 self.last_syntax_error = None
355
347
356 def __call__(self, etype, value, elist):
348 def __call__(self, etype, value, elist):
357 self.last_syntax_error = value
349 self.last_syntax_error = value
358 ultraTB.ListTB.__call__(self,etype,value,elist)
350 ultraTB.ListTB.__call__(self,etype,value,elist)
359
351
360 def clear_err_state(self):
352 def clear_err_state(self):
361 """Return the current error state and clear it"""
353 """Return the current error state and clear it"""
362 e = self.last_syntax_error
354 e = self.last_syntax_error
363 self.last_syntax_error = None
355 self.last_syntax_error = None
364 return e
356 return e
365
357
366 #****************************************************************************
358 #****************************************************************************
367 # Main IPython class
359 # Main IPython class
368
360
369 # FIXME: the Magic class is a mixin for now, and will unfortunately remain so
361 # FIXME: the Magic class is a mixin for now, and will unfortunately remain so
370 # until a full rewrite is made. I've cleaned all cross-class uses of
362 # until a full rewrite is made. I've cleaned all cross-class uses of
371 # attributes and methods, but too much user code out there relies on the
363 # attributes and methods, but too much user code out there relies on the
372 # equlity %foo == __IP.magic_foo, so I can't actually remove the mixin usage.
364 # equlity %foo == __IP.magic_foo, so I can't actually remove the mixin usage.
373 #
365 #
374 # But at least now, all the pieces have been separated and we could, in
366 # But at least now, all the pieces have been separated and we could, in
375 # principle, stop using the mixin. This will ease the transition to the
367 # principle, stop using the mixin. This will ease the transition to the
376 # chainsaw branch.
368 # chainsaw branch.
377
369
378 # For reference, the following is the list of 'self.foo' uses in the Magic
370 # For reference, the following is the list of 'self.foo' uses in the Magic
379 # class as of 2005-12-28. These are names we CAN'T use in the main ipython
371 # class as of 2005-12-28. These are names we CAN'T use in the main ipython
380 # class, to prevent clashes.
372 # class, to prevent clashes.
381
373
382 # ['self.__class__', 'self.__dict__', 'self._inspect', 'self._ofind',
374 # ['self.__class__', 'self.__dict__', 'self._inspect', 'self._ofind',
383 # 'self.arg_err', 'self.extract_input', 'self.format_', 'self.lsmagic',
375 # 'self.arg_err', 'self.extract_input', 'self.format_', 'self.lsmagic',
384 # 'self.magic_', 'self.options_table', 'self.parse', 'self.shell',
376 # 'self.magic_', 'self.options_table', 'self.parse', 'self.shell',
385 # 'self.value']
377 # 'self.value']
386
378
387 class InteractiveShell(object,Magic):
379 class InteractiveShell(object,Magic):
388 """An enhanced console for Python."""
380 """An enhanced console for Python."""
389
381
390 # class attribute to indicate whether the class supports threads or not.
382 # class attribute to indicate whether the class supports threads or not.
391 # Subclasses with thread support should override this as needed.
383 # Subclasses with thread support should override this as needed.
392 isthreaded = False
384 isthreaded = False
393
385
394 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
386 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
395 user_ns=None,user_global_ns=None,banner2='',
387 user_ns=None,user_global_ns=None,banner2='',
396 custom_exceptions=((),None),embedded=False):
388 custom_exceptions=((),None),embedded=False):
397
389
398 # log system
390 # log system
399 self.logger = Logger(self,logfname='ipython_log.py',logmode='rotate')
391 self.logger = Logger(self,logfname='ipython_log.py',logmode='rotate')
400
392
401 # Job manager (for jobs run as background threads)
393 # Job manager (for jobs run as background threads)
402 self.jobs = BackgroundJobManager()
394 self.jobs = BackgroundJobManager()
403
395
404 # Store the actual shell's name
396 # Store the actual shell's name
405 self.name = name
397 self.name = name
406 self.more = False
398 self.more = False
407
399
408 # We need to know whether the instance is meant for embedding, since
400 # We need to know whether the instance is meant for embedding, since
409 # global/local namespaces need to be handled differently in that case
401 # global/local namespaces need to be handled differently in that case
410 self.embedded = embedded
402 self.embedded = embedded
411 if embedded:
403 if embedded:
412 # Control variable so users can, from within the embedded instance,
404 # Control variable so users can, from within the embedded instance,
413 # permanently deactivate it.
405 # permanently deactivate it.
414 self.embedded_active = True
406 self.embedded_active = True
415
407
416 # command compiler
408 # command compiler
417 self.compile = codeop.CommandCompiler()
409 self.compile = codeop.CommandCompiler()
418
410
419 # User input buffer
411 # User input buffer
420 self.buffer = []
412 self.buffer = []
421
413
422 # Default name given in compilation of code
414 # Default name given in compilation of code
423 self.filename = '<ipython console>'
415 self.filename = '<ipython console>'
424
416
425 # Install our own quitter instead of the builtins. For python2.3-2.4,
417 # Install our own quitter instead of the builtins. For python2.3-2.4,
426 # this brings in behavior like 2.5, and for 2.5 it's identical.
418 # this brings in behavior like 2.5, and for 2.5 it's identical.
427 __builtin__.exit = Quitter(self,'exit')
419 __builtin__.exit = Quitter(self,'exit')
428 __builtin__.quit = Quitter(self,'quit')
420 __builtin__.quit = Quitter(self,'quit')
429
421
430 # Make an empty namespace, which extension writers can rely on both
422 # Make an empty namespace, which extension writers can rely on both
431 # existing and NEVER being used by ipython itself. This gives them a
423 # existing and NEVER being used by ipython itself. This gives them a
432 # convenient location for storing additional information and state
424 # convenient location for storing additional information and state
433 # their extensions may require, without fear of collisions with other
425 # their extensions may require, without fear of collisions with other
434 # ipython names that may develop later.
426 # ipython names that may develop later.
435 self.meta = Struct()
427 self.meta = Struct()
436
428
437 # Create the namespace where the user will operate. user_ns is
429 # Create the namespace where the user will operate. user_ns is
438 # normally the only one used, and it is passed to the exec calls as
430 # normally the only one used, and it is passed to the exec calls as
439 # the locals argument. But we do carry a user_global_ns namespace
431 # the locals argument. But we do carry a user_global_ns namespace
440 # given as the exec 'globals' argument, This is useful in embedding
432 # given as the exec 'globals' argument, This is useful in embedding
441 # situations where the ipython shell opens in a context where the
433 # situations where the ipython shell opens in a context where the
442 # distinction between locals and globals is meaningful. For
434 # distinction between locals and globals is meaningful. For
443 # non-embedded contexts, it is just the same object as the user_ns dict.
435 # non-embedded contexts, it is just the same object as the user_ns dict.
444
436
445 # FIXME. For some strange reason, __builtins__ is showing up at user
437 # FIXME. For some strange reason, __builtins__ is showing up at user
446 # level as a dict instead of a module. This is a manual fix, but I
438 # level as a dict instead of a module. This is a manual fix, but I
447 # should really track down where the problem is coming from. Alex
439 # should really track down where the problem is coming from. Alex
448 # Schmolck reported this problem first.
440 # Schmolck reported this problem first.
449
441
450 # A useful post by Alex Martelli on this topic:
442 # A useful post by Alex Martelli on this topic:
451 # Re: inconsistent value from __builtins__
443 # Re: inconsistent value from __builtins__
452 # Von: Alex Martelli <aleaxit@yahoo.com>
444 # Von: Alex Martelli <aleaxit@yahoo.com>
453 # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends
445 # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends
454 # Gruppen: comp.lang.python
446 # Gruppen: comp.lang.python
455
447
456 # Michael Hohn <hohn@hooknose.lbl.gov> wrote:
448 # Michael Hohn <hohn@hooknose.lbl.gov> wrote:
457 # > >>> print type(builtin_check.get_global_binding('__builtins__'))
449 # > >>> print type(builtin_check.get_global_binding('__builtins__'))
458 # > <type 'dict'>
450 # > <type 'dict'>
459 # > >>> print type(__builtins__)
451 # > >>> print type(__builtins__)
460 # > <type 'module'>
452 # > <type 'module'>
461 # > Is this difference in return value intentional?
453 # > Is this difference in return value intentional?
462
454
463 # Well, it's documented that '__builtins__' can be either a dictionary
455 # Well, it's documented that '__builtins__' can be either a dictionary
464 # or a module, and it's been that way for a long time. Whether it's
456 # or a module, and it's been that way for a long time. Whether it's
465 # intentional (or sensible), I don't know. In any case, the idea is
457 # intentional (or sensible), I don't know. In any case, the idea is
466 # that if you need to access the built-in namespace directly, you
458 # that if you need to access the built-in namespace directly, you
467 # should start with "import __builtin__" (note, no 's') which will
459 # should start with "import __builtin__" (note, no 's') which will
468 # definitely give you a module. Yeah, it's somewhat confusing:-(.
460 # definitely give you a module. Yeah, it's somewhat confusing:-(.
469
461
470 # These routines return properly built dicts as needed by the rest of
462 # These routines return properly built dicts as needed by the rest of
471 # the code, and can also be used by extension writers to generate
463 # the code, and can also be used by extension writers to generate
472 # properly initialized namespaces.
464 # properly initialized namespaces.
473 user_ns, user_global_ns = IPython.ipapi.make_user_namespaces(user_ns,
465 user_ns, user_global_ns = IPython.ipapi.make_user_namespaces(user_ns,
474 user_global_ns)
466 user_global_ns)
475
467
476 # Assign namespaces
468 # Assign namespaces
477 # This is the namespace where all normal user variables live
469 # This is the namespace where all normal user variables live
478 self.user_ns = user_ns
470 self.user_ns = user_ns
479 self.user_global_ns = user_global_ns
471 self.user_global_ns = user_global_ns
480
472
481 # An auxiliary namespace that checks what parts of the user_ns were
473 # An auxiliary namespace that checks what parts of the user_ns were
482 # loaded at startup, so we can list later only variables defined in
474 # loaded at startup, so we can list later only variables defined in
483 # actual interactive use. Since it is always a subset of user_ns, it
475 # actual interactive use. Since it is always a subset of user_ns, it
484 # doesn't need to be seaparately tracked in the ns_table
476 # doesn't need to be seaparately tracked in the ns_table
485 self.user_config_ns = {}
477 self.user_config_ns = {}
486
478
487 # A namespace to keep track of internal data structures to prevent
479 # A namespace to keep track of internal data structures to prevent
488 # them from cluttering user-visible stuff. Will be updated later
480 # them from cluttering user-visible stuff. Will be updated later
489 self.internal_ns = {}
481 self.internal_ns = {}
490
482
491 # Namespace of system aliases. Each entry in the alias
483 # Namespace of system aliases. Each entry in the alias
492 # table must be a 2-tuple of the form (N,name), where N is the number
484 # table must be a 2-tuple of the form (N,name), where N is the number
493 # of positional arguments of the alias.
485 # of positional arguments of the alias.
494 self.alias_table = {}
486 self.alias_table = {}
495
487
496 # Now that FakeModule produces a real module, we've run into a nasty
488 # Now that FakeModule produces a real module, we've run into a nasty
497 # problem: after script execution (via %run), the module where the user
489 # problem: after script execution (via %run), the module where the user
498 # code ran is deleted. Now that this object is a true module (needed
490 # code ran is deleted. Now that this object is a true module (needed
499 # so docetst and other tools work correctly), the Python module
491 # so docetst and other tools work correctly), the Python module
500 # teardown mechanism runs over it, and sets to None every variable
492 # teardown mechanism runs over it, and sets to None every variable
501 # present in that module. Top-level references to objects from the
493 # present in that module. Top-level references to objects from the
502 # script survive, because the user_ns is updated with them. However,
494 # script survive, because the user_ns is updated with them. However,
503 # calling functions defined in the script that use other things from
495 # calling functions defined in the script that use other things from
504 # the script will fail, because the function's closure had references
496 # the script will fail, because the function's closure had references
505 # to the original objects, which are now all None. So we must protect
497 # to the original objects, which are now all None. So we must protect
506 # these modules from deletion by keeping a cache.
498 # these modules from deletion by keeping a cache.
507 #
499 #
508 # To avoid keeping stale modules around (we only need the one from the
500 # To avoid keeping stale modules around (we only need the one from the
509 # last run), we use a dict keyed with the full path to the script, so
501 # last run), we use a dict keyed with the full path to the script, so
510 # only the last version of the module is held in the cache. Note,
502 # only the last version of the module is held in the cache. Note,
511 # however, that we must cache the module *namespace contents* (their
503 # however, that we must cache the module *namespace contents* (their
512 # __dict__). Because if we try to cache the actual modules, old ones
504 # __dict__). Because if we try to cache the actual modules, old ones
513 # (uncached) could be destroyed while still holding references (such as
505 # (uncached) could be destroyed while still holding references (such as
514 # those held by GUI objects that tend to be long-lived)>
506 # those held by GUI objects that tend to be long-lived)>
515 #
507 #
516 # The %reset command will flush this cache. See the cache_main_mod()
508 # The %reset command will flush this cache. See the cache_main_mod()
517 # and clear_main_mod_cache() methods for details on use.
509 # and clear_main_mod_cache() methods for details on use.
518
510
519 # This is the cache used for 'main' namespaces
511 # This is the cache used for 'main' namespaces
520 self._main_ns_cache = {}
512 self._main_ns_cache = {}
521 # And this is the single instance of FakeModule whose __dict__ we keep
513 # And this is the single instance of FakeModule whose __dict__ we keep
522 # copying and clearing for reuse on each %run
514 # copying and clearing for reuse on each %run
523 self._user_main_module = FakeModule()
515 self._user_main_module = FakeModule()
524
516
525 # A table holding all the namespaces IPython deals with, so that
517 # A table holding all the namespaces IPython deals with, so that
526 # introspection facilities can search easily.
518 # introspection facilities can search easily.
527 self.ns_table = {'user':user_ns,
519 self.ns_table = {'user':user_ns,
528 'user_global':user_global_ns,
520 'user_global':user_global_ns,
529 'alias':self.alias_table,
521 'alias':self.alias_table,
530 'internal':self.internal_ns,
522 'internal':self.internal_ns,
531 'builtin':__builtin__.__dict__
523 'builtin':__builtin__.__dict__
532 }
524 }
533
525
534 # Similarly, track all namespaces where references can be held and that
526 # Similarly, track all namespaces where references can be held and that
535 # we can safely clear (so it can NOT include builtin). This one can be
527 # we can safely clear (so it can NOT include builtin). This one can be
536 # a simple list.
528 # a simple list.
537 self.ns_refs_table = [ user_ns, user_global_ns, self.user_config_ns,
529 self.ns_refs_table = [ user_ns, user_global_ns, self.user_config_ns,
538 self.alias_table, self.internal_ns,
530 self.alias_table, self.internal_ns,
539 self._main_ns_cache ]
531 self._main_ns_cache ]
540
532
541 # We need to insert into sys.modules something that looks like a
533 # We need to insert into sys.modules something that looks like a
542 # module but which accesses the IPython namespace, for shelve and
534 # module but which accesses the IPython namespace, for shelve and
543 # pickle to work interactively. Normally they rely on getting
535 # pickle to work interactively. Normally they rely on getting
544 # everything out of __main__, but for embedding purposes each IPython
536 # everything out of __main__, but for embedding purposes each IPython
545 # instance has its own private namespace, so we can't go shoving
537 # instance has its own private namespace, so we can't go shoving
546 # everything into __main__.
538 # everything into __main__.
547
539
548 # note, however, that we should only do this for non-embedded
540 # note, however, that we should only do this for non-embedded
549 # ipythons, which really mimic the __main__.__dict__ with their own
541 # ipythons, which really mimic the __main__.__dict__ with their own
550 # namespace. Embedded instances, on the other hand, should not do
542 # namespace. Embedded instances, on the other hand, should not do
551 # this because they need to manage the user local/global namespaces
543 # this because they need to manage the user local/global namespaces
552 # only, but they live within a 'normal' __main__ (meaning, they
544 # only, but they live within a 'normal' __main__ (meaning, they
553 # shouldn't overtake the execution environment of the script they're
545 # shouldn't overtake the execution environment of the script they're
554 # embedded in).
546 # embedded in).
555
547
556 if not embedded:
548 if not embedded:
557 try:
549 try:
558 main_name = self.user_ns['__name__']
550 main_name = self.user_ns['__name__']
559 except KeyError:
551 except KeyError:
560 raise KeyError,'user_ns dictionary MUST have a "__name__" key'
552 raise KeyError,'user_ns dictionary MUST have a "__name__" key'
561 else:
553 else:
562 #print "pickle hack in place" # dbg
554 #print "pickle hack in place" # dbg
563 #print 'main_name:',main_name # dbg
555 #print 'main_name:',main_name # dbg
564 sys.modules[main_name] = FakeModule(self.user_ns)
556 sys.modules[main_name] = FakeModule(self.user_ns)
565
557
566 # List of input with multi-line handling.
558 # List of input with multi-line handling.
567 self.input_hist = InputList()
559 self.input_hist = InputList()
568 # This one will hold the 'raw' input history, without any
560 # This one will hold the 'raw' input history, without any
569 # pre-processing. This will allow users to retrieve the input just as
561 # pre-processing. This will allow users to retrieve the input just as
570 # it was exactly typed in by the user, with %hist -r.
562 # it was exactly typed in by the user, with %hist -r.
571 self.input_hist_raw = InputList()
563 self.input_hist_raw = InputList()
572
564
573 # list of visited directories
565 # list of visited directories
574 try:
566 try:
575 self.dir_hist = [os.getcwd()]
567 self.dir_hist = [os.getcwd()]
576 except OSError:
568 except OSError:
577 self.dir_hist = []
569 self.dir_hist = []
578
570
579 # dict of output history
571 # dict of output history
580 self.output_hist = {}
572 self.output_hist = {}
581
573
582 # Get system encoding at startup time. Certain terminals (like Emacs
574 # Get system encoding at startup time. Certain terminals (like Emacs
583 # under Win32 have it set to None, and we need to have a known valid
575 # under Win32 have it set to None, and we need to have a known valid
584 # encoding to use in the raw_input() method
576 # encoding to use in the raw_input() method
585 try:
577 try:
586 self.stdin_encoding = sys.stdin.encoding or 'ascii'
578 self.stdin_encoding = sys.stdin.encoding or 'ascii'
587 except AttributeError:
579 except AttributeError:
588 self.stdin_encoding = 'ascii'
580 self.stdin_encoding = 'ascii'
589
581
590 # dict of things NOT to alias (keywords, builtins and some magics)
582 # dict of things NOT to alias (keywords, builtins and some magics)
591 no_alias = {}
583 no_alias = {}
592 no_alias_magics = ['cd','popd','pushd','dhist','alias','unalias']
584 no_alias_magics = ['cd','popd','pushd','dhist','alias','unalias']
593 for key in keyword.kwlist + no_alias_magics:
585 for key in keyword.kwlist + no_alias_magics:
594 no_alias[key] = 1
586 no_alias[key] = 1
595 no_alias.update(__builtin__.__dict__)
587 no_alias.update(__builtin__.__dict__)
596 self.no_alias = no_alias
588 self.no_alias = no_alias
597
589
598 # Object variable to store code object waiting execution. This is
590 # Object variable to store code object waiting execution. This is
599 # used mainly by the multithreaded shells, but it can come in handy in
591 # used mainly by the multithreaded shells, but it can come in handy in
600 # other situations. No need to use a Queue here, since it's a single
592 # other situations. No need to use a Queue here, since it's a single
601 # item which gets cleared once run.
593 # item which gets cleared once run.
602 self.code_to_run = None
594 self.code_to_run = None
603
595
604 # escapes for automatic behavior on the command line
596 # escapes for automatic behavior on the command line
605 self.ESC_SHELL = '!'
597 self.ESC_SHELL = '!'
606 self.ESC_SH_CAP = '!!'
598 self.ESC_SH_CAP = '!!'
607 self.ESC_HELP = '?'
599 self.ESC_HELP = '?'
608 self.ESC_MAGIC = '%'
600 self.ESC_MAGIC = '%'
609 self.ESC_QUOTE = ','
601 self.ESC_QUOTE = ','
610 self.ESC_QUOTE2 = ';'
602 self.ESC_QUOTE2 = ';'
611 self.ESC_PAREN = '/'
603 self.ESC_PAREN = '/'
612
604
613 # And their associated handlers
605 # And their associated handlers
614 self.esc_handlers = {self.ESC_PAREN : self.handle_auto,
606 self.esc_handlers = {self.ESC_PAREN : self.handle_auto,
615 self.ESC_QUOTE : self.handle_auto,
607 self.ESC_QUOTE : self.handle_auto,
616 self.ESC_QUOTE2 : self.handle_auto,
608 self.ESC_QUOTE2 : self.handle_auto,
617 self.ESC_MAGIC : self.handle_magic,
609 self.ESC_MAGIC : self.handle_magic,
618 self.ESC_HELP : self.handle_help,
610 self.ESC_HELP : self.handle_help,
619 self.ESC_SHELL : self.handle_shell_escape,
611 self.ESC_SHELL : self.handle_shell_escape,
620 self.ESC_SH_CAP : self.handle_shell_escape,
612 self.ESC_SH_CAP : self.handle_shell_escape,
621 }
613 }
622
614
623 # class initializations
615 # class initializations
624 Magic.__init__(self,self)
616 Magic.__init__(self,self)
625
617
626 # Python source parser/formatter for syntax highlighting
618 # Python source parser/formatter for syntax highlighting
627 pyformat = PyColorize.Parser().format
619 pyformat = PyColorize.Parser().format
628 self.pycolorize = lambda src: pyformat(src,'str',self.rc['colors'])
620 self.pycolorize = lambda src: pyformat(src,'str',self.rc['colors'])
629
621
630 # hooks holds pointers used for user-side customizations
622 # hooks holds pointers used for user-side customizations
631 self.hooks = Struct()
623 self.hooks = Struct()
632
624
633 self.strdispatchers = {}
625 self.strdispatchers = {}
634
626
635 # Set all default hooks, defined in the IPython.hooks module.
627 # Set all default hooks, defined in the IPython.hooks module.
636 hooks = IPython.hooks
628 hooks = IPython.hooks
637 for hook_name in hooks.__all__:
629 for hook_name in hooks.__all__:
638 # default hooks have priority 100, i.e. low; user hooks should have
630 # default hooks have priority 100, i.e. low; user hooks should have
639 # 0-100 priority
631 # 0-100 priority
640 self.set_hook(hook_name,getattr(hooks,hook_name), 100)
632 self.set_hook(hook_name,getattr(hooks,hook_name), 100)
641 #print "bound hook",hook_name
633 #print "bound hook",hook_name
642
634
643 # Flag to mark unconditional exit
635 # Flag to mark unconditional exit
644 self.exit_now = False
636 self.exit_now = False
645
637
646 self.usage_min = """\
638 self.usage_min = """\
647 An enhanced console for Python.
639 An enhanced console for Python.
648 Some of its features are:
640 Some of its features are:
649 - Readline support if the readline library is present.
641 - Readline support if the readline library is present.
650 - Tab completion in the local namespace.
642 - Tab completion in the local namespace.
651 - Logging of input, see command-line options.
643 - Logging of input, see command-line options.
652 - System shell escape via ! , eg !ls.
644 - System shell escape via ! , eg !ls.
653 - Magic commands, starting with a % (like %ls, %pwd, %cd, etc.)
645 - Magic commands, starting with a % (like %ls, %pwd, %cd, etc.)
654 - Keeps track of locally defined variables via %who, %whos.
646 - Keeps track of locally defined variables via %who, %whos.
655 - Show object information with a ? eg ?x or x? (use ?? for more info).
647 - Show object information with a ? eg ?x or x? (use ?? for more info).
656 """
648 """
657 if usage: self.usage = usage
649 if usage: self.usage = usage
658 else: self.usage = self.usage_min
650 else: self.usage = self.usage_min
659
651
660 # Storage
652 # Storage
661 self.rc = rc # This will hold all configuration information
653 self.rc = rc # This will hold all configuration information
662 self.pager = 'less'
654 self.pager = 'less'
663 # temporary files used for various purposes. Deleted at exit.
655 # temporary files used for various purposes. Deleted at exit.
664 self.tempfiles = []
656 self.tempfiles = []
665
657
666 # Keep track of readline usage (later set by init_readline)
658 # Keep track of readline usage (later set by init_readline)
667 self.has_readline = False
659 self.has_readline = False
668
660
669 # template for logfile headers. It gets resolved at runtime by the
661 # template for logfile headers. It gets resolved at runtime by the
670 # logstart method.
662 # logstart method.
671 self.loghead_tpl = \
663 self.loghead_tpl = \
672 """#log# Automatic Logger file. *** THIS MUST BE THE FIRST LINE ***
664 """#log# Automatic Logger file. *** THIS MUST BE THE FIRST LINE ***
673 #log# DO NOT CHANGE THIS LINE OR THE TWO BELOW
665 #log# DO NOT CHANGE THIS LINE OR THE TWO BELOW
674 #log# opts = %s
666 #log# opts = %s
675 #log# args = %s
667 #log# args = %s
676 #log# It is safe to make manual edits below here.
668 #log# It is safe to make manual edits below here.
677 #log#-----------------------------------------------------------------------
669 #log#-----------------------------------------------------------------------
678 """
670 """
679 # for pushd/popd management
671 # for pushd/popd management
680 try:
672 try:
681 self.home_dir = get_home_dir()
673 self.home_dir = get_home_dir()
682 except HomeDirError,msg:
674 except HomeDirError,msg:
683 fatal(msg)
675 fatal(msg)
684
676
685 self.dir_stack = []
677 self.dir_stack = []
686
678
687 # Functions to call the underlying shell.
679 # Functions to call the underlying shell.
688
680
689 # The first is similar to os.system, but it doesn't return a value,
681 # The first is similar to os.system, but it doesn't return a value,
690 # and it allows interpolation of variables in the user's namespace.
682 # and it allows interpolation of variables in the user's namespace.
691 self.system = lambda cmd: \
683 self.system = lambda cmd: \
692 self.hooks.shell_hook(self.var_expand(cmd,depth=2))
684 self.hooks.shell_hook(self.var_expand(cmd,depth=2))
693
685
694 # These are for getoutput and getoutputerror:
686 # These are for getoutput and getoutputerror:
695 self.getoutput = lambda cmd: \
687 self.getoutput = lambda cmd: \
696 getoutput(self.var_expand(cmd,depth=2),
688 getoutput(self.var_expand(cmd,depth=2),
697 header=self.rc.system_header,
689 header=self.rc.system_header,
698 verbose=self.rc.system_verbose)
690 verbose=self.rc.system_verbose)
699
691
700 self.getoutputerror = lambda cmd: \
692 self.getoutputerror = lambda cmd: \
701 getoutputerror(self.var_expand(cmd,depth=2),
693 getoutputerror(self.var_expand(cmd,depth=2),
702 header=self.rc.system_header,
694 header=self.rc.system_header,
703 verbose=self.rc.system_verbose)
695 verbose=self.rc.system_verbose)
704
696
705
697
706 # keep track of where we started running (mainly for crash post-mortem)
698 # keep track of where we started running (mainly for crash post-mortem)
707 self.starting_dir = os.getcwd()
699 self.starting_dir = os.getcwd()
708
700
709 # Various switches which can be set
701 # Various switches which can be set
710 self.CACHELENGTH = 5000 # this is cheap, it's just text
702 self.CACHELENGTH = 5000 # this is cheap, it's just text
711 self.BANNER = "Python %(version)s on %(platform)s\n" % sys.__dict__
703 self.BANNER = "Python %(version)s on %(platform)s\n" % sys.__dict__
712 self.banner2 = banner2
704 self.banner2 = banner2
713
705
714 # TraceBack handlers:
706 # TraceBack handlers:
715
707
716 # Syntax error handler.
708 # Syntax error handler.
717 self.SyntaxTB = SyntaxTB(color_scheme='NoColor')
709 self.SyntaxTB = SyntaxTB(color_scheme='NoColor')
718
710
719 # The interactive one is initialized with an offset, meaning we always
711 # The interactive one is initialized with an offset, meaning we always
720 # want to remove the topmost item in the traceback, which is our own
712 # want to remove the topmost item in the traceback, which is our own
721 # internal code. Valid modes: ['Plain','Context','Verbose']
713 # internal code. Valid modes: ['Plain','Context','Verbose']
722 self.InteractiveTB = ultraTB.AutoFormattedTB(mode = 'Plain',
714 self.InteractiveTB = ultraTB.AutoFormattedTB(mode = 'Plain',
723 color_scheme='NoColor',
715 color_scheme='NoColor',
724 tb_offset = 1)
716 tb_offset = 1)
725
717
726 # IPython itself shouldn't crash. This will produce a detailed
718 # IPython itself shouldn't crash. This will produce a detailed
727 # post-mortem if it does. But we only install the crash handler for
719 # post-mortem if it does. But we only install the crash handler for
728 # non-threaded shells, the threaded ones use a normal verbose reporter
720 # non-threaded shells, the threaded ones use a normal verbose reporter
729 # and lose the crash handler. This is because exceptions in the main
721 # and lose the crash handler. This is because exceptions in the main
730 # thread (such as in GUI code) propagate directly to sys.excepthook,
722 # thread (such as in GUI code) propagate directly to sys.excepthook,
731 # and there's no point in printing crash dumps for every user exception.
723 # and there's no point in printing crash dumps for every user exception.
732 if self.isthreaded:
724 if self.isthreaded:
733 ipCrashHandler = ultraTB.FormattedTB()
725 ipCrashHandler = ultraTB.FormattedTB()
734 else:
726 else:
735 from IPython import CrashHandler
727 from IPython import CrashHandler
736 ipCrashHandler = CrashHandler.IPythonCrashHandler(self)
728 ipCrashHandler = CrashHandler.IPythonCrashHandler(self)
737 self.set_crash_handler(ipCrashHandler)
729 self.set_crash_handler(ipCrashHandler)
738
730
739 # and add any custom exception handlers the user may have specified
731 # and add any custom exception handlers the user may have specified
740 self.set_custom_exc(*custom_exceptions)
732 self.set_custom_exc(*custom_exceptions)
741
733
742 # indentation management
734 # indentation management
743 self.autoindent = False
735 self.autoindent = False
744 self.indent_current_nsp = 0
736 self.indent_current_nsp = 0
745
737
746 # Make some aliases automatically
738 # Make some aliases automatically
747 # Prepare list of shell aliases to auto-define
739 # Prepare list of shell aliases to auto-define
748 if os.name == 'posix':
740 if os.name == 'posix':
749 auto_alias = ('mkdir mkdir', 'rmdir rmdir',
741 auto_alias = ('mkdir mkdir', 'rmdir rmdir',
750 'mv mv -i','rm rm -i','cp cp -i',
742 'mv mv -i','rm rm -i','cp cp -i',
751 'cat cat','less less','clear clear',
743 'cat cat','less less','clear clear',
752 # a better ls
744 # a better ls
753 'ls ls -F',
745 'ls ls -F',
754 # long ls
746 # long ls
755 'll ls -lF')
747 'll ls -lF')
756 # Extra ls aliases with color, which need special treatment on BSD
748 # Extra ls aliases with color, which need special treatment on BSD
757 # variants
749 # variants
758 ls_extra = ( # color ls
750 ls_extra = ( # color ls
759 'lc ls -F -o --color',
751 'lc ls -F -o --color',
760 # ls normal files only
752 # ls normal files only
761 'lf ls -F -o --color %l | grep ^-',
753 'lf ls -F -o --color %l | grep ^-',
762 # ls symbolic links
754 # ls symbolic links
763 'lk ls -F -o --color %l | grep ^l',
755 'lk ls -F -o --color %l | grep ^l',
764 # directories or links to directories,
756 # directories or links to directories,
765 'ldir ls -F -o --color %l | grep /$',
757 'ldir ls -F -o --color %l | grep /$',
766 # things which are executable
758 # things which are executable
767 'lx ls -F -o --color %l | grep ^-..x',
759 'lx ls -F -o --color %l | grep ^-..x',
768 )
760 )
769 # The BSDs don't ship GNU ls, so they don't understand the
761 # The BSDs don't ship GNU ls, so they don't understand the
770 # --color switch out of the box
762 # --color switch out of the box
771 if 'bsd' in sys.platform:
763 if 'bsd' in sys.platform:
772 ls_extra = ( # ls normal files only
764 ls_extra = ( # ls normal files only
773 'lf ls -lF | grep ^-',
765 'lf ls -lF | grep ^-',
774 # ls symbolic links
766 # ls symbolic links
775 'lk ls -lF | grep ^l',
767 'lk ls -lF | grep ^l',
776 # directories or links to directories,
768 # directories or links to directories,
777 'ldir ls -lF | grep /$',
769 'ldir ls -lF | grep /$',
778 # things which are executable
770 # things which are executable
779 'lx ls -lF | grep ^-..x',
771 'lx ls -lF | grep ^-..x',
780 )
772 )
781 auto_alias = auto_alias + ls_extra
773 auto_alias = auto_alias + ls_extra
782 elif os.name in ['nt','dos']:
774 elif os.name in ['nt','dos']:
783 auto_alias = ('ls dir /on',
775 auto_alias = ('ls dir /on',
784 'ddir dir /ad /on', 'ldir dir /ad /on',
776 'ddir dir /ad /on', 'ldir dir /ad /on',
785 'mkdir mkdir','rmdir rmdir','echo echo',
777 'mkdir mkdir','rmdir rmdir','echo echo',
786 'ren ren','cls cls','copy copy')
778 'ren ren','cls cls','copy copy')
787 else:
779 else:
788 auto_alias = ()
780 auto_alias = ()
789 self.auto_alias = [s.split(None,1) for s in auto_alias]
781 self.auto_alias = [s.split(None,1) for s in auto_alias]
790
782
791 # Produce a public API instance
783 # Produce a public API instance
792 self.api = IPython.ipapi.IPApi(self)
784 self.api = IPython.ipapi.IPApi(self)
793
785
794 # Initialize all user-visible namespaces
786 # Initialize all user-visible namespaces
795 self.init_namespaces()
787 self.init_namespaces()
796
788
797 # Call the actual (public) initializer
789 # Call the actual (public) initializer
798 self.init_auto_alias()
790 self.init_auto_alias()
799
791
800 # track which builtins we add, so we can clean up later
792 # track which builtins we add, so we can clean up later
801 self.builtins_added = {}
793 self.builtins_added = {}
802 # This method will add the necessary builtins for operation, but
794 # This method will add the necessary builtins for operation, but
803 # tracking what it did via the builtins_added dict.
795 # tracking what it did via the builtins_added dict.
804
796
805 #TODO: remove this, redundant
797 #TODO: remove this, redundant
806 self.add_builtins()
798 self.add_builtins()
807 # end __init__
799 # end __init__
808
800
809 def var_expand(self,cmd,depth=0):
801 def var_expand(self,cmd,depth=0):
810 """Expand python variables in a string.
802 """Expand python variables in a string.
811
803
812 The depth argument indicates how many frames above the caller should
804 The depth argument indicates how many frames above the caller should
813 be walked to look for the local namespace where to expand variables.
805 be walked to look for the local namespace where to expand variables.
814
806
815 The global namespace for expansion is always the user's interactive
807 The global namespace for expansion is always the user's interactive
816 namespace.
808 namespace.
817 """
809 """
818
810
819 return str(ItplNS(cmd,
811 return str(ItplNS(cmd,
820 self.user_ns, # globals
812 self.user_ns, # globals
821 # Skip our own frame in searching for locals:
813 # Skip our own frame in searching for locals:
822 sys._getframe(depth+1).f_locals # locals
814 sys._getframe(depth+1).f_locals # locals
823 ))
815 ))
824
816
825 def pre_config_initialization(self):
817 def pre_config_initialization(self):
826 """Pre-configuration init method
818 """Pre-configuration init method
827
819
828 This is called before the configuration files are processed to
820 This is called before the configuration files are processed to
829 prepare the services the config files might need.
821 prepare the services the config files might need.
830
822
831 self.rc already has reasonable default values at this point.
823 self.rc already has reasonable default values at this point.
832 """
824 """
833 rc = self.rc
825 rc = self.rc
834 try:
826 try:
835 self.db = pickleshare.PickleShareDB(rc.ipythondir + "/db")
827 self.db = pickleshare.PickleShareDB(rc.ipythondir + "/db")
836 except exceptions.UnicodeDecodeError:
828 except exceptions.UnicodeDecodeError:
837 print "Your ipythondir can't be decoded to unicode!"
829 print "Your ipythondir can't be decoded to unicode!"
838 print "Please set HOME environment variable to something that"
830 print "Please set HOME environment variable to something that"
839 print r"only has ASCII characters, e.g. c:\home"
831 print r"only has ASCII characters, e.g. c:\home"
840 print "Now it is",rc.ipythondir
832 print "Now it is",rc.ipythondir
841 sys.exit()
833 sys.exit()
842 self.shadowhist = IPython.history.ShadowHist(self.db)
834 self.shadowhist = IPython.history.ShadowHist(self.db)
843
835
844 def post_config_initialization(self):
836 def post_config_initialization(self):
845 """Post configuration init method
837 """Post configuration init method
846
838
847 This is called after the configuration files have been processed to
839 This is called after the configuration files have been processed to
848 'finalize' the initialization."""
840 'finalize' the initialization."""
849
841
850 rc = self.rc
842 rc = self.rc
851
843
852 # Object inspector
844 # Object inspector
853 self.inspector = OInspect.Inspector(OInspect.InspectColors,
845 self.inspector = OInspect.Inspector(OInspect.InspectColors,
854 PyColorize.ANSICodeColors,
846 PyColorize.ANSICodeColors,
855 'NoColor',
847 'NoColor',
856 rc.object_info_string_level)
848 rc.object_info_string_level)
857
849
858 self.rl_next_input = None
850 self.rl_next_input = None
859 self.rl_do_indent = False
851 self.rl_do_indent = False
860 # Load readline proper
852 # Load readline proper
861 if rc.readline:
853 if rc.readline:
862 self.init_readline()
854 self.init_readline()
863
855
864 # local shortcut, this is used a LOT
856 # local shortcut, this is used a LOT
865 self.log = self.logger.log
857 self.log = self.logger.log
866
858
867 # Initialize cache, set in/out prompts and printing system
859 # Initialize cache, set in/out prompts and printing system
868 self.outputcache = CachedOutput(self,
860 self.outputcache = CachedOutput(self,
869 rc.cache_size,
861 rc.cache_size,
870 rc.pprint,
862 rc.pprint,
871 input_sep = rc.separate_in,
863 input_sep = rc.separate_in,
872 output_sep = rc.separate_out,
864 output_sep = rc.separate_out,
873 output_sep2 = rc.separate_out2,
865 output_sep2 = rc.separate_out2,
874 ps1 = rc.prompt_in1,
866 ps1 = rc.prompt_in1,
875 ps2 = rc.prompt_in2,
867 ps2 = rc.prompt_in2,
876 ps_out = rc.prompt_out,
868 ps_out = rc.prompt_out,
877 pad_left = rc.prompts_pad_left)
869 pad_left = rc.prompts_pad_left)
878
870
879 # user may have over-ridden the default print hook:
871 # user may have over-ridden the default print hook:
880 try:
872 try:
881 self.outputcache.__class__.display = self.hooks.display
873 self.outputcache.__class__.display = self.hooks.display
882 except AttributeError:
874 except AttributeError:
883 pass
875 pass
884
876
885 # I don't like assigning globally to sys, because it means when
877 # I don't like assigning globally to sys, because it means when
886 # embedding instances, each embedded instance overrides the previous
878 # embedding instances, each embedded instance overrides the previous
887 # choice. But sys.displayhook seems to be called internally by exec,
879 # choice. But sys.displayhook seems to be called internally by exec,
888 # so I don't see a way around it. We first save the original and then
880 # so I don't see a way around it. We first save the original and then
889 # overwrite it.
881 # overwrite it.
890 self.sys_displayhook = sys.displayhook
882 self.sys_displayhook = sys.displayhook
891 sys.displayhook = self.outputcache
883 sys.displayhook = self.outputcache
892
884
893 # Do a proper resetting of doctest, including the necessary displayhook
885 # Do a proper resetting of doctest, including the necessary displayhook
894 # monkeypatching
886 # monkeypatching
895 try:
887 try:
896 doctest_reload()
888 doctest_reload()
897 except ImportError:
889 except ImportError:
898 warn("doctest module does not exist.")
890 warn("doctest module does not exist.")
899
891
900 # Set user colors (don't do it in the constructor above so that it
892 # Set user colors (don't do it in the constructor above so that it
901 # doesn't crash if colors option is invalid)
893 # doesn't crash if colors option is invalid)
902 self.magic_colors(rc.colors)
894 self.magic_colors(rc.colors)
903
895
904 # Set calling of pdb on exceptions
896 # Set calling of pdb on exceptions
905 self.call_pdb = rc.pdb
897 self.call_pdb = rc.pdb
906
898
907 # Load user aliases
899 # Load user aliases
908 for alias in rc.alias:
900 for alias in rc.alias:
909 self.magic_alias(alias)
901 self.magic_alias(alias)
910
902
911 self.hooks.late_startup_hook()
903 self.hooks.late_startup_hook()
912
904
913 for cmd in self.rc.autoexec:
905 for cmd in self.rc.autoexec:
914 #print "autoexec>",cmd #dbg
906 #print "autoexec>",cmd #dbg
915 self.api.runlines(cmd)
907 self.api.runlines(cmd)
916
908
917 batchrun = False
909 batchrun = False
918 for batchfile in [path(arg) for arg in self.rc.args
910 for batchfile in [path(arg) for arg in self.rc.args
919 if arg.lower().endswith('.ipy')]:
911 if arg.lower().endswith('.ipy')]:
920 if not batchfile.isfile():
912 if not batchfile.isfile():
921 print "No such batch file:", batchfile
913 print "No such batch file:", batchfile
922 continue
914 continue
923 self.api.runlines(batchfile.text())
915 self.api.runlines(batchfile.text())
924 batchrun = True
916 batchrun = True
925 # without -i option, exit after running the batch file
917 # without -i option, exit after running the batch file
926 if batchrun and not self.rc.interact:
918 if batchrun and not self.rc.interact:
927 self.ask_exit()
919 self.ask_exit()
928
920
929 def init_namespaces(self):
921 def init_namespaces(self):
930 """Initialize all user-visible namespaces to their minimum defaults.
922 """Initialize all user-visible namespaces to their minimum defaults.
931
923
932 Certain history lists are also initialized here, as they effectively
924 Certain history lists are also initialized here, as they effectively
933 act as user namespaces.
925 act as user namespaces.
934
926
935 Note
927 Note
936 ----
928 ----
937 All data structures here are only filled in, they are NOT reset by this
929 All data structures here are only filled in, they are NOT reset by this
938 method. If they were not empty before, data will simply be added to
930 method. If they were not empty before, data will simply be added to
939 therm.
931 therm.
940 """
932 """
941 # The user namespace MUST have a pointer to the shell itself.
933 # The user namespace MUST have a pointer to the shell itself.
942 self.user_ns[self.name] = self
934 self.user_ns[self.name] = self
943
935
944 # Store the public api instance
936 # Store the public api instance
945 self.user_ns['_ip'] = self.api
937 self.user_ns['_ip'] = self.api
946
938
947 # make global variables for user access to the histories
939 # make global variables for user access to the histories
948 self.user_ns['_ih'] = self.input_hist
940 self.user_ns['_ih'] = self.input_hist
949 self.user_ns['_oh'] = self.output_hist
941 self.user_ns['_oh'] = self.output_hist
950 self.user_ns['_dh'] = self.dir_hist
942 self.user_ns['_dh'] = self.dir_hist
951
943
952 # user aliases to input and output histories
944 # user aliases to input and output histories
953 self.user_ns['In'] = self.input_hist
945 self.user_ns['In'] = self.input_hist
954 self.user_ns['Out'] = self.output_hist
946 self.user_ns['Out'] = self.output_hist
955
947
956 self.user_ns['_sh'] = IPython.shadowns
948 self.user_ns['_sh'] = IPython.shadowns
957
949
958 # Fill the history zero entry, user counter starts at 1
950 # Fill the history zero entry, user counter starts at 1
959 self.input_hist.append('\n')
951 self.input_hist.append('\n')
960 self.input_hist_raw.append('\n')
952 self.input_hist_raw.append('\n')
961
953
962 def add_builtins(self):
954 def add_builtins(self):
963 """Store ipython references into the builtin namespace.
955 """Store ipython references into the builtin namespace.
964
956
965 Some parts of ipython operate via builtins injected here, which hold a
957 Some parts of ipython operate via builtins injected here, which hold a
966 reference to IPython itself."""
958 reference to IPython itself."""
967
959
968 # TODO: deprecate all of these, they are unsafe
960 # TODO: deprecate all of these, they are unsafe
969 builtins_new = dict(__IPYTHON__ = self,
961 builtins_new = dict(__IPYTHON__ = self,
970 ip_set_hook = self.set_hook,
962 ip_set_hook = self.set_hook,
971 jobs = self.jobs,
963 jobs = self.jobs,
972 ipmagic = wrap_deprecated(self.ipmagic,'_ip.magic()'),
964 ipmagic = wrap_deprecated(self.ipmagic,'_ip.magic()'),
973 ipalias = wrap_deprecated(self.ipalias),
965 ipalias = wrap_deprecated(self.ipalias),
974 ipsystem = wrap_deprecated(self.ipsystem,'_ip.system()'),
966 ipsystem = wrap_deprecated(self.ipsystem,'_ip.system()'),
975 #_ip = self.api
967 #_ip = self.api
976 )
968 )
977 for biname,bival in builtins_new.items():
969 for biname,bival in builtins_new.items():
978 try:
970 try:
979 # store the orignal value so we can restore it
971 # store the orignal value so we can restore it
980 self.builtins_added[biname] = __builtin__.__dict__[biname]
972 self.builtins_added[biname] = __builtin__.__dict__[biname]
981 except KeyError:
973 except KeyError:
982 # or mark that it wasn't defined, and we'll just delete it at
974 # or mark that it wasn't defined, and we'll just delete it at
983 # cleanup
975 # cleanup
984 self.builtins_added[biname] = Undefined
976 self.builtins_added[biname] = Undefined
985 __builtin__.__dict__[biname] = bival
977 __builtin__.__dict__[biname] = bival
986
978
987 # Keep in the builtins a flag for when IPython is active. We set it
979 # Keep in the builtins a flag for when IPython is active. We set it
988 # with setdefault so that multiple nested IPythons don't clobber one
980 # with setdefault so that multiple nested IPythons don't clobber one
989 # another. Each will increase its value by one upon being activated,
981 # another. Each will increase its value by one upon being activated,
990 # which also gives us a way to determine the nesting level.
982 # which also gives us a way to determine the nesting level.
991 __builtin__.__dict__.setdefault('__IPYTHON__active',0)
983 __builtin__.__dict__.setdefault('__IPYTHON__active',0)
992
984
993 def clean_builtins(self):
985 def clean_builtins(self):
994 """Remove any builtins which might have been added by add_builtins, or
986 """Remove any builtins which might have been added by add_builtins, or
995 restore overwritten ones to their previous values."""
987 restore overwritten ones to their previous values."""
996 for biname,bival in self.builtins_added.items():
988 for biname,bival in self.builtins_added.items():
997 if bival is Undefined:
989 if bival is Undefined:
998 del __builtin__.__dict__[biname]
990 del __builtin__.__dict__[biname]
999 else:
991 else:
1000 __builtin__.__dict__[biname] = bival
992 __builtin__.__dict__[biname] = bival
1001 self.builtins_added.clear()
993 self.builtins_added.clear()
1002
994
1003 def set_hook(self,name,hook, priority = 50, str_key = None, re_key = None):
995 def set_hook(self,name,hook, priority = 50, str_key = None, re_key = None):
1004 """set_hook(name,hook) -> sets an internal IPython hook.
996 """set_hook(name,hook) -> sets an internal IPython hook.
1005
997
1006 IPython exposes some of its internal API as user-modifiable hooks. By
998 IPython exposes some of its internal API as user-modifiable hooks. By
1007 adding your function to one of these hooks, you can modify IPython's
999 adding your function to one of these hooks, you can modify IPython's
1008 behavior to call at runtime your own routines."""
1000 behavior to call at runtime your own routines."""
1009
1001
1010 # At some point in the future, this should validate the hook before it
1002 # At some point in the future, this should validate the hook before it
1011 # accepts it. Probably at least check that the hook takes the number
1003 # accepts it. Probably at least check that the hook takes the number
1012 # of args it's supposed to.
1004 # of args it's supposed to.
1013
1005
1014 f = new.instancemethod(hook,self,self.__class__)
1006 f = new.instancemethod(hook,self,self.__class__)
1015
1007
1016 # check if the hook is for strdispatcher first
1008 # check if the hook is for strdispatcher first
1017 if str_key is not None:
1009 if str_key is not None:
1018 sdp = self.strdispatchers.get(name, StrDispatch())
1010 sdp = self.strdispatchers.get(name, StrDispatch())
1019 sdp.add_s(str_key, f, priority )
1011 sdp.add_s(str_key, f, priority )
1020 self.strdispatchers[name] = sdp
1012 self.strdispatchers[name] = sdp
1021 return
1013 return
1022 if re_key is not None:
1014 if re_key is not None:
1023 sdp = self.strdispatchers.get(name, StrDispatch())
1015 sdp = self.strdispatchers.get(name, StrDispatch())
1024 sdp.add_re(re.compile(re_key), f, priority )
1016 sdp.add_re(re.compile(re_key), f, priority )
1025 self.strdispatchers[name] = sdp
1017 self.strdispatchers[name] = sdp
1026 return
1018 return
1027
1019
1028 dp = getattr(self.hooks, name, None)
1020 dp = getattr(self.hooks, name, None)
1029 if name not in IPython.hooks.__all__:
1021 if name not in IPython.hooks.__all__:
1030 print "Warning! Hook '%s' is not one of %s" % (name, IPython.hooks.__all__ )
1022 print "Warning! Hook '%s' is not one of %s" % (name, IPython.hooks.__all__ )
1031 if not dp:
1023 if not dp:
1032 dp = IPython.hooks.CommandChainDispatcher()
1024 dp = IPython.hooks.CommandChainDispatcher()
1033
1025
1034 try:
1026 try:
1035 dp.add(f,priority)
1027 dp.add(f,priority)
1036 except AttributeError:
1028 except AttributeError:
1037 # it was not commandchain, plain old func - replace
1029 # it was not commandchain, plain old func - replace
1038 dp = f
1030 dp = f
1039
1031
1040 setattr(self.hooks,name, dp)
1032 setattr(self.hooks,name, dp)
1041
1033
1042
1034
1043 #setattr(self.hooks,name,new.instancemethod(hook,self,self.__class__))
1035 #setattr(self.hooks,name,new.instancemethod(hook,self,self.__class__))
1044
1036
1045 def set_crash_handler(self,crashHandler):
1037 def set_crash_handler(self,crashHandler):
1046 """Set the IPython crash handler.
1038 """Set the IPython crash handler.
1047
1039
1048 This must be a callable with a signature suitable for use as
1040 This must be a callable with a signature suitable for use as
1049 sys.excepthook."""
1041 sys.excepthook."""
1050
1042
1051 # Install the given crash handler as the Python exception hook
1043 # Install the given crash handler as the Python exception hook
1052 sys.excepthook = crashHandler
1044 sys.excepthook = crashHandler
1053
1045
1054 # The instance will store a pointer to this, so that runtime code
1046 # The instance will store a pointer to this, so that runtime code
1055 # (such as magics) can access it. This is because during the
1047 # (such as magics) can access it. This is because during the
1056 # read-eval loop, it gets temporarily overwritten (to deal with GUI
1048 # read-eval loop, it gets temporarily overwritten (to deal with GUI
1057 # frameworks).
1049 # frameworks).
1058 self.sys_excepthook = sys.excepthook
1050 self.sys_excepthook = sys.excepthook
1059
1051
1060
1052
1061 def set_custom_exc(self,exc_tuple,handler):
1053 def set_custom_exc(self,exc_tuple,handler):
1062 """set_custom_exc(exc_tuple,handler)
1054 """set_custom_exc(exc_tuple,handler)
1063
1055
1064 Set a custom exception handler, which will be called if any of the
1056 Set a custom exception handler, which will be called if any of the
1065 exceptions in exc_tuple occur in the mainloop (specifically, in the
1057 exceptions in exc_tuple occur in the mainloop (specifically, in the
1066 runcode() method.
1058 runcode() method.
1067
1059
1068 Inputs:
1060 Inputs:
1069
1061
1070 - exc_tuple: a *tuple* of valid exceptions to call the defined
1062 - exc_tuple: a *tuple* of valid exceptions to call the defined
1071 handler for. It is very important that you use a tuple, and NOT A
1063 handler for. It is very important that you use a tuple, and NOT A
1072 LIST here, because of the way Python's except statement works. If
1064 LIST here, because of the way Python's except statement works. If
1073 you only want to trap a single exception, use a singleton tuple:
1065 you only want to trap a single exception, use a singleton tuple:
1074
1066
1075 exc_tuple == (MyCustomException,)
1067 exc_tuple == (MyCustomException,)
1076
1068
1077 - handler: this must be defined as a function with the following
1069 - handler: this must be defined as a function with the following
1078 basic interface: def my_handler(self,etype,value,tb).
1070 basic interface: def my_handler(self,etype,value,tb).
1079
1071
1080 This will be made into an instance method (via new.instancemethod)
1072 This will be made into an instance method (via new.instancemethod)
1081 of IPython itself, and it will be called if any of the exceptions
1073 of IPython itself, and it will be called if any of the exceptions
1082 listed in the exc_tuple are caught. If the handler is None, an
1074 listed in the exc_tuple are caught. If the handler is None, an
1083 internal basic one is used, which just prints basic info.
1075 internal basic one is used, which just prints basic info.
1084
1076
1085 WARNING: by putting in your own exception handler into IPython's main
1077 WARNING: by putting in your own exception handler into IPython's main
1086 execution loop, you run a very good chance of nasty crashes. This
1078 execution loop, you run a very good chance of nasty crashes. This
1087 facility should only be used if you really know what you are doing."""
1079 facility should only be used if you really know what you are doing."""
1088
1080
1089 assert type(exc_tuple)==type(()) , \
1081 assert type(exc_tuple)==type(()) , \
1090 "The custom exceptions must be given AS A TUPLE."
1082 "The custom exceptions must be given AS A TUPLE."
1091
1083
1092 def dummy_handler(self,etype,value,tb):
1084 def dummy_handler(self,etype,value,tb):
1093 print '*** Simple custom exception handler ***'
1085 print '*** Simple custom exception handler ***'
1094 print 'Exception type :',etype
1086 print 'Exception type :',etype
1095 print 'Exception value:',value
1087 print 'Exception value:',value
1096 print 'Traceback :',tb
1088 print 'Traceback :',tb
1097 print 'Source code :','\n'.join(self.buffer)
1089 print 'Source code :','\n'.join(self.buffer)
1098
1090
1099 if handler is None: handler = dummy_handler
1091 if handler is None: handler = dummy_handler
1100
1092
1101 self.CustomTB = new.instancemethod(handler,self,self.__class__)
1093 self.CustomTB = new.instancemethod(handler,self,self.__class__)
1102 self.custom_exceptions = exc_tuple
1094 self.custom_exceptions = exc_tuple
1103
1095
1104 def set_custom_completer(self,completer,pos=0):
1096 def set_custom_completer(self,completer,pos=0):
1105 """set_custom_completer(completer,pos=0)
1097 """set_custom_completer(completer,pos=0)
1106
1098
1107 Adds a new custom completer function.
1099 Adds a new custom completer function.
1108
1100
1109 The position argument (defaults to 0) is the index in the completers
1101 The position argument (defaults to 0) is the index in the completers
1110 list where you want the completer to be inserted."""
1102 list where you want the completer to be inserted."""
1111
1103
1112 newcomp = new.instancemethod(completer,self.Completer,
1104 newcomp = new.instancemethod(completer,self.Completer,
1113 self.Completer.__class__)
1105 self.Completer.__class__)
1114 self.Completer.matchers.insert(pos,newcomp)
1106 self.Completer.matchers.insert(pos,newcomp)
1115
1107
1116 def set_completer(self):
1108 def set_completer(self):
1117 """reset readline's completer to be our own."""
1109 """reset readline's completer to be our own."""
1118 self.readline.set_completer(self.Completer.complete)
1110 self.readline.set_completer(self.Completer.complete)
1119
1111
1120 def _get_call_pdb(self):
1112 def _get_call_pdb(self):
1121 return self._call_pdb
1113 return self._call_pdb
1122
1114
1123 def _set_call_pdb(self,val):
1115 def _set_call_pdb(self,val):
1124
1116
1125 if val not in (0,1,False,True):
1117 if val not in (0,1,False,True):
1126 raise ValueError,'new call_pdb value must be boolean'
1118 raise ValueError,'new call_pdb value must be boolean'
1127
1119
1128 # store value in instance
1120 # store value in instance
1129 self._call_pdb = val
1121 self._call_pdb = val
1130
1122
1131 # notify the actual exception handlers
1123 # notify the actual exception handlers
1132 self.InteractiveTB.call_pdb = val
1124 self.InteractiveTB.call_pdb = val
1133 if self.isthreaded:
1125 if self.isthreaded:
1134 try:
1126 try:
1135 self.sys_excepthook.call_pdb = val
1127 self.sys_excepthook.call_pdb = val
1136 except:
1128 except:
1137 warn('Failed to activate pdb for threaded exception handler')
1129 warn('Failed to activate pdb for threaded exception handler')
1138
1130
1139 call_pdb = property(_get_call_pdb,_set_call_pdb,None,
1131 call_pdb = property(_get_call_pdb,_set_call_pdb,None,
1140 'Control auto-activation of pdb at exceptions')
1132 'Control auto-activation of pdb at exceptions')
1141
1133
1142 # These special functions get installed in the builtin namespace, to
1134 # These special functions get installed in the builtin namespace, to
1143 # provide programmatic (pure python) access to magics, aliases and system
1135 # provide programmatic (pure python) access to magics, aliases and system
1144 # calls. This is important for logging, user scripting, and more.
1136 # calls. This is important for logging, user scripting, and more.
1145
1137
1146 # We are basically exposing, via normal python functions, the three
1138 # We are basically exposing, via normal python functions, the three
1147 # mechanisms in which ipython offers special call modes (magics for
1139 # mechanisms in which ipython offers special call modes (magics for
1148 # internal control, aliases for direct system access via pre-selected
1140 # internal control, aliases for direct system access via pre-selected
1149 # names, and !cmd for calling arbitrary system commands).
1141 # names, and !cmd for calling arbitrary system commands).
1150
1142
1151 def ipmagic(self,arg_s):
1143 def ipmagic(self,arg_s):
1152 """Call a magic function by name.
1144 """Call a magic function by name.
1153
1145
1154 Input: a string containing the name of the magic function to call and any
1146 Input: a string containing the name of the magic function to call and any
1155 additional arguments to be passed to the magic.
1147 additional arguments to be passed to the magic.
1156
1148
1157 ipmagic('name -opt foo bar') is equivalent to typing at the ipython
1149 ipmagic('name -opt foo bar') is equivalent to typing at the ipython
1158 prompt:
1150 prompt:
1159
1151
1160 In[1]: %name -opt foo bar
1152 In[1]: %name -opt foo bar
1161
1153
1162 To call a magic without arguments, simply use ipmagic('name').
1154 To call a magic without arguments, simply use ipmagic('name').
1163
1155
1164 This provides a proper Python function to call IPython's magics in any
1156 This provides a proper Python function to call IPython's magics in any
1165 valid Python code you can type at the interpreter, including loops and
1157 valid Python code you can type at the interpreter, including loops and
1166 compound statements. It is added by IPython to the Python builtin
1158 compound statements. It is added by IPython to the Python builtin
1167 namespace upon initialization."""
1159 namespace upon initialization."""
1168
1160
1169 args = arg_s.split(' ',1)
1161 args = arg_s.split(' ',1)
1170 magic_name = args[0]
1162 magic_name = args[0]
1171 magic_name = magic_name.lstrip(self.ESC_MAGIC)
1163 magic_name = magic_name.lstrip(self.ESC_MAGIC)
1172
1164
1173 try:
1165 try:
1174 magic_args = args[1]
1166 magic_args = args[1]
1175 except IndexError:
1167 except IndexError:
1176 magic_args = ''
1168 magic_args = ''
1177 fn = getattr(self,'magic_'+magic_name,None)
1169 fn = getattr(self,'magic_'+magic_name,None)
1178 if fn is None:
1170 if fn is None:
1179 error("Magic function `%s` not found." % magic_name)
1171 error("Magic function `%s` not found." % magic_name)
1180 else:
1172 else:
1181 magic_args = self.var_expand(magic_args,1)
1173 magic_args = self.var_expand(magic_args,1)
1182 return fn(magic_args)
1174 return fn(magic_args)
1183
1175
1184 def ipalias(self,arg_s):
1176 def ipalias(self,arg_s):
1185 """Call an alias by name.
1177 """Call an alias by name.
1186
1178
1187 Input: a string containing the name of the alias to call and any
1179 Input: a string containing the name of the alias to call and any
1188 additional arguments to be passed to the magic.
1180 additional arguments to be passed to the magic.
1189
1181
1190 ipalias('name -opt foo bar') is equivalent to typing at the ipython
1182 ipalias('name -opt foo bar') is equivalent to typing at the ipython
1191 prompt:
1183 prompt:
1192
1184
1193 In[1]: name -opt foo bar
1185 In[1]: name -opt foo bar
1194
1186
1195 To call an alias without arguments, simply use ipalias('name').
1187 To call an alias without arguments, simply use ipalias('name').
1196
1188
1197 This provides a proper Python function to call IPython's aliases in any
1189 This provides a proper Python function to call IPython's aliases in any
1198 valid Python code you can type at the interpreter, including loops and
1190 valid Python code you can type at the interpreter, including loops and
1199 compound statements. It is added by IPython to the Python builtin
1191 compound statements. It is added by IPython to the Python builtin
1200 namespace upon initialization."""
1192 namespace upon initialization."""
1201
1193
1202 args = arg_s.split(' ',1)
1194 args = arg_s.split(' ',1)
1203 alias_name = args[0]
1195 alias_name = args[0]
1204 try:
1196 try:
1205 alias_args = args[1]
1197 alias_args = args[1]
1206 except IndexError:
1198 except IndexError:
1207 alias_args = ''
1199 alias_args = ''
1208 if alias_name in self.alias_table:
1200 if alias_name in self.alias_table:
1209 self.call_alias(alias_name,alias_args)
1201 self.call_alias(alias_name,alias_args)
1210 else:
1202 else:
1211 error("Alias `%s` not found." % alias_name)
1203 error("Alias `%s` not found." % alias_name)
1212
1204
1213 def ipsystem(self,arg_s):
1205 def ipsystem(self,arg_s):
1214 """Make a system call, using IPython."""
1206 """Make a system call, using IPython."""
1215
1207
1216 self.system(arg_s)
1208 self.system(arg_s)
1217
1209
1218 def complete(self,text):
1210 def complete(self,text):
1219 """Return a sorted list of all possible completions on text.
1211 """Return a sorted list of all possible completions on text.
1220
1212
1221 Inputs:
1213 Inputs:
1222
1214
1223 - text: a string of text to be completed on.
1215 - text: a string of text to be completed on.
1224
1216
1225 This is a wrapper around the completion mechanism, similar to what
1217 This is a wrapper around the completion mechanism, similar to what
1226 readline does at the command line when the TAB key is hit. By
1218 readline does at the command line when the TAB key is hit. By
1227 exposing it as a method, it can be used by other non-readline
1219 exposing it as a method, it can be used by other non-readline
1228 environments (such as GUIs) for text completion.
1220 environments (such as GUIs) for text completion.
1229
1221
1230 Simple usage example:
1222 Simple usage example:
1231
1223
1232 In [7]: x = 'hello'
1224 In [7]: x = 'hello'
1233
1225
1234 In [8]: x
1226 In [8]: x
1235 Out[8]: 'hello'
1227 Out[8]: 'hello'
1236
1228
1237 In [9]: print x
1229 In [9]: print x
1238 hello
1230 hello
1239
1231
1240 In [10]: _ip.IP.complete('x.l')
1232 In [10]: _ip.IP.complete('x.l')
1241 Out[10]: ['x.ljust', 'x.lower', 'x.lstrip']
1233 Out[10]: ['x.ljust', 'x.lower', 'x.lstrip']
1242 """
1234 """
1243
1235
1244 complete = self.Completer.complete
1236 complete = self.Completer.complete
1245 state = 0
1237 state = 0
1246 # use a dict so we get unique keys, since ipyhton's multiple
1238 # use a dict so we get unique keys, since ipyhton's multiple
1247 # completers can return duplicates. When we make 2.4 a requirement,
1239 # completers can return duplicates. When we make 2.4 a requirement,
1248 # start using sets instead, which are faster.
1240 # start using sets instead, which are faster.
1249 comps = {}
1241 comps = {}
1250 while True:
1242 while True:
1251 newcomp = complete(text,state,line_buffer=text)
1243 newcomp = complete(text,state,line_buffer=text)
1252 if newcomp is None:
1244 if newcomp is None:
1253 break
1245 break
1254 comps[newcomp] = 1
1246 comps[newcomp] = 1
1255 state += 1
1247 state += 1
1256 outcomps = comps.keys()
1248 outcomps = comps.keys()
1257 outcomps.sort()
1249 outcomps.sort()
1258 #print "T:",text,"OC:",outcomps # dbg
1250 #print "T:",text,"OC:",outcomps # dbg
1259 #print "vars:",self.user_ns.keys()
1251 #print "vars:",self.user_ns.keys()
1260 return outcomps
1252 return outcomps
1261
1253
1262 def set_completer_frame(self, frame=None):
1254 def set_completer_frame(self, frame=None):
1263 if frame:
1255 if frame:
1264 self.Completer.namespace = frame.f_locals
1256 self.Completer.namespace = frame.f_locals
1265 self.Completer.global_namespace = frame.f_globals
1257 self.Completer.global_namespace = frame.f_globals
1266 else:
1258 else:
1267 self.Completer.namespace = self.user_ns
1259 self.Completer.namespace = self.user_ns
1268 self.Completer.global_namespace = self.user_global_ns
1260 self.Completer.global_namespace = self.user_global_ns
1269
1261
1270 def init_auto_alias(self):
1262 def init_auto_alias(self):
1271 """Define some aliases automatically.
1263 """Define some aliases automatically.
1272
1264
1273 These are ALL parameter-less aliases"""
1265 These are ALL parameter-less aliases"""
1274
1266
1275 for alias,cmd in self.auto_alias:
1267 for alias,cmd in self.auto_alias:
1276 self.getapi().defalias(alias,cmd)
1268 self.getapi().defalias(alias,cmd)
1277
1269
1278
1270
1279 def alias_table_validate(self,verbose=0):
1271 def alias_table_validate(self,verbose=0):
1280 """Update information about the alias table.
1272 """Update information about the alias table.
1281
1273
1282 In particular, make sure no Python keywords/builtins are in it."""
1274 In particular, make sure no Python keywords/builtins are in it."""
1283
1275
1284 no_alias = self.no_alias
1276 no_alias = self.no_alias
1285 for k in self.alias_table.keys():
1277 for k in self.alias_table.keys():
1286 if k in no_alias:
1278 if k in no_alias:
1287 del self.alias_table[k]
1279 del self.alias_table[k]
1288 if verbose:
1280 if verbose:
1289 print ("Deleting alias <%s>, it's a Python "
1281 print ("Deleting alias <%s>, it's a Python "
1290 "keyword or builtin." % k)
1282 "keyword or builtin." % k)
1291
1283
1292 def set_autoindent(self,value=None):
1284 def set_autoindent(self,value=None):
1293 """Set the autoindent flag, checking for readline support.
1285 """Set the autoindent flag, checking for readline support.
1294
1286
1295 If called with no arguments, it acts as a toggle."""
1287 If called with no arguments, it acts as a toggle."""
1296
1288
1297 if not self.has_readline:
1289 if not self.has_readline:
1298 if os.name == 'posix':
1290 if os.name == 'posix':
1299 warn("The auto-indent feature requires the readline library")
1291 warn("The auto-indent feature requires the readline library")
1300 self.autoindent = 0
1292 self.autoindent = 0
1301 return
1293 return
1302 if value is None:
1294 if value is None:
1303 self.autoindent = not self.autoindent
1295 self.autoindent = not self.autoindent
1304 else:
1296 else:
1305 self.autoindent = value
1297 self.autoindent = value
1306
1298
1307 def rc_set_toggle(self,rc_field,value=None):
1299 def rc_set_toggle(self,rc_field,value=None):
1308 """Set or toggle a field in IPython's rc config. structure.
1300 """Set or toggle a field in IPython's rc config. structure.
1309
1301
1310 If called with no arguments, it acts as a toggle.
1302 If called with no arguments, it acts as a toggle.
1311
1303
1312 If called with a non-existent field, the resulting AttributeError
1304 If called with a non-existent field, the resulting AttributeError
1313 exception will propagate out."""
1305 exception will propagate out."""
1314
1306
1315 rc_val = getattr(self.rc,rc_field)
1307 rc_val = getattr(self.rc,rc_field)
1316 if value is None:
1308 if value is None:
1317 value = not rc_val
1309 value = not rc_val
1318 setattr(self.rc,rc_field,value)
1310 setattr(self.rc,rc_field,value)
1319
1311
1320 def user_setup(self,ipythondir,rc_suffix,mode='install'):
1312 def user_setup(self,ipythondir,rc_suffix,mode='install'):
1321 """Install the user configuration directory.
1313 """Install the user configuration directory.
1322
1314
1323 Note
1315 Note
1324 ----
1316 ----
1325 DEPRECATED: use the top-level user_setup() function instead.
1317 DEPRECATED: use the top-level user_setup() function instead.
1326 """
1318 """
1327 return user_setup(ipythondir,rc_suffix,mode)
1319 return user_setup(ipythondir,rc_suffix,mode)
1328
1320
1329 def atexit_operations(self):
1321 def atexit_operations(self):
1330 """This will be executed at the time of exit.
1322 """This will be executed at the time of exit.
1331
1323
1332 Saving of persistent data should be performed here. """
1324 Saving of persistent data should be performed here. """
1333
1325
1334 #print '*** IPython exit cleanup ***' # dbg
1326 #print '*** IPython exit cleanup ***' # dbg
1335 # input history
1327 # input history
1336 self.savehist()
1328 self.savehist()
1337
1329
1338 # Cleanup all tempfiles left around
1330 # Cleanup all tempfiles left around
1339 for tfile in self.tempfiles:
1331 for tfile in self.tempfiles:
1340 try:
1332 try:
1341 os.unlink(tfile)
1333 os.unlink(tfile)
1342 except OSError:
1334 except OSError:
1343 pass
1335 pass
1344
1336
1345 # Clear all user namespaces to release all references cleanly.
1337 # Clear all user namespaces to release all references cleanly.
1346 self.reset()
1338 self.reset()
1347
1339
1348 # Run user hooks
1340 # Run user hooks
1349 self.hooks.shutdown_hook()
1341 self.hooks.shutdown_hook()
1350
1342
1351 def reset(self):
1343 def reset(self):
1352 """Clear all internal namespaces.
1344 """Clear all internal namespaces.
1353
1345
1354 Note that this is much more aggressive than %reset, since it clears
1346 Note that this is much more aggressive than %reset, since it clears
1355 fully all namespaces, as well as all input/output lists.
1347 fully all namespaces, as well as all input/output lists.
1356 """
1348 """
1357 for ns in self.ns_refs_table:
1349 for ns in self.ns_refs_table:
1358 ns.clear()
1350 ns.clear()
1359
1351
1360 # Clear input and output histories
1352 # Clear input and output histories
1361 self.input_hist[:] = []
1353 self.input_hist[:] = []
1362 self.input_hist_raw[:] = []
1354 self.input_hist_raw[:] = []
1363 self.output_hist.clear()
1355 self.output_hist.clear()
1364 # Restore the user namespaces to minimal usability
1356 # Restore the user namespaces to minimal usability
1365 self.init_namespaces()
1357 self.init_namespaces()
1366
1358
1367 def savehist(self):
1359 def savehist(self):
1368 """Save input history to a file (via readline library)."""
1360 """Save input history to a file (via readline library)."""
1369
1361
1370 if not self.has_readline:
1362 if not self.has_readline:
1371 return
1363 return
1372
1364
1373 try:
1365 try:
1374 self.readline.write_history_file(self.histfile)
1366 self.readline.write_history_file(self.histfile)
1375 except:
1367 except:
1376 print 'Unable to save IPython command history to file: ' + \
1368 print 'Unable to save IPython command history to file: ' + \
1377 `self.histfile`
1369 `self.histfile`
1378
1370
1379 def reloadhist(self):
1371 def reloadhist(self):
1380 """Reload the input history from disk file."""
1372 """Reload the input history from disk file."""
1381
1373
1382 if self.has_readline:
1374 if self.has_readline:
1383 try:
1375 try:
1384 self.readline.clear_history()
1376 self.readline.clear_history()
1385 self.readline.read_history_file(self.shell.histfile)
1377 self.readline.read_history_file(self.shell.histfile)
1386 except AttributeError:
1378 except AttributeError:
1387 pass
1379 pass
1388
1380
1389
1381
1390 def history_saving_wrapper(self, func):
1382 def history_saving_wrapper(self, func):
1391 """ Wrap func for readline history saving
1383 """ Wrap func for readline history saving
1392
1384
1393 Convert func into callable that saves & restores
1385 Convert func into callable that saves & restores
1394 history around the call """
1386 history around the call """
1395
1387
1396 if not self.has_readline:
1388 if not self.has_readline:
1397 return func
1389 return func
1398
1390
1399 def wrapper():
1391 def wrapper():
1400 self.savehist()
1392 self.savehist()
1401 try:
1393 try:
1402 func()
1394 func()
1403 finally:
1395 finally:
1404 readline.read_history_file(self.histfile)
1396 readline.read_history_file(self.histfile)
1405 return wrapper
1397 return wrapper
1406
1398
1407 def pre_readline(self):
1399 def pre_readline(self):
1408 """readline hook to be used at the start of each line.
1400 """readline hook to be used at the start of each line.
1409
1401
1410 Currently it handles auto-indent only."""
1402 Currently it handles auto-indent only."""
1411
1403
1412 #debugx('self.indent_current_nsp','pre_readline:')
1404 #debugx('self.indent_current_nsp','pre_readline:')
1413
1405
1414 if self.rl_do_indent:
1406 if self.rl_do_indent:
1415 self.readline.insert_text(self.indent_current_str())
1407 self.readline.insert_text(self.indent_current_str())
1416 if self.rl_next_input is not None:
1408 if self.rl_next_input is not None:
1417 self.readline.insert_text(self.rl_next_input)
1409 self.readline.insert_text(self.rl_next_input)
1418 self.rl_next_input = None
1410 self.rl_next_input = None
1419
1411
1420 def init_readline(self):
1412 def init_readline(self):
1421 """Command history completion/saving/reloading."""
1413 """Command history completion/saving/reloading."""
1422
1414
1423
1415
1424 import IPython.rlineimpl as readline
1416 import IPython.rlineimpl as readline
1425
1417
1426 if not readline.have_readline:
1418 if not readline.have_readline:
1427 self.has_readline = 0
1419 self.has_readline = 0
1428 self.readline = None
1420 self.readline = None
1429 # no point in bugging windows users with this every time:
1421 # no point in bugging windows users with this every time:
1430 warn('Readline services not available on this platform.')
1422 warn('Readline services not available on this platform.')
1431 else:
1423 else:
1432 sys.modules['readline'] = readline
1424 sys.modules['readline'] = readline
1433 import atexit
1425 import atexit
1434 from IPython.completer import IPCompleter
1426 from IPython.completer import IPCompleter
1435 self.Completer = IPCompleter(self,
1427 self.Completer = IPCompleter(self,
1436 self.user_ns,
1428 self.user_ns,
1437 self.user_global_ns,
1429 self.user_global_ns,
1438 self.rc.readline_omit__names,
1430 self.rc.readline_omit__names,
1439 self.alias_table)
1431 self.alias_table)
1440 sdisp = self.strdispatchers.get('complete_command', StrDispatch())
1432 sdisp = self.strdispatchers.get('complete_command', StrDispatch())
1441 self.strdispatchers['complete_command'] = sdisp
1433 self.strdispatchers['complete_command'] = sdisp
1442 self.Completer.custom_completers = sdisp
1434 self.Completer.custom_completers = sdisp
1443 # Platform-specific configuration
1435 # Platform-specific configuration
1444 if os.name == 'nt':
1436 if os.name == 'nt':
1445 self.readline_startup_hook = readline.set_pre_input_hook
1437 self.readline_startup_hook = readline.set_pre_input_hook
1446 else:
1438 else:
1447 self.readline_startup_hook = readline.set_startup_hook
1439 self.readline_startup_hook = readline.set_startup_hook
1448
1440
1449 # Load user's initrc file (readline config)
1441 # Load user's initrc file (readline config)
1450 # Or if libedit is used, load editrc.
1442 # Or if libedit is used, load editrc.
1451 inputrc_name = os.environ.get('INPUTRC')
1443 inputrc_name = os.environ.get('INPUTRC')
1452 if inputrc_name is None:
1444 if inputrc_name is None:
1453 home_dir = get_home_dir()
1445 home_dir = get_home_dir()
1454 if home_dir is not None:
1446 if home_dir is not None:
1455 inputrc_name = '.inputrc'
1447 inputrc_name = '.inputrc'
1456 if readline.uses_libedit:
1448 if readline.uses_libedit:
1457 inputrc_name = '.editrc'
1449 inputrc_name = '.editrc'
1458 inputrc_name = os.path.join(home_dir, inputrc_name)
1450 inputrc_name = os.path.join(home_dir, inputrc_name)
1459 if os.path.isfile(inputrc_name):
1451 if os.path.isfile(inputrc_name):
1460 try:
1452 try:
1461 readline.read_init_file(inputrc_name)
1453 readline.read_init_file(inputrc_name)
1462 except:
1454 except:
1463 warn('Problems reading readline initialization file <%s>'
1455 warn('Problems reading readline initialization file <%s>'
1464 % inputrc_name)
1456 % inputrc_name)
1465
1457
1466 self.has_readline = 1
1458 self.has_readline = 1
1467 self.readline = readline
1459 self.readline = readline
1468 # save this in sys so embedded copies can restore it properly
1460 # save this in sys so embedded copies can restore it properly
1469 sys.ipcompleter = self.Completer.complete
1461 sys.ipcompleter = self.Completer.complete
1470 self.set_completer()
1462 self.set_completer()
1471
1463
1472 # Configure readline according to user's prefs
1464 # Configure readline according to user's prefs
1473 # This is only done if GNU readline is being used. If libedit
1465 # This is only done if GNU readline is being used. If libedit
1474 # is being used (as on Leopard) the readline config is
1466 # is being used (as on Leopard) the readline config is
1475 # not run as the syntax for libedit is different.
1467 # not run as the syntax for libedit is different.
1476 if not readline.uses_libedit:
1468 if not readline.uses_libedit:
1477 for rlcommand in self.rc.readline_parse_and_bind:
1469 for rlcommand in self.rc.readline_parse_and_bind:
1478 #print "loading rl:",rlcommand # dbg
1470 #print "loading rl:",rlcommand # dbg
1479 readline.parse_and_bind(rlcommand)
1471 readline.parse_and_bind(rlcommand)
1480
1472
1481 # Remove some chars from the delimiters list. If we encounter
1473 # Remove some chars from the delimiters list. If we encounter
1482 # unicode chars, discard them.
1474 # unicode chars, discard them.
1483 delims = readline.get_completer_delims().encode("ascii", "ignore")
1475 delims = readline.get_completer_delims().encode("ascii", "ignore")
1484 delims = delims.translate(string._idmap,
1476 delims = delims.translate(string._idmap,
1485 self.rc.readline_remove_delims)
1477 self.rc.readline_remove_delims)
1486 readline.set_completer_delims(delims)
1478 readline.set_completer_delims(delims)
1487 # otherwise we end up with a monster history after a while:
1479 # otherwise we end up with a monster history after a while:
1488 readline.set_history_length(1000)
1480 readline.set_history_length(1000)
1489 try:
1481 try:
1490 #print '*** Reading readline history' # dbg
1482 #print '*** Reading readline history' # dbg
1491 readline.read_history_file(self.histfile)
1483 readline.read_history_file(self.histfile)
1492 except IOError:
1484 except IOError:
1493 pass # It doesn't exist yet.
1485 pass # It doesn't exist yet.
1494
1486
1495 atexit.register(self.atexit_operations)
1487 atexit.register(self.atexit_operations)
1496 del atexit
1488 del atexit
1497
1489
1498 # Configure auto-indent for all platforms
1490 # Configure auto-indent for all platforms
1499 self.set_autoindent(self.rc.autoindent)
1491 self.set_autoindent(self.rc.autoindent)
1500
1492
1501 def ask_yes_no(self,prompt,default=True):
1493 def ask_yes_no(self,prompt,default=True):
1502 if self.rc.quiet:
1494 if self.rc.quiet:
1503 return True
1495 return True
1504 return ask_yes_no(prompt,default)
1496 return ask_yes_no(prompt,default)
1505
1497
1506 def new_main_mod(self,ns=None):
1498 def new_main_mod(self,ns=None):
1507 """Return a new 'main' module object for user code execution.
1499 """Return a new 'main' module object for user code execution.
1508 """
1500 """
1509 main_mod = self._user_main_module
1501 main_mod = self._user_main_module
1510 init_fakemod_dict(main_mod,ns)
1502 init_fakemod_dict(main_mod,ns)
1511 return main_mod
1503 return main_mod
1512
1504
1513 def cache_main_mod(self,ns,fname):
1505 def cache_main_mod(self,ns,fname):
1514 """Cache a main module's namespace.
1506 """Cache a main module's namespace.
1515
1507
1516 When scripts are executed via %run, we must keep a reference to the
1508 When scripts are executed via %run, we must keep a reference to the
1517 namespace of their __main__ module (a FakeModule instance) around so
1509 namespace of their __main__ module (a FakeModule instance) around so
1518 that Python doesn't clear it, rendering objects defined therein
1510 that Python doesn't clear it, rendering objects defined therein
1519 useless.
1511 useless.
1520
1512
1521 This method keeps said reference in a private dict, keyed by the
1513 This method keeps said reference in a private dict, keyed by the
1522 absolute path of the module object (which corresponds to the script
1514 absolute path of the module object (which corresponds to the script
1523 path). This way, for multiple executions of the same script we only
1515 path). This way, for multiple executions of the same script we only
1524 keep one copy of the namespace (the last one), thus preventing memory
1516 keep one copy of the namespace (the last one), thus preventing memory
1525 leaks from old references while allowing the objects from the last
1517 leaks from old references while allowing the objects from the last
1526 execution to be accessible.
1518 execution to be accessible.
1527
1519
1528 Note: we can not allow the actual FakeModule instances to be deleted,
1520 Note: we can not allow the actual FakeModule instances to be deleted,
1529 because of how Python tears down modules (it hard-sets all their
1521 because of how Python tears down modules (it hard-sets all their
1530 references to None without regard for reference counts). This method
1522 references to None without regard for reference counts). This method
1531 must therefore make a *copy* of the given namespace, to allow the
1523 must therefore make a *copy* of the given namespace, to allow the
1532 original module's __dict__ to be cleared and reused.
1524 original module's __dict__ to be cleared and reused.
1533
1525
1534
1526
1535 Parameters
1527 Parameters
1536 ----------
1528 ----------
1537 ns : a namespace (a dict, typically)
1529 ns : a namespace (a dict, typically)
1538
1530
1539 fname : str
1531 fname : str
1540 Filename associated with the namespace.
1532 Filename associated with the namespace.
1541
1533
1542 Examples
1534 Examples
1543 --------
1535 --------
1544
1536
1545 In [10]: import IPython
1537 In [10]: import IPython
1546
1538
1547 In [11]: _ip.IP.cache_main_mod(IPython.__dict__,IPython.__file__)
1539 In [11]: _ip.IP.cache_main_mod(IPython.__dict__,IPython.__file__)
1548
1540
1549 In [12]: IPython.__file__ in _ip.IP._main_ns_cache
1541 In [12]: IPython.__file__ in _ip.IP._main_ns_cache
1550 Out[12]: True
1542 Out[12]: True
1551 """
1543 """
1552 self._main_ns_cache[os.path.abspath(fname)] = ns.copy()
1544 self._main_ns_cache[os.path.abspath(fname)] = ns.copy()
1553
1545
1554 def clear_main_mod_cache(self):
1546 def clear_main_mod_cache(self):
1555 """Clear the cache of main modules.
1547 """Clear the cache of main modules.
1556
1548
1557 Mainly for use by utilities like %reset.
1549 Mainly for use by utilities like %reset.
1558
1550
1559 Examples
1551 Examples
1560 --------
1552 --------
1561
1553
1562 In [15]: import IPython
1554 In [15]: import IPython
1563
1555
1564 In [16]: _ip.IP.cache_main_mod(IPython.__dict__,IPython.__file__)
1556 In [16]: _ip.IP.cache_main_mod(IPython.__dict__,IPython.__file__)
1565
1557
1566 In [17]: len(_ip.IP._main_ns_cache) > 0
1558 In [17]: len(_ip.IP._main_ns_cache) > 0
1567 Out[17]: True
1559 Out[17]: True
1568
1560
1569 In [18]: _ip.IP.clear_main_mod_cache()
1561 In [18]: _ip.IP.clear_main_mod_cache()
1570
1562
1571 In [19]: len(_ip.IP._main_ns_cache) == 0
1563 In [19]: len(_ip.IP._main_ns_cache) == 0
1572 Out[19]: True
1564 Out[19]: True
1573 """
1565 """
1574 self._main_ns_cache.clear()
1566 self._main_ns_cache.clear()
1575
1567
1576 def _should_recompile(self,e):
1568 def _should_recompile(self,e):
1577 """Utility routine for edit_syntax_error"""
1569 """Utility routine for edit_syntax_error"""
1578
1570
1579 if e.filename in ('<ipython console>','<input>','<string>',
1571 if e.filename in ('<ipython console>','<input>','<string>',
1580 '<console>','<BackgroundJob compilation>',
1572 '<console>','<BackgroundJob compilation>',
1581 None):
1573 None):
1582
1574
1583 return False
1575 return False
1584 try:
1576 try:
1585 if (self.rc.autoedit_syntax and
1577 if (self.rc.autoedit_syntax and
1586 not self.ask_yes_no('Return to editor to correct syntax error? '
1578 not self.ask_yes_no('Return to editor to correct syntax error? '
1587 '[Y/n] ','y')):
1579 '[Y/n] ','y')):
1588 return False
1580 return False
1589 except EOFError:
1581 except EOFError:
1590 return False
1582 return False
1591
1583
1592 def int0(x):
1584 def int0(x):
1593 try:
1585 try:
1594 return int(x)
1586 return int(x)
1595 except TypeError:
1587 except TypeError:
1596 return 0
1588 return 0
1597 # always pass integer line and offset values to editor hook
1589 # always pass integer line and offset values to editor hook
1598 try:
1590 try:
1599 self.hooks.fix_error_editor(e.filename,
1591 self.hooks.fix_error_editor(e.filename,
1600 int0(e.lineno),int0(e.offset),e.msg)
1592 int0(e.lineno),int0(e.offset),e.msg)
1601 except IPython.ipapi.TryNext:
1593 except IPython.ipapi.TryNext:
1602 warn('Could not open editor')
1594 warn('Could not open editor')
1603 return False
1595 return False
1604 return True
1596 return True
1605
1597
1606 def edit_syntax_error(self):
1598 def edit_syntax_error(self):
1607 """The bottom half of the syntax error handler called in the main loop.
1599 """The bottom half of the syntax error handler called in the main loop.
1608
1600
1609 Loop until syntax error is fixed or user cancels.
1601 Loop until syntax error is fixed or user cancels.
1610 """
1602 """
1611
1603
1612 while self.SyntaxTB.last_syntax_error:
1604 while self.SyntaxTB.last_syntax_error:
1613 # copy and clear last_syntax_error
1605 # copy and clear last_syntax_error
1614 err = self.SyntaxTB.clear_err_state()
1606 err = self.SyntaxTB.clear_err_state()
1615 if not self._should_recompile(err):
1607 if not self._should_recompile(err):
1616 return
1608 return
1617 try:
1609 try:
1618 # may set last_syntax_error again if a SyntaxError is raised
1610 # may set last_syntax_error again if a SyntaxError is raised
1619 self.safe_execfile(err.filename,self.user_ns)
1611 self.safe_execfile(err.filename,self.user_ns)
1620 except:
1612 except:
1621 self.showtraceback()
1613 self.showtraceback()
1622 else:
1614 else:
1623 try:
1615 try:
1624 f = file(err.filename)
1616 f = file(err.filename)
1625 try:
1617 try:
1626 sys.displayhook(f.read())
1618 sys.displayhook(f.read())
1627 finally:
1619 finally:
1628 f.close()
1620 f.close()
1629 except:
1621 except:
1630 self.showtraceback()
1622 self.showtraceback()
1631
1623
1632 def showsyntaxerror(self, filename=None):
1624 def showsyntaxerror(self, filename=None):
1633 """Display the syntax error that just occurred.
1625 """Display the syntax error that just occurred.
1634
1626
1635 This doesn't display a stack trace because there isn't one.
1627 This doesn't display a stack trace because there isn't one.
1636
1628
1637 If a filename is given, it is stuffed in the exception instead
1629 If a filename is given, it is stuffed in the exception instead
1638 of what was there before (because Python's parser always uses
1630 of what was there before (because Python's parser always uses
1639 "<string>" when reading from a string).
1631 "<string>" when reading from a string).
1640 """
1632 """
1641 etype, value, last_traceback = sys.exc_info()
1633 etype, value, last_traceback = sys.exc_info()
1642
1634
1643 # See note about these variables in showtraceback() below
1635 # See note about these variables in showtraceback() below
1644 sys.last_type = etype
1636 sys.last_type = etype
1645 sys.last_value = value
1637 sys.last_value = value
1646 sys.last_traceback = last_traceback
1638 sys.last_traceback = last_traceback
1647
1639
1648 if filename and etype is SyntaxError:
1640 if filename and etype is SyntaxError:
1649 # Work hard to stuff the correct filename in the exception
1641 # Work hard to stuff the correct filename in the exception
1650 try:
1642 try:
1651 msg, (dummy_filename, lineno, offset, line) = value
1643 msg, (dummy_filename, lineno, offset, line) = value
1652 except:
1644 except:
1653 # Not the format we expect; leave it alone
1645 # Not the format we expect; leave it alone
1654 pass
1646 pass
1655 else:
1647 else:
1656 # Stuff in the right filename
1648 # Stuff in the right filename
1657 try:
1649 try:
1658 # Assume SyntaxError is a class exception
1650 # Assume SyntaxError is a class exception
1659 value = SyntaxError(msg, (filename, lineno, offset, line))
1651 value = SyntaxError(msg, (filename, lineno, offset, line))
1660 except:
1652 except:
1661 # If that failed, assume SyntaxError is a string
1653 # If that failed, assume SyntaxError is a string
1662 value = msg, (filename, lineno, offset, line)
1654 value = msg, (filename, lineno, offset, line)
1663 self.SyntaxTB(etype,value,[])
1655 self.SyntaxTB(etype,value,[])
1664
1656
1665 def debugger(self,force=False):
1657 def debugger(self,force=False):
1666 """Call the pydb/pdb debugger.
1658 """Call the pydb/pdb debugger.
1667
1659
1668 Keywords:
1660 Keywords:
1669
1661
1670 - force(False): by default, this routine checks the instance call_pdb
1662 - force(False): by default, this routine checks the instance call_pdb
1671 flag and does not actually invoke the debugger if the flag is false.
1663 flag and does not actually invoke the debugger if the flag is false.
1672 The 'force' option forces the debugger to activate even if the flag
1664 The 'force' option forces the debugger to activate even if the flag
1673 is false.
1665 is false.
1674 """
1666 """
1675
1667
1676 if not (force or self.call_pdb):
1668 if not (force or self.call_pdb):
1677 return
1669 return
1678
1670
1679 if not hasattr(sys,'last_traceback'):
1671 if not hasattr(sys,'last_traceback'):
1680 error('No traceback has been produced, nothing to debug.')
1672 error('No traceback has been produced, nothing to debug.')
1681 return
1673 return
1682
1674
1683 # use pydb if available
1675 # use pydb if available
1684 if Debugger.has_pydb:
1676 if Debugger.has_pydb:
1685 from pydb import pm
1677 from pydb import pm
1686 else:
1678 else:
1687 # fallback to our internal debugger
1679 # fallback to our internal debugger
1688 pm = lambda : self.InteractiveTB.debugger(force=True)
1680 pm = lambda : self.InteractiveTB.debugger(force=True)
1689 self.history_saving_wrapper(pm)()
1681 self.history_saving_wrapper(pm)()
1690
1682
1691 def showtraceback(self,exc_tuple = None,filename=None,tb_offset=None):
1683 def showtraceback(self,exc_tuple = None,filename=None,tb_offset=None):
1692 """Display the exception that just occurred.
1684 """Display the exception that just occurred.
1693
1685
1694 If nothing is known about the exception, this is the method which
1686 If nothing is known about the exception, this is the method which
1695 should be used throughout the code for presenting user tracebacks,
1687 should be used throughout the code for presenting user tracebacks,
1696 rather than directly invoking the InteractiveTB object.
1688 rather than directly invoking the InteractiveTB object.
1697
1689
1698 A specific showsyntaxerror() also exists, but this method can take
1690 A specific showsyntaxerror() also exists, but this method can take
1699 care of calling it if needed, so unless you are explicitly catching a
1691 care of calling it if needed, so unless you are explicitly catching a
1700 SyntaxError exception, don't try to analyze the stack manually and
1692 SyntaxError exception, don't try to analyze the stack manually and
1701 simply call this method."""
1693 simply call this method."""
1702
1694
1703
1695
1704 # Though this won't be called by syntax errors in the input line,
1696 # Though this won't be called by syntax errors in the input line,
1705 # there may be SyntaxError cases whith imported code.
1697 # there may be SyntaxError cases whith imported code.
1706
1698
1707 try:
1699 try:
1708 if exc_tuple is None:
1700 if exc_tuple is None:
1709 etype, value, tb = sys.exc_info()
1701 etype, value, tb = sys.exc_info()
1710 else:
1702 else:
1711 etype, value, tb = exc_tuple
1703 etype, value, tb = exc_tuple
1712
1704
1713 if etype is SyntaxError:
1705 if etype is SyntaxError:
1714 self.showsyntaxerror(filename)
1706 self.showsyntaxerror(filename)
1715 elif etype is IPython.ipapi.UsageError:
1707 elif etype is IPython.ipapi.UsageError:
1716 print "UsageError:", value
1708 print "UsageError:", value
1717 else:
1709 else:
1718 # WARNING: these variables are somewhat deprecated and not
1710 # WARNING: these variables are somewhat deprecated and not
1719 # necessarily safe to use in a threaded environment, but tools
1711 # necessarily safe to use in a threaded environment, but tools
1720 # like pdb depend on their existence, so let's set them. If we
1712 # like pdb depend on their existence, so let's set them. If we
1721 # find problems in the field, we'll need to revisit their use.
1713 # find problems in the field, we'll need to revisit their use.
1722 sys.last_type = etype
1714 sys.last_type = etype
1723 sys.last_value = value
1715 sys.last_value = value
1724 sys.last_traceback = tb
1716 sys.last_traceback = tb
1725
1717
1726 if etype in self.custom_exceptions:
1718 if etype in self.custom_exceptions:
1727 self.CustomTB(etype,value,tb)
1719 self.CustomTB(etype,value,tb)
1728 else:
1720 else:
1729 self.InteractiveTB(etype,value,tb,tb_offset=tb_offset)
1721 self.InteractiveTB(etype,value,tb,tb_offset=tb_offset)
1730 if self.InteractiveTB.call_pdb and self.has_readline:
1722 if self.InteractiveTB.call_pdb and self.has_readline:
1731 # pdb mucks up readline, fix it back
1723 # pdb mucks up readline, fix it back
1732 self.set_completer()
1724 self.set_completer()
1733 except KeyboardInterrupt:
1725 except KeyboardInterrupt:
1734 self.write("\nKeyboardInterrupt\n")
1726 self.write("\nKeyboardInterrupt\n")
1735
1727
1736 def mainloop(self,banner=None):
1728 def mainloop(self,banner=None):
1737 """Creates the local namespace and starts the mainloop.
1729 """Creates the local namespace and starts the mainloop.
1738
1730
1739 If an optional banner argument is given, it will override the
1731 If an optional banner argument is given, it will override the
1740 internally created default banner."""
1732 internally created default banner."""
1741
1733
1742 if self.rc.c: # Emulate Python's -c option
1734 if self.rc.c: # Emulate Python's -c option
1743 self.exec_init_cmd()
1735 self.exec_init_cmd()
1744 if banner is None:
1736 if banner is None:
1745 if not self.rc.banner:
1737 if not self.rc.banner:
1746 banner = ''
1738 banner = ''
1747 # banner is string? Use it directly!
1739 # banner is string? Use it directly!
1748 elif isinstance(self.rc.banner,basestring):
1740 elif isinstance(self.rc.banner,basestring):
1749 banner = self.rc.banner
1741 banner = self.rc.banner
1750 else:
1742 else:
1751 banner = self.BANNER+self.banner2
1743 banner = self.BANNER+self.banner2
1752
1744
1753 # if you run stuff with -c <cmd>, raw hist is not updated
1745 # if you run stuff with -c <cmd>, raw hist is not updated
1754 # ensure that it's in sync
1746 # ensure that it's in sync
1755 if len(self.input_hist) != len (self.input_hist_raw):
1747 if len(self.input_hist) != len (self.input_hist_raw):
1756 self.input_hist_raw = InputList(self.input_hist)
1748 self.input_hist_raw = InputList(self.input_hist)
1757
1749
1758 while 1:
1750 while 1:
1759 try:
1751 try:
1760 self.interact(banner)
1752 self.interact(banner)
1761 #self.interact_with_readline()
1753 #self.interact_with_readline()
1762
1754
1763 # XXX for testing of a readline-decoupled repl loop, call
1755 # XXX for testing of a readline-decoupled repl loop, call
1764 # interact_with_readline above
1756 # interact_with_readline above
1765
1757
1766 break
1758 break
1767 except KeyboardInterrupt:
1759 except KeyboardInterrupt:
1768 # this should not be necessary, but KeyboardInterrupt
1760 # this should not be necessary, but KeyboardInterrupt
1769 # handling seems rather unpredictable...
1761 # handling seems rather unpredictable...
1770 self.write("\nKeyboardInterrupt in interact()\n")
1762 self.write("\nKeyboardInterrupt in interact()\n")
1771
1763
1772 def exec_init_cmd(self):
1764 def exec_init_cmd(self):
1773 """Execute a command given at the command line.
1765 """Execute a command given at the command line.
1774
1766
1775 This emulates Python's -c option."""
1767 This emulates Python's -c option."""
1776
1768
1777 #sys.argv = ['-c']
1769 #sys.argv = ['-c']
1778 self.push(self.prefilter(self.rc.c, False))
1770 self.push(self.prefilter(self.rc.c, False))
1779 if not self.rc.interact:
1771 if not self.rc.interact:
1780 self.ask_exit()
1772 self.ask_exit()
1781
1773
1782 def embed_mainloop(self,header='',local_ns=None,global_ns=None,stack_depth=0):
1774 def embed_mainloop(self,header='',local_ns=None,global_ns=None,stack_depth=0):
1783 """Embeds IPython into a running python program.
1775 """Embeds IPython into a running python program.
1784
1776
1785 Input:
1777 Input:
1786
1778
1787 - header: An optional header message can be specified.
1779 - header: An optional header message can be specified.
1788
1780
1789 - local_ns, global_ns: working namespaces. If given as None, the
1781 - local_ns, global_ns: working namespaces. If given as None, the
1790 IPython-initialized one is updated with __main__.__dict__, so that
1782 IPython-initialized one is updated with __main__.__dict__, so that
1791 program variables become visible but user-specific configuration
1783 program variables become visible but user-specific configuration
1792 remains possible.
1784 remains possible.
1793
1785
1794 - stack_depth: specifies how many levels in the stack to go to
1786 - stack_depth: specifies how many levels in the stack to go to
1795 looking for namespaces (when local_ns and global_ns are None). This
1787 looking for namespaces (when local_ns and global_ns are None). This
1796 allows an intermediate caller to make sure that this function gets
1788 allows an intermediate caller to make sure that this function gets
1797 the namespace from the intended level in the stack. By default (0)
1789 the namespace from the intended level in the stack. By default (0)
1798 it will get its locals and globals from the immediate caller.
1790 it will get its locals and globals from the immediate caller.
1799
1791
1800 Warning: it's possible to use this in a program which is being run by
1792 Warning: it's possible to use this in a program which is being run by
1801 IPython itself (via %run), but some funny things will happen (a few
1793 IPython itself (via %run), but some funny things will happen (a few
1802 globals get overwritten). In the future this will be cleaned up, as
1794 globals get overwritten). In the future this will be cleaned up, as
1803 there is no fundamental reason why it can't work perfectly."""
1795 there is no fundamental reason why it can't work perfectly."""
1804
1796
1805 # Get locals and globals from caller
1797 # Get locals and globals from caller
1806 if local_ns is None or global_ns is None:
1798 if local_ns is None or global_ns is None:
1807 call_frame = sys._getframe(stack_depth).f_back
1799 call_frame = sys._getframe(stack_depth).f_back
1808
1800
1809 if local_ns is None:
1801 if local_ns is None:
1810 local_ns = call_frame.f_locals
1802 local_ns = call_frame.f_locals
1811 if global_ns is None:
1803 if global_ns is None:
1812 global_ns = call_frame.f_globals
1804 global_ns = call_frame.f_globals
1813
1805
1814 # Update namespaces and fire up interpreter
1806 # Update namespaces and fire up interpreter
1815
1807
1816 # The global one is easy, we can just throw it in
1808 # The global one is easy, we can just throw it in
1817 self.user_global_ns = global_ns
1809 self.user_global_ns = global_ns
1818
1810
1819 # but the user/local one is tricky: ipython needs it to store internal
1811 # but the user/local one is tricky: ipython needs it to store internal
1820 # data, but we also need the locals. We'll copy locals in the user
1812 # data, but we also need the locals. We'll copy locals in the user
1821 # one, but will track what got copied so we can delete them at exit.
1813 # one, but will track what got copied so we can delete them at exit.
1822 # This is so that a later embedded call doesn't see locals from a
1814 # This is so that a later embedded call doesn't see locals from a
1823 # previous call (which most likely existed in a separate scope).
1815 # previous call (which most likely existed in a separate scope).
1824 local_varnames = local_ns.keys()
1816 local_varnames = local_ns.keys()
1825 self.user_ns.update(local_ns)
1817 self.user_ns.update(local_ns)
1826 #self.user_ns['local_ns'] = local_ns # dbg
1818 #self.user_ns['local_ns'] = local_ns # dbg
1827
1819
1828 # Patch for global embedding to make sure that things don't overwrite
1820 # Patch for global embedding to make sure that things don't overwrite
1829 # user globals accidentally. Thanks to Richard <rxe@renre-europe.com>
1821 # user globals accidentally. Thanks to Richard <rxe@renre-europe.com>
1830 # FIXME. Test this a bit more carefully (the if.. is new)
1822 # FIXME. Test this a bit more carefully (the if.. is new)
1831 if local_ns is None and global_ns is None:
1823 if local_ns is None and global_ns is None:
1832 self.user_global_ns.update(__main__.__dict__)
1824 self.user_global_ns.update(__main__.__dict__)
1833
1825
1834 # make sure the tab-completer has the correct frame information, so it
1826 # make sure the tab-completer has the correct frame information, so it
1835 # actually completes using the frame's locals/globals
1827 # actually completes using the frame's locals/globals
1836 self.set_completer_frame()
1828 self.set_completer_frame()
1837
1829
1838 # before activating the interactive mode, we need to make sure that
1830 # before activating the interactive mode, we need to make sure that
1839 # all names in the builtin namespace needed by ipython point to
1831 # all names in the builtin namespace needed by ipython point to
1840 # ourselves, and not to other instances.
1832 # ourselves, and not to other instances.
1841 self.add_builtins()
1833 self.add_builtins()
1842
1834
1843 self.interact(header)
1835 self.interact(header)
1844
1836
1845 # now, purge out the user namespace from anything we might have added
1837 # now, purge out the user namespace from anything we might have added
1846 # from the caller's local namespace
1838 # from the caller's local namespace
1847 delvar = self.user_ns.pop
1839 delvar = self.user_ns.pop
1848 for var in local_varnames:
1840 for var in local_varnames:
1849 delvar(var,None)
1841 delvar(var,None)
1850 # and clean builtins we may have overridden
1842 # and clean builtins we may have overridden
1851 self.clean_builtins()
1843 self.clean_builtins()
1852
1844
1853 def interact_prompt(self):
1845 def interact_prompt(self):
1854 """ Print the prompt (in read-eval-print loop)
1846 """ Print the prompt (in read-eval-print loop)
1855
1847
1856 Provided for those who want to implement their own read-eval-print loop (e.g. GUIs), not
1848 Provided for those who want to implement their own read-eval-print loop (e.g. GUIs), not
1857 used in standard IPython flow.
1849 used in standard IPython flow.
1858 """
1850 """
1859 if self.more:
1851 if self.more:
1860 try:
1852 try:
1861 prompt = self.hooks.generate_prompt(True)
1853 prompt = self.hooks.generate_prompt(True)
1862 except:
1854 except:
1863 self.showtraceback()
1855 self.showtraceback()
1864 if self.autoindent:
1856 if self.autoindent:
1865 self.rl_do_indent = True
1857 self.rl_do_indent = True
1866
1858
1867 else:
1859 else:
1868 try:
1860 try:
1869 prompt = self.hooks.generate_prompt(False)
1861 prompt = self.hooks.generate_prompt(False)
1870 except:
1862 except:
1871 self.showtraceback()
1863 self.showtraceback()
1872 self.write(prompt)
1864 self.write(prompt)
1873
1865
1874 def interact_handle_input(self,line):
1866 def interact_handle_input(self,line):
1875 """ Handle the input line (in read-eval-print loop)
1867 """ Handle the input line (in read-eval-print loop)
1876
1868
1877 Provided for those who want to implement their own read-eval-print loop (e.g. GUIs), not
1869 Provided for those who want to implement their own read-eval-print loop (e.g. GUIs), not
1878 used in standard IPython flow.
1870 used in standard IPython flow.
1879 """
1871 """
1880 if line.lstrip() == line:
1872 if line.lstrip() == line:
1881 self.shadowhist.add(line.strip())
1873 self.shadowhist.add(line.strip())
1882 lineout = self.prefilter(line,self.more)
1874 lineout = self.prefilter(line,self.more)
1883
1875
1884 if line.strip():
1876 if line.strip():
1885 if self.more:
1877 if self.more:
1886 self.input_hist_raw[-1] += '%s\n' % line
1878 self.input_hist_raw[-1] += '%s\n' % line
1887 else:
1879 else:
1888 self.input_hist_raw.append('%s\n' % line)
1880 self.input_hist_raw.append('%s\n' % line)
1889
1881
1890
1882
1891 self.more = self.push(lineout)
1883 self.more = self.push(lineout)
1892 if (self.SyntaxTB.last_syntax_error and
1884 if (self.SyntaxTB.last_syntax_error and
1893 self.rc.autoedit_syntax):
1885 self.rc.autoedit_syntax):
1894 self.edit_syntax_error()
1886 self.edit_syntax_error()
1895
1887
1896 def interact_with_readline(self):
1888 def interact_with_readline(self):
1897 """ Demo of using interact_handle_input, interact_prompt
1889 """ Demo of using interact_handle_input, interact_prompt
1898
1890
1899 This is the main read-eval-print loop. If you need to implement your own (e.g. for GUI),
1891 This is the main read-eval-print loop. If you need to implement your own (e.g. for GUI),
1900 it should work like this.
1892 it should work like this.
1901 """
1893 """
1902 self.readline_startup_hook(self.pre_readline)
1894 self.readline_startup_hook(self.pre_readline)
1903 while not self.exit_now:
1895 while not self.exit_now:
1904 self.interact_prompt()
1896 self.interact_prompt()
1905 if self.more:
1897 if self.more:
1906 self.rl_do_indent = True
1898 self.rl_do_indent = True
1907 else:
1899 else:
1908 self.rl_do_indent = False
1900 self.rl_do_indent = False
1909 line = raw_input_original().decode(self.stdin_encoding)
1901 line = raw_input_original().decode(self.stdin_encoding)
1910 self.interact_handle_input(line)
1902 self.interact_handle_input(line)
1911
1903
1912
1904
1913 def interact(self, banner=None):
1905 def interact(self, banner=None):
1914 """Closely emulate the interactive Python console.
1906 """Closely emulate the interactive Python console.
1915
1907
1916 The optional banner argument specify the banner to print
1908 The optional banner argument specify the banner to print
1917 before the first interaction; by default it prints a banner
1909 before the first interaction; by default it prints a banner
1918 similar to the one printed by the real Python interpreter,
1910 similar to the one printed by the real Python interpreter,
1919 followed by the current class name in parentheses (so as not
1911 followed by the current class name in parentheses (so as not
1920 to confuse this with the real interpreter -- since it's so
1912 to confuse this with the real interpreter -- since it's so
1921 close!).
1913 close!).
1922
1914
1923 """
1915 """
1924
1916
1925 if self.exit_now:
1917 if self.exit_now:
1926 # batch run -> do not interact
1918 # batch run -> do not interact
1927 return
1919 return
1928 cprt = 'Type "copyright", "credits" or "license" for more information.'
1920 cprt = 'Type "copyright", "credits" or "license" for more information.'
1929 if banner is None:
1921 if banner is None:
1930 self.write("Python %s on %s\n%s\n(%s)\n" %
1922 self.write("Python %s on %s\n%s\n(%s)\n" %
1931 (sys.version, sys.platform, cprt,
1923 (sys.version, sys.platform, cprt,
1932 self.__class__.__name__))
1924 self.__class__.__name__))
1933 else:
1925 else:
1934 self.write(banner)
1926 self.write(banner)
1935
1927
1936 more = 0
1928 more = 0
1937
1929
1938 # Mark activity in the builtins
1930 # Mark activity in the builtins
1939 __builtin__.__dict__['__IPYTHON__active'] += 1
1931 __builtin__.__dict__['__IPYTHON__active'] += 1
1940
1932
1941 if self.has_readline:
1933 if self.has_readline:
1942 self.readline_startup_hook(self.pre_readline)
1934 self.readline_startup_hook(self.pre_readline)
1943 # exit_now is set by a call to %Exit or %Quit, through the
1935 # exit_now is set by a call to %Exit or %Quit, through the
1944 # ask_exit callback.
1936 # ask_exit callback.
1945
1937
1946 while not self.exit_now:
1938 while not self.exit_now:
1947 self.hooks.pre_prompt_hook()
1939 self.hooks.pre_prompt_hook()
1948 if more:
1940 if more:
1949 try:
1941 try:
1950 prompt = self.hooks.generate_prompt(True)
1942 prompt = self.hooks.generate_prompt(True)
1951 except:
1943 except:
1952 self.showtraceback()
1944 self.showtraceback()
1953 if self.autoindent:
1945 if self.autoindent:
1954 self.rl_do_indent = True
1946 self.rl_do_indent = True
1955
1947
1956 else:
1948 else:
1957 try:
1949 try:
1958 prompt = self.hooks.generate_prompt(False)
1950 prompt = self.hooks.generate_prompt(False)
1959 except:
1951 except:
1960 self.showtraceback()
1952 self.showtraceback()
1961 try:
1953 try:
1962 line = self.raw_input(prompt,more)
1954 line = self.raw_input(prompt,more)
1963 if self.exit_now:
1955 if self.exit_now:
1964 # quick exit on sys.std[in|out] close
1956 # quick exit on sys.std[in|out] close
1965 break
1957 break
1966 if self.autoindent:
1958 if self.autoindent:
1967 self.rl_do_indent = False
1959 self.rl_do_indent = False
1968
1960
1969 except KeyboardInterrupt:
1961 except KeyboardInterrupt:
1970 #double-guard against keyboardinterrupts during kbdint handling
1962 #double-guard against keyboardinterrupts during kbdint handling
1971 try:
1963 try:
1972 self.write('\nKeyboardInterrupt\n')
1964 self.write('\nKeyboardInterrupt\n')
1973 self.resetbuffer()
1965 self.resetbuffer()
1974 # keep cache in sync with the prompt counter:
1966 # keep cache in sync with the prompt counter:
1975 self.outputcache.prompt_count -= 1
1967 self.outputcache.prompt_count -= 1
1976
1968
1977 if self.autoindent:
1969 if self.autoindent:
1978 self.indent_current_nsp = 0
1970 self.indent_current_nsp = 0
1979 more = 0
1971 more = 0
1980 except KeyboardInterrupt:
1972 except KeyboardInterrupt:
1981 pass
1973 pass
1982 except EOFError:
1974 except EOFError:
1983 if self.autoindent:
1975 if self.autoindent:
1984 self.rl_do_indent = False
1976 self.rl_do_indent = False
1985 self.readline_startup_hook(None)
1977 self.readline_startup_hook(None)
1986 self.write('\n')
1978 self.write('\n')
1987 self.exit()
1979 self.exit()
1988 except bdb.BdbQuit:
1980 except bdb.BdbQuit:
1989 warn('The Python debugger has exited with a BdbQuit exception.\n'
1981 warn('The Python debugger has exited with a BdbQuit exception.\n'
1990 'Because of how pdb handles the stack, it is impossible\n'
1982 'Because of how pdb handles the stack, it is impossible\n'
1991 'for IPython to properly format this particular exception.\n'
1983 'for IPython to properly format this particular exception.\n'
1992 'IPython will resume normal operation.')
1984 'IPython will resume normal operation.')
1993 except:
1985 except:
1994 # exceptions here are VERY RARE, but they can be triggered
1986 # exceptions here are VERY RARE, but they can be triggered
1995 # asynchronously by signal handlers, for example.
1987 # asynchronously by signal handlers, for example.
1996 self.showtraceback()
1988 self.showtraceback()
1997 else:
1989 else:
1998 more = self.push(line)
1990 more = self.push(line)
1999 if (self.SyntaxTB.last_syntax_error and
1991 if (self.SyntaxTB.last_syntax_error and
2000 self.rc.autoedit_syntax):
1992 self.rc.autoedit_syntax):
2001 self.edit_syntax_error()
1993 self.edit_syntax_error()
2002
1994
2003 # We are off again...
1995 # We are off again...
2004 __builtin__.__dict__['__IPYTHON__active'] -= 1
1996 __builtin__.__dict__['__IPYTHON__active'] -= 1
2005
1997
2006 def excepthook(self, etype, value, tb):
1998 def excepthook(self, etype, value, tb):
2007 """One more defense for GUI apps that call sys.excepthook.
1999 """One more defense for GUI apps that call sys.excepthook.
2008
2000
2009 GUI frameworks like wxPython trap exceptions and call
2001 GUI frameworks like wxPython trap exceptions and call
2010 sys.excepthook themselves. I guess this is a feature that
2002 sys.excepthook themselves. I guess this is a feature that
2011 enables them to keep running after exceptions that would
2003 enables them to keep running after exceptions that would
2012 otherwise kill their mainloop. This is a bother for IPython
2004 otherwise kill their mainloop. This is a bother for IPython
2013 which excepts to catch all of the program exceptions with a try:
2005 which excepts to catch all of the program exceptions with a try:
2014 except: statement.
2006 except: statement.
2015
2007
2016 Normally, IPython sets sys.excepthook to a CrashHandler instance, so if
2008 Normally, IPython sets sys.excepthook to a CrashHandler instance, so if
2017 any app directly invokes sys.excepthook, it will look to the user like
2009 any app directly invokes sys.excepthook, it will look to the user like
2018 IPython crashed. In order to work around this, we can disable the
2010 IPython crashed. In order to work around this, we can disable the
2019 CrashHandler and replace it with this excepthook instead, which prints a
2011 CrashHandler and replace it with this excepthook instead, which prints a
2020 regular traceback using our InteractiveTB. In this fashion, apps which
2012 regular traceback using our InteractiveTB. In this fashion, apps which
2021 call sys.excepthook will generate a regular-looking exception from
2013 call sys.excepthook will generate a regular-looking exception from
2022 IPython, and the CrashHandler will only be triggered by real IPython
2014 IPython, and the CrashHandler will only be triggered by real IPython
2023 crashes.
2015 crashes.
2024
2016
2025 This hook should be used sparingly, only in places which are not likely
2017 This hook should be used sparingly, only in places which are not likely
2026 to be true IPython errors.
2018 to be true IPython errors.
2027 """
2019 """
2028 self.showtraceback((etype,value,tb),tb_offset=0)
2020 self.showtraceback((etype,value,tb),tb_offset=0)
2029
2021
2030 def expand_aliases(self,fn,rest):
2022 def expand_aliases(self,fn,rest):
2031 """ Expand multiple levels of aliases:
2023 """ Expand multiple levels of aliases:
2032
2024
2033 if:
2025 if:
2034
2026
2035 alias foo bar /tmp
2027 alias foo bar /tmp
2036 alias baz foo
2028 alias baz foo
2037
2029
2038 then:
2030 then:
2039
2031
2040 baz huhhahhei -> bar /tmp huhhahhei
2032 baz huhhahhei -> bar /tmp huhhahhei
2041
2033
2042 """
2034 """
2043 line = fn + " " + rest
2035 line = fn + " " + rest
2044
2036
2045 done = set()
2037 done = set()
2046 while 1:
2038 while 1:
2047 pre,fn,rest = prefilter.splitUserInput(line,
2039 pre,fn,rest = prefilter.splitUserInput(line,
2048 prefilter.shell_line_split)
2040 prefilter.shell_line_split)
2049 if fn in self.alias_table:
2041 if fn in self.alias_table:
2050 if fn in done:
2042 if fn in done:
2051 warn("Cyclic alias definition, repeated '%s'" % fn)
2043 warn("Cyclic alias definition, repeated '%s'" % fn)
2052 return ""
2044 return ""
2053 done.add(fn)
2045 done.add(fn)
2054
2046
2055 l2 = self.transform_alias(fn,rest)
2047 l2 = self.transform_alias(fn,rest)
2056 # dir -> dir
2048 # dir -> dir
2057 # print "alias",line, "->",l2 #dbg
2049 # print "alias",line, "->",l2 #dbg
2058 if l2 == line:
2050 if l2 == line:
2059 break
2051 break
2060 # ls -> ls -F should not recurse forever
2052 # ls -> ls -F should not recurse forever
2061 if l2.split(None,1)[0] == line.split(None,1)[0]:
2053 if l2.split(None,1)[0] == line.split(None,1)[0]:
2062 line = l2
2054 line = l2
2063 break
2055 break
2064
2056
2065 line=l2
2057 line=l2
2066
2058
2067
2059
2068 # print "al expand to",line #dbg
2060 # print "al expand to",line #dbg
2069 else:
2061 else:
2070 break
2062 break
2071
2063
2072 return line
2064 return line
2073
2065
2074 def transform_alias(self, alias,rest=''):
2066 def transform_alias(self, alias,rest=''):
2075 """ Transform alias to system command string.
2067 """ Transform alias to system command string.
2076 """
2068 """
2077 trg = self.alias_table[alias]
2069 trg = self.alias_table[alias]
2078
2070
2079 nargs,cmd = trg
2071 nargs,cmd = trg
2080 # print trg #dbg
2072 # print trg #dbg
2081 if ' ' in cmd and os.path.isfile(cmd):
2073 if ' ' in cmd and os.path.isfile(cmd):
2082 cmd = '"%s"' % cmd
2074 cmd = '"%s"' % cmd
2083
2075
2084 # Expand the %l special to be the user's input line
2076 # Expand the %l special to be the user's input line
2085 if cmd.find('%l') >= 0:
2077 if cmd.find('%l') >= 0:
2086 cmd = cmd.replace('%l',rest)
2078 cmd = cmd.replace('%l',rest)
2087 rest = ''
2079 rest = ''
2088 if nargs==0:
2080 if nargs==0:
2089 # Simple, argument-less aliases
2081 # Simple, argument-less aliases
2090 cmd = '%s %s' % (cmd,rest)
2082 cmd = '%s %s' % (cmd,rest)
2091 else:
2083 else:
2092 # Handle aliases with positional arguments
2084 # Handle aliases with positional arguments
2093 args = rest.split(None,nargs)
2085 args = rest.split(None,nargs)
2094 if len(args)< nargs:
2086 if len(args)< nargs:
2095 error('Alias <%s> requires %s arguments, %s given.' %
2087 error('Alias <%s> requires %s arguments, %s given.' %
2096 (alias,nargs,len(args)))
2088 (alias,nargs,len(args)))
2097 return None
2089 return None
2098 cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:]))
2090 cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:]))
2099 # Now call the macro, evaluating in the user's namespace
2091 # Now call the macro, evaluating in the user's namespace
2100 #print 'new command: <%r>' % cmd # dbg
2092 #print 'new command: <%r>' % cmd # dbg
2101 return cmd
2093 return cmd
2102
2094
2103 def call_alias(self,alias,rest=''):
2095 def call_alias(self,alias,rest=''):
2104 """Call an alias given its name and the rest of the line.
2096 """Call an alias given its name and the rest of the line.
2105
2097
2106 This is only used to provide backwards compatibility for users of
2098 This is only used to provide backwards compatibility for users of
2107 ipalias(), use of which is not recommended for anymore."""
2099 ipalias(), use of which is not recommended for anymore."""
2108
2100
2109 # Now call the macro, evaluating in the user's namespace
2101 # Now call the macro, evaluating in the user's namespace
2110 cmd = self.transform_alias(alias, rest)
2102 cmd = self.transform_alias(alias, rest)
2111 try:
2103 try:
2112 self.system(cmd)
2104 self.system(cmd)
2113 except:
2105 except:
2114 self.showtraceback()
2106 self.showtraceback()
2115
2107
2116 def indent_current_str(self):
2108 def indent_current_str(self):
2117 """return the current level of indentation as a string"""
2109 """return the current level of indentation as a string"""
2118 return self.indent_current_nsp * ' '
2110 return self.indent_current_nsp * ' '
2119
2111
2120 def autoindent_update(self,line):
2112 def autoindent_update(self,line):
2121 """Keep track of the indent level."""
2113 """Keep track of the indent level."""
2122
2114
2123 #debugx('line')
2115 #debugx('line')
2124 #debugx('self.indent_current_nsp')
2116 #debugx('self.indent_current_nsp')
2125 if self.autoindent:
2117 if self.autoindent:
2126 if line:
2118 if line:
2127 inisp = num_ini_spaces(line)
2119 inisp = num_ini_spaces(line)
2128 if inisp < self.indent_current_nsp:
2120 if inisp < self.indent_current_nsp:
2129 self.indent_current_nsp = inisp
2121 self.indent_current_nsp = inisp
2130
2122
2131 if line[-1] == ':':
2123 if line[-1] == ':':
2132 self.indent_current_nsp += 4
2124 self.indent_current_nsp += 4
2133 elif dedent_re.match(line):
2125 elif dedent_re.match(line):
2134 self.indent_current_nsp -= 4
2126 self.indent_current_nsp -= 4
2135 else:
2127 else:
2136 self.indent_current_nsp = 0
2128 self.indent_current_nsp = 0
2137
2129
2138 def runlines(self,lines):
2130 def runlines(self,lines):
2139 """Run a string of one or more lines of source.
2131 """Run a string of one or more lines of source.
2140
2132
2141 This method is capable of running a string containing multiple source
2133 This method is capable of running a string containing multiple source
2142 lines, as if they had been entered at the IPython prompt. Since it
2134 lines, as if they had been entered at the IPython prompt. Since it
2143 exposes IPython's processing machinery, the given strings can contain
2135 exposes IPython's processing machinery, the given strings can contain
2144 magic calls (%magic), special shell access (!cmd), etc."""
2136 magic calls (%magic), special shell access (!cmd), etc."""
2145
2137
2146 # We must start with a clean buffer, in case this is run from an
2138 # We must start with a clean buffer, in case this is run from an
2147 # interactive IPython session (via a magic, for example).
2139 # interactive IPython session (via a magic, for example).
2148 self.resetbuffer()
2140 self.resetbuffer()
2149 lines = lines.split('\n')
2141 lines = lines.split('\n')
2150 more = 0
2142 more = 0
2151
2143
2152 for line in lines:
2144 for line in lines:
2153 # skip blank lines so we don't mess up the prompt counter, but do
2145 # skip blank lines so we don't mess up the prompt counter, but do
2154 # NOT skip even a blank line if we are in a code block (more is
2146 # NOT skip even a blank line if we are in a code block (more is
2155 # true)
2147 # true)
2156
2148
2157 if line or more:
2149 if line or more:
2158 # push to raw history, so hist line numbers stay in sync
2150 # push to raw history, so hist line numbers stay in sync
2159 self.input_hist_raw.append("# " + line + "\n")
2151 self.input_hist_raw.append("# " + line + "\n")
2160 more = self.push(self.prefilter(line,more))
2152 more = self.push(self.prefilter(line,more))
2161 # IPython's runsource returns None if there was an error
2153 # IPython's runsource returns None if there was an error
2162 # compiling the code. This allows us to stop processing right
2154 # compiling the code. This allows us to stop processing right
2163 # away, so the user gets the error message at the right place.
2155 # away, so the user gets the error message at the right place.
2164 if more is None:
2156 if more is None:
2165 break
2157 break
2166 else:
2158 else:
2167 self.input_hist_raw.append("\n")
2159 self.input_hist_raw.append("\n")
2168 # final newline in case the input didn't have it, so that the code
2160 # final newline in case the input didn't have it, so that the code
2169 # actually does get executed
2161 # actually does get executed
2170 if more:
2162 if more:
2171 self.push('\n')
2163 self.push('\n')
2172
2164
2173 def runsource(self, source, filename='<input>', symbol='single'):
2165 def runsource(self, source, filename='<input>', symbol='single'):
2174 """Compile and run some source in the interpreter.
2166 """Compile and run some source in the interpreter.
2175
2167
2176 Arguments are as for compile_command().
2168 Arguments are as for compile_command().
2177
2169
2178 One several things can happen:
2170 One several things can happen:
2179
2171
2180 1) The input is incorrect; compile_command() raised an
2172 1) The input is incorrect; compile_command() raised an
2181 exception (SyntaxError or OverflowError). A syntax traceback
2173 exception (SyntaxError or OverflowError). A syntax traceback
2182 will be printed by calling the showsyntaxerror() method.
2174 will be printed by calling the showsyntaxerror() method.
2183
2175
2184 2) The input is incomplete, and more input is required;
2176 2) The input is incomplete, and more input is required;
2185 compile_command() returned None. Nothing happens.
2177 compile_command() returned None. Nothing happens.
2186
2178
2187 3) The input is complete; compile_command() returned a code
2179 3) The input is complete; compile_command() returned a code
2188 object. The code is executed by calling self.runcode() (which
2180 object. The code is executed by calling self.runcode() (which
2189 also handles run-time exceptions, except for SystemExit).
2181 also handles run-time exceptions, except for SystemExit).
2190
2182
2191 The return value is:
2183 The return value is:
2192
2184
2193 - True in case 2
2185 - True in case 2
2194
2186
2195 - False in the other cases, unless an exception is raised, where
2187 - False in the other cases, unless an exception is raised, where
2196 None is returned instead. This can be used by external callers to
2188 None is returned instead. This can be used by external callers to
2197 know whether to continue feeding input or not.
2189 know whether to continue feeding input or not.
2198
2190
2199 The return value can be used to decide whether to use sys.ps1 or
2191 The return value can be used to decide whether to use sys.ps1 or
2200 sys.ps2 to prompt the next line."""
2192 sys.ps2 to prompt the next line."""
2201
2193
2202 # if the source code has leading blanks, add 'if 1:\n' to it
2194 # if the source code has leading blanks, add 'if 1:\n' to it
2203 # this allows execution of indented pasted code. It is tempting
2195 # this allows execution of indented pasted code. It is tempting
2204 # to add '\n' at the end of source to run commands like ' a=1'
2196 # to add '\n' at the end of source to run commands like ' a=1'
2205 # directly, but this fails for more complicated scenarios
2197 # directly, but this fails for more complicated scenarios
2206 source=source.encode(self.stdin_encoding)
2198 source=source.encode(self.stdin_encoding)
2207 if source[:1] in [' ', '\t']:
2199 if source[:1] in [' ', '\t']:
2208 source = 'if 1:\n%s' % source
2200 source = 'if 1:\n%s' % source
2209
2201
2210 try:
2202 try:
2211 code = self.compile(source,filename,symbol)
2203 code = self.compile(source,filename,symbol)
2212 except (OverflowError, SyntaxError, ValueError, TypeError, MemoryError):
2204 except (OverflowError, SyntaxError, ValueError, TypeError, MemoryError):
2213 # Case 1
2205 # Case 1
2214 self.showsyntaxerror(filename)
2206 self.showsyntaxerror(filename)
2215 return None
2207 return None
2216
2208
2217 if code is None:
2209 if code is None:
2218 # Case 2
2210 # Case 2
2219 return True
2211 return True
2220
2212
2221 # Case 3
2213 # Case 3
2222 # We store the code object so that threaded shells and
2214 # We store the code object so that threaded shells and
2223 # custom exception handlers can access all this info if needed.
2215 # custom exception handlers can access all this info if needed.
2224 # The source corresponding to this can be obtained from the
2216 # The source corresponding to this can be obtained from the
2225 # buffer attribute as '\n'.join(self.buffer).
2217 # buffer attribute as '\n'.join(self.buffer).
2226 self.code_to_run = code
2218 self.code_to_run = code
2227 # now actually execute the code object
2219 # now actually execute the code object
2228 if self.runcode(code) == 0:
2220 if self.runcode(code) == 0:
2229 return False
2221 return False
2230 else:
2222 else:
2231 return None
2223 return None
2232
2224
2233 def runcode(self,code_obj):
2225 def runcode(self,code_obj):
2234 """Execute a code object.
2226 """Execute a code object.
2235
2227
2236 When an exception occurs, self.showtraceback() is called to display a
2228 When an exception occurs, self.showtraceback() is called to display a
2237 traceback.
2229 traceback.
2238
2230
2239 Return value: a flag indicating whether the code to be run completed
2231 Return value: a flag indicating whether the code to be run completed
2240 successfully:
2232 successfully:
2241
2233
2242 - 0: successful execution.
2234 - 0: successful execution.
2243 - 1: an error occurred.
2235 - 1: an error occurred.
2244 """
2236 """
2245
2237
2246 # Set our own excepthook in case the user code tries to call it
2238 # Set our own excepthook in case the user code tries to call it
2247 # directly, so that the IPython crash handler doesn't get triggered
2239 # directly, so that the IPython crash handler doesn't get triggered
2248 old_excepthook,sys.excepthook = sys.excepthook, self.excepthook
2240 old_excepthook,sys.excepthook = sys.excepthook, self.excepthook
2249
2241
2250 # we save the original sys.excepthook in the instance, in case config
2242 # we save the original sys.excepthook in the instance, in case config
2251 # code (such as magics) needs access to it.
2243 # code (such as magics) needs access to it.
2252 self.sys_excepthook = old_excepthook
2244 self.sys_excepthook = old_excepthook
2253 outflag = 1 # happens in more places, so it's easier as default
2245 outflag = 1 # happens in more places, so it's easier as default
2254 try:
2246 try:
2255 try:
2247 try:
2256 self.hooks.pre_runcode_hook()
2248 self.hooks.pre_runcode_hook()
2257 exec code_obj in self.user_global_ns, self.user_ns
2249 exec code_obj in self.user_global_ns, self.user_ns
2258 finally:
2250 finally:
2259 # Reset our crash handler in place
2251 # Reset our crash handler in place
2260 sys.excepthook = old_excepthook
2252 sys.excepthook = old_excepthook
2261 except SystemExit:
2253 except SystemExit:
2262 self.resetbuffer()
2254 self.resetbuffer()
2263 self.showtraceback()
2255 self.showtraceback()
2264 warn("Type %exit or %quit to exit IPython "
2256 warn("Type %exit or %quit to exit IPython "
2265 "(%Exit or %Quit do so unconditionally).",level=1)
2257 "(%Exit or %Quit do so unconditionally).",level=1)
2266 except self.custom_exceptions:
2258 except self.custom_exceptions:
2267 etype,value,tb = sys.exc_info()
2259 etype,value,tb = sys.exc_info()
2268 self.CustomTB(etype,value,tb)
2260 self.CustomTB(etype,value,tb)
2269 except:
2261 except:
2270 self.showtraceback()
2262 self.showtraceback()
2271 else:
2263 else:
2272 outflag = 0
2264 outflag = 0
2273 if softspace(sys.stdout, 0):
2265 if softspace(sys.stdout, 0):
2274 print
2266 print
2275 # Flush out code object which has been run (and source)
2267 # Flush out code object which has been run (and source)
2276 self.code_to_run = None
2268 self.code_to_run = None
2277 return outflag
2269 return outflag
2278
2270
2279 def push(self, line):
2271 def push(self, line):
2280 """Push a line to the interpreter.
2272 """Push a line to the interpreter.
2281
2273
2282 The line should not have a trailing newline; it may have
2274 The line should not have a trailing newline; it may have
2283 internal newlines. The line is appended to a buffer and the
2275 internal newlines. The line is appended to a buffer and the
2284 interpreter's runsource() method is called with the
2276 interpreter's runsource() method is called with the
2285 concatenated contents of the buffer as source. If this
2277 concatenated contents of the buffer as source. If this
2286 indicates that the command was executed or invalid, the buffer
2278 indicates that the command was executed or invalid, the buffer
2287 is reset; otherwise, the command is incomplete, and the buffer
2279 is reset; otherwise, the command is incomplete, and the buffer
2288 is left as it was after the line was appended. The return
2280 is left as it was after the line was appended. The return
2289 value is 1 if more input is required, 0 if the line was dealt
2281 value is 1 if more input is required, 0 if the line was dealt
2290 with in some way (this is the same as runsource()).
2282 with in some way (this is the same as runsource()).
2291 """
2283 """
2292
2284
2293 # autoindent management should be done here, and not in the
2285 # autoindent management should be done here, and not in the
2294 # interactive loop, since that one is only seen by keyboard input. We
2286 # interactive loop, since that one is only seen by keyboard input. We
2295 # need this done correctly even for code run via runlines (which uses
2287 # need this done correctly even for code run via runlines (which uses
2296 # push).
2288 # push).
2297
2289
2298 #print 'push line: <%s>' % line # dbg
2290 #print 'push line: <%s>' % line # dbg
2299 for subline in line.splitlines():
2291 for subline in line.splitlines():
2300 self.autoindent_update(subline)
2292 self.autoindent_update(subline)
2301 self.buffer.append(line)
2293 self.buffer.append(line)
2302 more = self.runsource('\n'.join(self.buffer), self.filename)
2294 more = self.runsource('\n'.join(self.buffer), self.filename)
2303 if not more:
2295 if not more:
2304 self.resetbuffer()
2296 self.resetbuffer()
2305 return more
2297 return more
2306
2298
2307 def split_user_input(self, line):
2299 def split_user_input(self, line):
2308 # This is really a hold-over to support ipapi and some extensions
2300 # This is really a hold-over to support ipapi and some extensions
2309 return prefilter.splitUserInput(line)
2301 return prefilter.splitUserInput(line)
2310
2302
2311 def resetbuffer(self):
2303 def resetbuffer(self):
2312 """Reset the input buffer."""
2304 """Reset the input buffer."""
2313 self.buffer[:] = []
2305 self.buffer[:] = []
2314
2306
2315 def raw_input(self,prompt='',continue_prompt=False):
2307 def raw_input(self,prompt='',continue_prompt=False):
2316 """Write a prompt and read a line.
2308 """Write a prompt and read a line.
2317
2309
2318 The returned line does not include the trailing newline.
2310 The returned line does not include the trailing newline.
2319 When the user enters the EOF key sequence, EOFError is raised.
2311 When the user enters the EOF key sequence, EOFError is raised.
2320
2312
2321 Optional inputs:
2313 Optional inputs:
2322
2314
2323 - prompt(''): a string to be printed to prompt the user.
2315 - prompt(''): a string to be printed to prompt the user.
2324
2316
2325 - continue_prompt(False): whether this line is the first one or a
2317 - continue_prompt(False): whether this line is the first one or a
2326 continuation in a sequence of inputs.
2318 continuation in a sequence of inputs.
2327 """
2319 """
2328
2320
2329 # Code run by the user may have modified the readline completer state.
2321 # Code run by the user may have modified the readline completer state.
2330 # We must ensure that our completer is back in place.
2322 # We must ensure that our completer is back in place.
2331 if self.has_readline:
2323 if self.has_readline:
2332 self.set_completer()
2324 self.set_completer()
2333
2325
2334 try:
2326 try:
2335 line = raw_input_original(prompt).decode(self.stdin_encoding)
2327 line = raw_input_original(prompt).decode(self.stdin_encoding)
2336 except ValueError:
2328 except ValueError:
2337 warn("\n********\nYou or a %run:ed script called sys.stdin.close()"
2329 warn("\n********\nYou or a %run:ed script called sys.stdin.close()"
2338 " or sys.stdout.close()!\nExiting IPython!")
2330 " or sys.stdout.close()!\nExiting IPython!")
2339 self.ask_exit()
2331 self.ask_exit()
2340 return ""
2332 return ""
2341
2333
2342 # Try to be reasonably smart about not re-indenting pasted input more
2334 # Try to be reasonably smart about not re-indenting pasted input more
2343 # than necessary. We do this by trimming out the auto-indent initial
2335 # than necessary. We do this by trimming out the auto-indent initial
2344 # spaces, if the user's actual input started itself with whitespace.
2336 # spaces, if the user's actual input started itself with whitespace.
2345 #debugx('self.buffer[-1]')
2337 #debugx('self.buffer[-1]')
2346
2338
2347 if self.autoindent:
2339 if self.autoindent:
2348 if num_ini_spaces(line) > self.indent_current_nsp:
2340 if num_ini_spaces(line) > self.indent_current_nsp:
2349 line = line[self.indent_current_nsp:]
2341 line = line[self.indent_current_nsp:]
2350 self.indent_current_nsp = 0
2342 self.indent_current_nsp = 0
2351
2343
2352 # store the unfiltered input before the user has any chance to modify
2344 # store the unfiltered input before the user has any chance to modify
2353 # it.
2345 # it.
2354 if line.strip():
2346 if line.strip():
2355 if continue_prompt:
2347 if continue_prompt:
2356 self.input_hist_raw[-1] += '%s\n' % line
2348 self.input_hist_raw[-1] += '%s\n' % line
2357 if self.has_readline: # and some config option is set?
2349 if self.has_readline: # and some config option is set?
2358 try:
2350 try:
2359 histlen = self.readline.get_current_history_length()
2351 histlen = self.readline.get_current_history_length()
2360 if histlen > 1:
2352 if histlen > 1:
2361 newhist = self.input_hist_raw[-1].rstrip()
2353 newhist = self.input_hist_raw[-1].rstrip()
2362 self.readline.remove_history_item(histlen-1)
2354 self.readline.remove_history_item(histlen-1)
2363 self.readline.replace_history_item(histlen-2,
2355 self.readline.replace_history_item(histlen-2,
2364 newhist.encode(self.stdin_encoding))
2356 newhist.encode(self.stdin_encoding))
2365 except AttributeError:
2357 except AttributeError:
2366 pass # re{move,place}_history_item are new in 2.4.
2358 pass # re{move,place}_history_item are new in 2.4.
2367 else:
2359 else:
2368 self.input_hist_raw.append('%s\n' % line)
2360 self.input_hist_raw.append('%s\n' % line)
2369 # only entries starting at first column go to shadow history
2361 # only entries starting at first column go to shadow history
2370 if line.lstrip() == line:
2362 if line.lstrip() == line:
2371 self.shadowhist.add(line.strip())
2363 self.shadowhist.add(line.strip())
2372 elif not continue_prompt:
2364 elif not continue_prompt:
2373 self.input_hist_raw.append('\n')
2365 self.input_hist_raw.append('\n')
2374 try:
2366 try:
2375 lineout = self.prefilter(line,continue_prompt)
2367 lineout = self.prefilter(line,continue_prompt)
2376 except:
2368 except:
2377 # blanket except, in case a user-defined prefilter crashes, so it
2369 # blanket except, in case a user-defined prefilter crashes, so it
2378 # can't take all of ipython with it.
2370 # can't take all of ipython with it.
2379 self.showtraceback()
2371 self.showtraceback()
2380 return ''
2372 return ''
2381 else:
2373 else:
2382 return lineout
2374 return lineout
2383
2375
2384 def _prefilter(self, line, continue_prompt):
2376 def _prefilter(self, line, continue_prompt):
2385 """Calls different preprocessors, depending on the form of line."""
2377 """Calls different preprocessors, depending on the form of line."""
2386
2378
2387 # All handlers *must* return a value, even if it's blank ('').
2379 # All handlers *must* return a value, even if it's blank ('').
2388
2380
2389 # Lines are NOT logged here. Handlers should process the line as
2381 # Lines are NOT logged here. Handlers should process the line as
2390 # needed, update the cache AND log it (so that the input cache array
2382 # needed, update the cache AND log it (so that the input cache array
2391 # stays synced).
2383 # stays synced).
2392
2384
2393 #.....................................................................
2385 #.....................................................................
2394 # Code begins
2386 # Code begins
2395
2387
2396 #if line.startswith('%crash'): raise RuntimeError,'Crash now!' # dbg
2388 #if line.startswith('%crash'): raise RuntimeError,'Crash now!' # dbg
2397
2389
2398 # save the line away in case we crash, so the post-mortem handler can
2390 # save the line away in case we crash, so the post-mortem handler can
2399 # record it
2391 # record it
2400 self._last_input_line = line
2392 self._last_input_line = line
2401
2393
2402 #print '***line: <%s>' % line # dbg
2394 #print '***line: <%s>' % line # dbg
2403
2395
2404 if not line:
2396 if not line:
2405 # Return immediately on purely empty lines, so that if the user
2397 # Return immediately on purely empty lines, so that if the user
2406 # previously typed some whitespace that started a continuation
2398 # previously typed some whitespace that started a continuation
2407 # prompt, he can break out of that loop with just an empty line.
2399 # prompt, he can break out of that loop with just an empty line.
2408 # This is how the default python prompt works.
2400 # This is how the default python prompt works.
2409
2401
2410 # Only return if the accumulated input buffer was just whitespace!
2402 # Only return if the accumulated input buffer was just whitespace!
2411 if ''.join(self.buffer).isspace():
2403 if ''.join(self.buffer).isspace():
2412 self.buffer[:] = []
2404 self.buffer[:] = []
2413 return ''
2405 return ''
2414
2406
2415 line_info = prefilter.LineInfo(line, continue_prompt)
2407 line_info = prefilter.LineInfo(line, continue_prompt)
2416
2408
2417 # the input history needs to track even empty lines
2409 # the input history needs to track even empty lines
2418 stripped = line.strip()
2410 stripped = line.strip()
2419
2411
2420 if not stripped:
2412 if not stripped:
2421 if not continue_prompt:
2413 if not continue_prompt:
2422 self.outputcache.prompt_count -= 1
2414 self.outputcache.prompt_count -= 1
2423 return self.handle_normal(line_info)
2415 return self.handle_normal(line_info)
2424
2416
2425 # print '***cont',continue_prompt # dbg
2417 # print '***cont',continue_prompt # dbg
2426 # special handlers are only allowed for single line statements
2418 # special handlers are only allowed for single line statements
2427 if continue_prompt and not self.rc.multi_line_specials:
2419 if continue_prompt and not self.rc.multi_line_specials:
2428 return self.handle_normal(line_info)
2420 return self.handle_normal(line_info)
2429
2421
2430
2422
2431 # See whether any pre-existing handler can take care of it
2423 # See whether any pre-existing handler can take care of it
2432 rewritten = self.hooks.input_prefilter(stripped)
2424 rewritten = self.hooks.input_prefilter(stripped)
2433 if rewritten != stripped: # ok, some prefilter did something
2425 if rewritten != stripped: # ok, some prefilter did something
2434 rewritten = line_info.pre + rewritten # add indentation
2426 rewritten = line_info.pre + rewritten # add indentation
2435 return self.handle_normal(prefilter.LineInfo(rewritten,
2427 return self.handle_normal(prefilter.LineInfo(rewritten,
2436 continue_prompt))
2428 continue_prompt))
2437
2429
2438 #print 'pre <%s> iFun <%s> rest <%s>' % (pre,iFun,theRest) # dbg
2430 #print 'pre <%s> iFun <%s> rest <%s>' % (pre,iFun,theRest) # dbg
2439
2431
2440 return prefilter.prefilter(line_info, self)
2432 return prefilter.prefilter(line_info, self)
2441
2433
2442
2434
2443 def _prefilter_dumb(self, line, continue_prompt):
2435 def _prefilter_dumb(self, line, continue_prompt):
2444 """simple prefilter function, for debugging"""
2436 """simple prefilter function, for debugging"""
2445 return self.handle_normal(line,continue_prompt)
2437 return self.handle_normal(line,continue_prompt)
2446
2438
2447
2439
2448 def multiline_prefilter(self, line, continue_prompt):
2440 def multiline_prefilter(self, line, continue_prompt):
2449 """ Run _prefilter for each line of input
2441 """ Run _prefilter for each line of input
2450
2442
2451 Covers cases where there are multiple lines in the user entry,
2443 Covers cases where there are multiple lines in the user entry,
2452 which is the case when the user goes back to a multiline history
2444 which is the case when the user goes back to a multiline history
2453 entry and presses enter.
2445 entry and presses enter.
2454
2446
2455 """
2447 """
2456 out = []
2448 out = []
2457 for l in line.rstrip('\n').split('\n'):
2449 for l in line.rstrip('\n').split('\n'):
2458 out.append(self._prefilter(l, continue_prompt))
2450 out.append(self._prefilter(l, continue_prompt))
2459 return '\n'.join(out)
2451 return '\n'.join(out)
2460
2452
2461 # Set the default prefilter() function (this can be user-overridden)
2453 # Set the default prefilter() function (this can be user-overridden)
2462 prefilter = multiline_prefilter
2454 prefilter = multiline_prefilter
2463
2455
2464 def handle_normal(self,line_info):
2456 def handle_normal(self,line_info):
2465 """Handle normal input lines. Use as a template for handlers."""
2457 """Handle normal input lines. Use as a template for handlers."""
2466
2458
2467 # With autoindent on, we need some way to exit the input loop, and I
2459 # With autoindent on, we need some way to exit the input loop, and I
2468 # don't want to force the user to have to backspace all the way to
2460 # don't want to force the user to have to backspace all the way to
2469 # clear the line. The rule will be in this case, that either two
2461 # clear the line. The rule will be in this case, that either two
2470 # lines of pure whitespace in a row, or a line of pure whitespace but
2462 # lines of pure whitespace in a row, or a line of pure whitespace but
2471 # of a size different to the indent level, will exit the input loop.
2463 # of a size different to the indent level, will exit the input loop.
2472 line = line_info.line
2464 line = line_info.line
2473 continue_prompt = line_info.continue_prompt
2465 continue_prompt = line_info.continue_prompt
2474
2466
2475 if (continue_prompt and self.autoindent and line.isspace() and
2467 if (continue_prompt and self.autoindent and line.isspace() and
2476 (0 < abs(len(line) - self.indent_current_nsp) <= 2 or
2468 (0 < abs(len(line) - self.indent_current_nsp) <= 2 or
2477 (self.buffer[-1]).isspace() )):
2469 (self.buffer[-1]).isspace() )):
2478 line = ''
2470 line = ''
2479
2471
2480 self.log(line,line,continue_prompt)
2472 self.log(line,line,continue_prompt)
2481 return line
2473 return line
2482
2474
2483 def handle_alias(self,line_info):
2475 def handle_alias(self,line_info):
2484 """Handle alias input lines. """
2476 """Handle alias input lines. """
2485 tgt = self.alias_table[line_info.iFun]
2477 tgt = self.alias_table[line_info.iFun]
2486 # print "=>",tgt #dbg
2478 # print "=>",tgt #dbg
2487 if callable(tgt):
2479 if callable(tgt):
2488 if '$' in line_info.line:
2480 if '$' in line_info.line:
2489 call_meth = '(_ip, _ip.itpl(%s))'
2481 call_meth = '(_ip, _ip.itpl(%s))'
2490 else:
2482 else:
2491 call_meth = '(_ip,%s)'
2483 call_meth = '(_ip,%s)'
2492 line_out = ("%s_sh.%s" + call_meth) % (line_info.preWhitespace,
2484 line_out = ("%s_sh.%s" + call_meth) % (line_info.preWhitespace,
2493 line_info.iFun,
2485 line_info.iFun,
2494 make_quoted_expr(line_info.line))
2486 make_quoted_expr(line_info.line))
2495 else:
2487 else:
2496 transformed = self.expand_aliases(line_info.iFun,line_info.theRest)
2488 transformed = self.expand_aliases(line_info.iFun,line_info.theRest)
2497
2489
2498 # pre is needed, because it carries the leading whitespace. Otherwise
2490 # pre is needed, because it carries the leading whitespace. Otherwise
2499 # aliases won't work in indented sections.
2491 # aliases won't work in indented sections.
2500 line_out = '%s_ip.system(%s)' % (line_info.preWhitespace,
2492 line_out = '%s_ip.system(%s)' % (line_info.preWhitespace,
2501 make_quoted_expr( transformed ))
2493 make_quoted_expr( transformed ))
2502
2494
2503 self.log(line_info.line,line_out,line_info.continue_prompt)
2495 self.log(line_info.line,line_out,line_info.continue_prompt)
2504 #print 'line out:',line_out # dbg
2496 #print 'line out:',line_out # dbg
2505 return line_out
2497 return line_out
2506
2498
2507 def handle_shell_escape(self, line_info):
2499 def handle_shell_escape(self, line_info):
2508 """Execute the line in a shell, empty return value"""
2500 """Execute the line in a shell, empty return value"""
2509 #print 'line in :', `line` # dbg
2501 #print 'line in :', `line` # dbg
2510 line = line_info.line
2502 line = line_info.line
2511 if line.lstrip().startswith('!!'):
2503 if line.lstrip().startswith('!!'):
2512 # rewrite LineInfo's line, iFun and theRest to properly hold the
2504 # rewrite LineInfo's line, iFun and theRest to properly hold the
2513 # call to %sx and the actual command to be executed, so
2505 # call to %sx and the actual command to be executed, so
2514 # handle_magic can work correctly. Note that this works even if
2506 # handle_magic can work correctly. Note that this works even if
2515 # the line is indented, so it handles multi_line_specials
2507 # the line is indented, so it handles multi_line_specials
2516 # properly.
2508 # properly.
2517 new_rest = line.lstrip()[2:]
2509 new_rest = line.lstrip()[2:]
2518 line_info.line = '%ssx %s' % (self.ESC_MAGIC,new_rest)
2510 line_info.line = '%ssx %s' % (self.ESC_MAGIC,new_rest)
2519 line_info.iFun = 'sx'
2511 line_info.iFun = 'sx'
2520 line_info.theRest = new_rest
2512 line_info.theRest = new_rest
2521 return self.handle_magic(line_info)
2513 return self.handle_magic(line_info)
2522 else:
2514 else:
2523 cmd = line.lstrip().lstrip('!')
2515 cmd = line.lstrip().lstrip('!')
2524 line_out = '%s_ip.system(%s)' % (line_info.preWhitespace,
2516 line_out = '%s_ip.system(%s)' % (line_info.preWhitespace,
2525 make_quoted_expr(cmd))
2517 make_quoted_expr(cmd))
2526 # update cache/log and return
2518 # update cache/log and return
2527 self.log(line,line_out,line_info.continue_prompt)
2519 self.log(line,line_out,line_info.continue_prompt)
2528 return line_out
2520 return line_out
2529
2521
2530 def handle_magic(self, line_info):
2522 def handle_magic(self, line_info):
2531 """Execute magic functions."""
2523 """Execute magic functions."""
2532 iFun = line_info.iFun
2524 iFun = line_info.iFun
2533 theRest = line_info.theRest
2525 theRest = line_info.theRest
2534 cmd = '%s_ip.magic(%s)' % (line_info.preWhitespace,
2526 cmd = '%s_ip.magic(%s)' % (line_info.preWhitespace,
2535 make_quoted_expr(iFun + " " + theRest))
2527 make_quoted_expr(iFun + " " + theRest))
2536 self.log(line_info.line,cmd,line_info.continue_prompt)
2528 self.log(line_info.line,cmd,line_info.continue_prompt)
2537 #print 'in handle_magic, cmd=<%s>' % cmd # dbg
2529 #print 'in handle_magic, cmd=<%s>' % cmd # dbg
2538 return cmd
2530 return cmd
2539
2531
2540 def handle_auto(self, line_info):
2532 def handle_auto(self, line_info):
2541 """Hande lines which can be auto-executed, quoting if requested."""
2533 """Hande lines which can be auto-executed, quoting if requested."""
2542
2534
2543 line = line_info.line
2535 line = line_info.line
2544 iFun = line_info.iFun
2536 iFun = line_info.iFun
2545 theRest = line_info.theRest
2537 theRest = line_info.theRest
2546 pre = line_info.pre
2538 pre = line_info.pre
2547 continue_prompt = line_info.continue_prompt
2539 continue_prompt = line_info.continue_prompt
2548 obj = line_info.ofind(self)['obj']
2540 obj = line_info.ofind(self)['obj']
2549
2541
2550 #print 'pre <%s> iFun <%s> rest <%s>' % (pre,iFun,theRest) # dbg
2542 #print 'pre <%s> iFun <%s> rest <%s>' % (pre,iFun,theRest) # dbg
2551
2543
2552 # This should only be active for single-line input!
2544 # This should only be active for single-line input!
2553 if continue_prompt:
2545 if continue_prompt:
2554 self.log(line,line,continue_prompt)
2546 self.log(line,line,continue_prompt)
2555 return line
2547 return line
2556
2548
2557 force_auto = isinstance(obj, IPython.ipapi.IPyAutocall)
2549 force_auto = isinstance(obj, IPython.ipapi.IPyAutocall)
2558 auto_rewrite = True
2550 auto_rewrite = True
2559
2551
2560 if pre == self.ESC_QUOTE:
2552 if pre == self.ESC_QUOTE:
2561 # Auto-quote splitting on whitespace
2553 # Auto-quote splitting on whitespace
2562 newcmd = '%s("%s")' % (iFun,'", "'.join(theRest.split()) )
2554 newcmd = '%s("%s")' % (iFun,'", "'.join(theRest.split()) )
2563 elif pre == self.ESC_QUOTE2:
2555 elif pre == self.ESC_QUOTE2:
2564 # Auto-quote whole string
2556 # Auto-quote whole string
2565 newcmd = '%s("%s")' % (iFun,theRest)
2557 newcmd = '%s("%s")' % (iFun,theRest)
2566 elif pre == self.ESC_PAREN:
2558 elif pre == self.ESC_PAREN:
2567 newcmd = '%s(%s)' % (iFun,",".join(theRest.split()))
2559 newcmd = '%s(%s)' % (iFun,",".join(theRest.split()))
2568 else:
2560 else:
2569 # Auto-paren.
2561 # Auto-paren.
2570 # We only apply it to argument-less calls if the autocall
2562 # We only apply it to argument-less calls if the autocall
2571 # parameter is set to 2. We only need to check that autocall is <
2563 # parameter is set to 2. We only need to check that autocall is <
2572 # 2, since this function isn't called unless it's at least 1.
2564 # 2, since this function isn't called unless it's at least 1.
2573 if not theRest and (self.rc.autocall < 2) and not force_auto:
2565 if not theRest and (self.rc.autocall < 2) and not force_auto:
2574 newcmd = '%s %s' % (iFun,theRest)
2566 newcmd = '%s %s' % (iFun,theRest)
2575 auto_rewrite = False
2567 auto_rewrite = False
2576 else:
2568 else:
2577 if not force_auto and theRest.startswith('['):
2569 if not force_auto and theRest.startswith('['):
2578 if hasattr(obj,'__getitem__'):
2570 if hasattr(obj,'__getitem__'):
2579 # Don't autocall in this case: item access for an object
2571 # Don't autocall in this case: item access for an object
2580 # which is BOTH callable and implements __getitem__.
2572 # which is BOTH callable and implements __getitem__.
2581 newcmd = '%s %s' % (iFun,theRest)
2573 newcmd = '%s %s' % (iFun,theRest)
2582 auto_rewrite = False
2574 auto_rewrite = False
2583 else:
2575 else:
2584 # if the object doesn't support [] access, go ahead and
2576 # if the object doesn't support [] access, go ahead and
2585 # autocall
2577 # autocall
2586 newcmd = '%s(%s)' % (iFun.rstrip(),theRest)
2578 newcmd = '%s(%s)' % (iFun.rstrip(),theRest)
2587 elif theRest.endswith(';'):
2579 elif theRest.endswith(';'):
2588 newcmd = '%s(%s);' % (iFun.rstrip(),theRest[:-1])
2580 newcmd = '%s(%s);' % (iFun.rstrip(),theRest[:-1])
2589 else:
2581 else:
2590 newcmd = '%s(%s)' % (iFun.rstrip(), theRest)
2582 newcmd = '%s(%s)' % (iFun.rstrip(), theRest)
2591
2583
2592 if auto_rewrite:
2584 if auto_rewrite:
2593 rw = self.outputcache.prompt1.auto_rewrite() + newcmd
2585 rw = self.outputcache.prompt1.auto_rewrite() + newcmd
2594
2586
2595 try:
2587 try:
2596 # plain ascii works better w/ pyreadline, on some machines, so
2588 # plain ascii works better w/ pyreadline, on some machines, so
2597 # we use it and only print uncolored rewrite if we have unicode
2589 # we use it and only print uncolored rewrite if we have unicode
2598 rw = str(rw)
2590 rw = str(rw)
2599 print >>Term.cout, rw
2591 print >>Term.cout, rw
2600 except UnicodeEncodeError:
2592 except UnicodeEncodeError:
2601 print "-------------->" + newcmd
2593 print "-------------->" + newcmd
2602
2594
2603 # log what is now valid Python, not the actual user input (without the
2595 # log what is now valid Python, not the actual user input (without the
2604 # final newline)
2596 # final newline)
2605 self.log(line,newcmd,continue_prompt)
2597 self.log(line,newcmd,continue_prompt)
2606 return newcmd
2598 return newcmd
2607
2599
2608 def handle_help(self, line_info):
2600 def handle_help(self, line_info):
2609 """Try to get some help for the object.
2601 """Try to get some help for the object.
2610
2602
2611 obj? or ?obj -> basic information.
2603 obj? or ?obj -> basic information.
2612 obj?? or ??obj -> more details.
2604 obj?? or ??obj -> more details.
2613 """
2605 """
2614
2606
2615 line = line_info.line
2607 line = line_info.line
2616 # We need to make sure that we don't process lines which would be
2608 # We need to make sure that we don't process lines which would be
2617 # otherwise valid python, such as "x=1 # what?"
2609 # otherwise valid python, such as "x=1 # what?"
2618 try:
2610 try:
2619 codeop.compile_command(line)
2611 codeop.compile_command(line)
2620 except SyntaxError:
2612 except SyntaxError:
2621 # We should only handle as help stuff which is NOT valid syntax
2613 # We should only handle as help stuff which is NOT valid syntax
2622 if line[0]==self.ESC_HELP:
2614 if line[0]==self.ESC_HELP:
2623 line = line[1:]
2615 line = line[1:]
2624 elif line[-1]==self.ESC_HELP:
2616 elif line[-1]==self.ESC_HELP:
2625 line = line[:-1]
2617 line = line[:-1]
2626 self.log(line,'#?'+line,line_info.continue_prompt)
2618 self.log(line,'#?'+line,line_info.continue_prompt)
2627 if line:
2619 if line:
2628 #print 'line:<%r>' % line # dbg
2620 #print 'line:<%r>' % line # dbg
2629 self.magic_pinfo(line)
2621 self.magic_pinfo(line)
2630 else:
2622 else:
2631 page(self.usage,screen_lines=self.rc.screen_length)
2623 page(self.usage,screen_lines=self.rc.screen_length)
2632 return '' # Empty string is needed here!
2624 return '' # Empty string is needed here!
2633 except:
2625 except:
2634 # Pass any other exceptions through to the normal handler
2626 # Pass any other exceptions through to the normal handler
2635 return self.handle_normal(line_info)
2627 return self.handle_normal(line_info)
2636 else:
2628 else:
2637 # If the code compiles ok, we should handle it normally
2629 # If the code compiles ok, we should handle it normally
2638 return self.handle_normal(line_info)
2630 return self.handle_normal(line_info)
2639
2631
2640 def getapi(self):
2632 def getapi(self):
2641 """ Get an IPApi object for this shell instance
2633 """ Get an IPApi object for this shell instance
2642
2634
2643 Getting an IPApi object is always preferable to accessing the shell
2635 Getting an IPApi object is always preferable to accessing the shell
2644 directly, but this holds true especially for extensions.
2636 directly, but this holds true especially for extensions.
2645
2637
2646 It should always be possible to implement an extension with IPApi
2638 It should always be possible to implement an extension with IPApi
2647 alone. If not, contact maintainer to request an addition.
2639 alone. If not, contact maintainer to request an addition.
2648
2640
2649 """
2641 """
2650 return self.api
2642 return self.api
2651
2643
2652 def handle_emacs(self, line_info):
2644 def handle_emacs(self, line_info):
2653 """Handle input lines marked by python-mode."""
2645 """Handle input lines marked by python-mode."""
2654
2646
2655 # Currently, nothing is done. Later more functionality can be added
2647 # Currently, nothing is done. Later more functionality can be added
2656 # here if needed.
2648 # here if needed.
2657
2649
2658 # The input cache shouldn't be updated
2650 # The input cache shouldn't be updated
2659 return line_info.line
2651 return line_info.line
2660
2652
2661
2653
2662 def mktempfile(self,data=None):
2654 def mktempfile(self,data=None):
2663 """Make a new tempfile and return its filename.
2655 """Make a new tempfile and return its filename.
2664
2656
2665 This makes a call to tempfile.mktemp, but it registers the created
2657 This makes a call to tempfile.mktemp, but it registers the created
2666 filename internally so ipython cleans it up at exit time.
2658 filename internally so ipython cleans it up at exit time.
2667
2659
2668 Optional inputs:
2660 Optional inputs:
2669
2661
2670 - data(None): if data is given, it gets written out to the temp file
2662 - data(None): if data is given, it gets written out to the temp file
2671 immediately, and the file is closed again."""
2663 immediately, and the file is closed again."""
2672
2664
2673 filename = tempfile.mktemp('.py','ipython_edit_')
2665 filename = tempfile.mktemp('.py','ipython_edit_')
2674 self.tempfiles.append(filename)
2666 self.tempfiles.append(filename)
2675
2667
2676 if data:
2668 if data:
2677 tmp_file = open(filename,'w')
2669 tmp_file = open(filename,'w')
2678 tmp_file.write(data)
2670 tmp_file.write(data)
2679 tmp_file.close()
2671 tmp_file.close()
2680 return filename
2672 return filename
2681
2673
2682 def write(self,data):
2674 def write(self,data):
2683 """Write a string to the default output"""
2675 """Write a string to the default output"""
2684 Term.cout.write(data)
2676 Term.cout.write(data)
2685
2677
2686 def write_err(self,data):
2678 def write_err(self,data):
2687 """Write a string to the default error output"""
2679 """Write a string to the default error output"""
2688 Term.cerr.write(data)
2680 Term.cerr.write(data)
2689
2681
2690 def ask_exit(self):
2682 def ask_exit(self):
2691 """ Call for exiting. Can be overiden and used as a callback. """
2683 """ Call for exiting. Can be overiden and used as a callback. """
2692 self.exit_now = True
2684 self.exit_now = True
2693
2685
2694 def exit(self):
2686 def exit(self):
2695 """Handle interactive exit.
2687 """Handle interactive exit.
2696
2688
2697 This method calls the ask_exit callback."""
2689 This method calls the ask_exit callback."""
2698
2690
2699 if self.rc.confirm_exit:
2691 if self.rc.confirm_exit:
2700 if self.ask_yes_no('Do you really want to exit ([y]/n)?','y'):
2692 if self.ask_yes_no('Do you really want to exit ([y]/n)?','y'):
2701 self.ask_exit()
2693 self.ask_exit()
2702 else:
2694 else:
2703 self.ask_exit()
2695 self.ask_exit()
2704
2696
2705 def safe_execfile(self,fname,*where,**kw):
2697 def safe_execfile(self,fname,*where,**kw):
2706 """A safe version of the builtin execfile().
2698 """A safe version of the builtin execfile().
2707
2699
2708 This version will never throw an exception, and knows how to handle
2700 This version will never throw an exception, and knows how to handle
2709 ipython logs as well.
2701 ipython logs as well.
2710
2702
2711 :Parameters:
2703 :Parameters:
2712 fname : string
2704 fname : string
2713 Name of the file to be executed.
2705 Name of the file to be executed.
2714
2706
2715 where : tuple
2707 where : tuple
2716 One or two namespaces, passed to execfile() as (globals,locals).
2708 One or two namespaces, passed to execfile() as (globals,locals).
2717 If only one is given, it is passed as both.
2709 If only one is given, it is passed as both.
2718
2710
2719 :Keywords:
2711 :Keywords:
2720 islog : boolean (False)
2712 islog : boolean (False)
2721
2713
2722 quiet : boolean (True)
2714 quiet : boolean (True)
2723
2715
2724 exit_ignore : boolean (False)
2716 exit_ignore : boolean (False)
2725 """
2717 """
2726
2718
2727 def syspath_cleanup():
2719 def syspath_cleanup():
2728 """Internal cleanup routine for sys.path."""
2720 """Internal cleanup routine for sys.path."""
2729 if add_dname:
2721 if add_dname:
2730 try:
2722 try:
2731 sys.path.remove(dname)
2723 sys.path.remove(dname)
2732 except ValueError:
2724 except ValueError:
2733 # For some reason the user has already removed it, ignore.
2725 # For some reason the user has already removed it, ignore.
2734 pass
2726 pass
2735
2727
2736 fname = os.path.expanduser(fname)
2728 fname = os.path.expanduser(fname)
2737
2729
2738 # Find things also in current directory. This is needed to mimic the
2730 # Find things also in current directory. This is needed to mimic the
2739 # behavior of running a script from the system command line, where
2731 # behavior of running a script from the system command line, where
2740 # Python inserts the script's directory into sys.path
2732 # Python inserts the script's directory into sys.path
2741 dname = os.path.dirname(os.path.abspath(fname))
2733 dname = os.path.dirname(os.path.abspath(fname))
2742 add_dname = False
2734 add_dname = False
2743 if dname not in sys.path:
2735 if dname not in sys.path:
2744 sys.path.insert(0,dname)
2736 sys.path.insert(0,dname)
2745 add_dname = True
2737 add_dname = True
2746
2738
2747 try:
2739 try:
2748 xfile = open(fname)
2740 xfile = open(fname)
2749 except:
2741 except:
2750 print >> Term.cerr, \
2742 print >> Term.cerr, \
2751 'Could not open file <%s> for safe execution.' % fname
2743 'Could not open file <%s> for safe execution.' % fname
2752 syspath_cleanup()
2744 syspath_cleanup()
2753 return None
2745 return None
2754
2746
2755 kw.setdefault('islog',0)
2747 kw.setdefault('islog',0)
2756 kw.setdefault('quiet',1)
2748 kw.setdefault('quiet',1)
2757 kw.setdefault('exit_ignore',0)
2749 kw.setdefault('exit_ignore',0)
2758
2750
2759 first = xfile.readline()
2751 first = xfile.readline()
2760 loghead = str(self.loghead_tpl).split('\n',1)[0].strip()
2752 loghead = str(self.loghead_tpl).split('\n',1)[0].strip()
2761 xfile.close()
2753 xfile.close()
2762 # line by line execution
2754 # line by line execution
2763 if first.startswith(loghead) or kw['islog']:
2755 if first.startswith(loghead) or kw['islog']:
2764 print 'Loading log file <%s> one line at a time...' % fname
2756 print 'Loading log file <%s> one line at a time...' % fname
2765 if kw['quiet']:
2757 if kw['quiet']:
2766 stdout_save = sys.stdout
2758 stdout_save = sys.stdout
2767 sys.stdout = StringIO.StringIO()
2759 sys.stdout = StringIO.StringIO()
2768 try:
2760 try:
2769 globs,locs = where[0:2]
2761 globs,locs = where[0:2]
2770 except:
2762 except:
2771 try:
2763 try:
2772 globs = locs = where[0]
2764 globs = locs = where[0]
2773 except:
2765 except:
2774 globs = locs = globals()
2766 globs = locs = globals()
2775 badblocks = []
2767 badblocks = []
2776
2768
2777 # we also need to identify indented blocks of code when replaying
2769 # we also need to identify indented blocks of code when replaying
2778 # logs and put them together before passing them to an exec
2770 # logs and put them together before passing them to an exec
2779 # statement. This takes a bit of regexp and look-ahead work in the
2771 # statement. This takes a bit of regexp and look-ahead work in the
2780 # file. It's easiest if we swallow the whole thing in memory
2772 # file. It's easiest if we swallow the whole thing in memory
2781 # first, and manually walk through the lines list moving the
2773 # first, and manually walk through the lines list moving the
2782 # counter ourselves.
2774 # counter ourselves.
2783 indent_re = re.compile('\s+\S')
2775 indent_re = re.compile('\s+\S')
2784 xfile = open(fname)
2776 xfile = open(fname)
2785 filelines = xfile.readlines()
2777 filelines = xfile.readlines()
2786 xfile.close()
2778 xfile.close()
2787 nlines = len(filelines)
2779 nlines = len(filelines)
2788 lnum = 0
2780 lnum = 0
2789 while lnum < nlines:
2781 while lnum < nlines:
2790 line = filelines[lnum]
2782 line = filelines[lnum]
2791 lnum += 1
2783 lnum += 1
2792 # don't re-insert logger status info into cache
2784 # don't re-insert logger status info into cache
2793 if line.startswith('#log#'):
2785 if line.startswith('#log#'):
2794 continue
2786 continue
2795 else:
2787 else:
2796 # build a block of code (maybe a single line) for execution
2788 # build a block of code (maybe a single line) for execution
2797 block = line
2789 block = line
2798 try:
2790 try:
2799 next = filelines[lnum] # lnum has already incremented
2791 next = filelines[lnum] # lnum has already incremented
2800 except:
2792 except:
2801 next = None
2793 next = None
2802 while next and indent_re.match(next):
2794 while next and indent_re.match(next):
2803 block += next
2795 block += next
2804 lnum += 1
2796 lnum += 1
2805 try:
2797 try:
2806 next = filelines[lnum]
2798 next = filelines[lnum]
2807 except:
2799 except:
2808 next = None
2800 next = None
2809 # now execute the block of one or more lines
2801 # now execute the block of one or more lines
2810 try:
2802 try:
2811 exec block in globs,locs
2803 exec block in globs,locs
2812 except SystemExit:
2804 except SystemExit:
2813 pass
2805 pass
2814 except:
2806 except:
2815 badblocks.append(block.rstrip())
2807 badblocks.append(block.rstrip())
2816 if kw['quiet']: # restore stdout
2808 if kw['quiet']: # restore stdout
2817 sys.stdout.close()
2809 sys.stdout.close()
2818 sys.stdout = stdout_save
2810 sys.stdout = stdout_save
2819 print 'Finished replaying log file <%s>' % fname
2811 print 'Finished replaying log file <%s>' % fname
2820 if badblocks:
2812 if badblocks:
2821 print >> sys.stderr, ('\nThe following lines/blocks in file '
2813 print >> sys.stderr, ('\nThe following lines/blocks in file '
2822 '<%s> reported errors:' % fname)
2814 '<%s> reported errors:' % fname)
2823
2815
2824 for badline in badblocks:
2816 for badline in badblocks:
2825 print >> sys.stderr, badline
2817 print >> sys.stderr, badline
2826 else: # regular file execution
2818 else: # regular file execution
2827 try:
2819 try:
2828 if sys.platform == 'win32' and sys.version_info < (2,5,1):
2820 if sys.platform == 'win32' and sys.version_info < (2,5,1):
2829 # Work around a bug in Python for Windows. The bug was
2821 # Work around a bug in Python for Windows. The bug was
2830 # fixed in in Python 2.5 r54159 and 54158, but that's still
2822 # fixed in in Python 2.5 r54159 and 54158, but that's still
2831 # SVN Python as of March/07. For details, see:
2823 # SVN Python as of March/07. For details, see:
2832 # http://projects.scipy.org/ipython/ipython/ticket/123
2824 # http://projects.scipy.org/ipython/ipython/ticket/123
2833 try:
2825 try:
2834 globs,locs = where[0:2]
2826 globs,locs = where[0:2]
2835 except:
2827 except:
2836 try:
2828 try:
2837 globs = locs = where[0]
2829 globs = locs = where[0]
2838 except:
2830 except:
2839 globs = locs = globals()
2831 globs = locs = globals()
2840 exec file(fname) in globs,locs
2832 exec file(fname) in globs,locs
2841 else:
2833 else:
2842 execfile(fname,*where)
2834 execfile(fname,*where)
2843 except SyntaxError:
2835 except SyntaxError:
2844 self.showsyntaxerror()
2836 self.showsyntaxerror()
2845 warn('Failure executing file: <%s>' % fname)
2837 warn('Failure executing file: <%s>' % fname)
2846 except SystemExit,status:
2838 except SystemExit,status:
2847 # Code that correctly sets the exit status flag to success (0)
2839 # Code that correctly sets the exit status flag to success (0)
2848 # shouldn't be bothered with a traceback. Note that a plain
2840 # shouldn't be bothered with a traceback. Note that a plain
2849 # sys.exit() does NOT set the message to 0 (it's empty) so that
2841 # sys.exit() does NOT set the message to 0 (it's empty) so that
2850 # will still get a traceback. Note that the structure of the
2842 # will still get a traceback. Note that the structure of the
2851 # SystemExit exception changed between Python 2.4 and 2.5, so
2843 # SystemExit exception changed between Python 2.4 and 2.5, so
2852 # the checks must be done in a version-dependent way.
2844 # the checks must be done in a version-dependent way.
2853 show = False
2845 show = False
2854
2846
2855 if sys.version_info[:2] > (2,5):
2847 if sys.version_info[:2] > (2,5):
2856 if status.message!=0 and not kw['exit_ignore']:
2848 if status.message!=0 and not kw['exit_ignore']:
2857 show = True
2849 show = True
2858 else:
2850 else:
2859 if status.code and not kw['exit_ignore']:
2851 if status.code and not kw['exit_ignore']:
2860 show = True
2852 show = True
2861 if show:
2853 if show:
2862 self.showtraceback()
2854 self.showtraceback()
2863 warn('Failure executing file: <%s>' % fname)
2855 warn('Failure executing file: <%s>' % fname)
2864 except:
2856 except:
2865 self.showtraceback()
2857 self.showtraceback()
2866 warn('Failure executing file: <%s>' % fname)
2858 warn('Failure executing file: <%s>' % fname)
2867
2859
2868 syspath_cleanup()
2860 syspath_cleanup()
2869
2861
2870 #************************* end of file <iplib.py> *****************************
2862 #************************* end of file <iplib.py> *****************************
@@ -1,588 +1,584 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Classes for handling input/output prompts.
2 """Classes for handling input/output prompts.
3
3
4 Authors
4 Authors
5 -------
5 -------
6 - Fernando Perez <Fernando.Perez@berkeley.edu>
6 - Fernando Perez <Fernando.Perez@berkeley.edu>
7 """
7 """
8
8
9 __docformat__ = "restructuredtext en"
9 __docformat__ = "restructuredtext en"
10
10
11 #-------------------------------------------------------------------------------
11 #-------------------------------------------------------------------------------
12 # Copyright (C) 2008 The IPython Development Team
12 # Copyright (C) 2008 The IPython Development Team
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 # Imports
19 # Imports
20 #-------------------------------------------------------------------------------
20 #-------------------------------------------------------------------------------
21
21
22 # Required modules
22 # Required modules
23 import __builtin__
23 import __builtin__
24 import os
25 import socket
24 import socket
26 import sys
25 import sys
27 import time
28
26
29 # IPython's own
27 # IPython's own
30 from IPython.external.Itpl import ItplNS
28 from IPython.external.Itpl import ItplNS
31 from macro import Macro
32
29
33 from IPython import ColorANSI
30 from IPython.utils import coloransi
34 from IPython import Release
31 from IPython import Release
35 from IPython.ipapi import TryNext
32 from IPython.ipapi import TryNext
36 from IPython.ipstruct import Struct
37 from IPython.genutils import *
33 from IPython.genutils import *
38
34
39 #****************************************************************************
35 #****************************************************************************
40 #Color schemes for Prompts.
36 #Color schemes for Prompts.
41
37
42 PromptColors = ColorANSI.ColorSchemeTable()
38 PromptColors = coloransi.ColorSchemeTable()
43 InputColors = ColorANSI.InputTermColors # just a shorthand
39 InputColors = coloransi.InputTermColors # just a shorthand
44 Colors = ColorANSI.TermColors # just a shorthand
40 Colors = coloransi.TermColors # just a shorthand
45
41
46
42
47 __PColNoColor = ColorANSI.ColorScheme(
43 __PColNoColor = coloransi.ColorScheme(
48 'NoColor',
44 'NoColor',
49 in_prompt = InputColors.NoColor, # Input prompt
45 in_prompt = InputColors.NoColor, # Input prompt
50 in_number = InputColors.NoColor, # Input prompt number
46 in_number = InputColors.NoColor, # Input prompt number
51 in_prompt2 = InputColors.NoColor, # Continuation prompt
47 in_prompt2 = InputColors.NoColor, # Continuation prompt
52 in_normal = InputColors.NoColor, # color off (usu. Colors.Normal)
48 in_normal = InputColors.NoColor, # color off (usu. Colors.Normal)
53
49
54 out_prompt = Colors.NoColor, # Output prompt
50 out_prompt = Colors.NoColor, # Output prompt
55 out_number = Colors.NoColor, # Output prompt number
51 out_number = Colors.NoColor, # Output prompt number
56
52
57 normal = Colors.NoColor # color off (usu. Colors.Normal)
53 normal = Colors.NoColor # color off (usu. Colors.Normal)
58 )
54 )
59
55
60 PromptColors.add_scheme(__PColNoColor)
56 PromptColors.add_scheme(__PColNoColor)
61
57
62 # make some schemes as instances so we can copy them for modification easily:
58 # make some schemes as instances so we can copy them for modification easily:
63 __PColLinux = __PColNoColor.copy('Linux')
59 __PColLinux = __PColNoColor.copy('Linux')
64 # Don't forget to enter it into the table!
60 # Don't forget to enter it into the table!
65 PromptColors.add_scheme(__PColLinux)
61 PromptColors.add_scheme(__PColLinux)
66 __PColLightBG = __PColLinux.copy('LightBG')
62 __PColLightBG = __PColLinux.copy('LightBG')
67 PromptColors.add_scheme(__PColLightBG)
63 PromptColors.add_scheme(__PColLightBG)
68
64
69 del Colors,InputColors
65 del Colors,InputColors
70
66
71 #-----------------------------------------------------------------------------
67 #-----------------------------------------------------------------------------
72 def multiple_replace(dict, text):
68 def multiple_replace(dict, text):
73 """ Replace in 'text' all occurences of any key in the given
69 """ Replace in 'text' all occurences of any key in the given
74 dictionary by its corresponding value. Returns the new string."""
70 dictionary by its corresponding value. Returns the new string."""
75
71
76 # Function by Xavier Defrang, originally found at:
72 # Function by Xavier Defrang, originally found at:
77 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
73 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
78
74
79 # Create a regular expression from the dictionary keys
75 # Create a regular expression from the dictionary keys
80 regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
76 regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
81 # For each match, look-up corresponding value in dictionary
77 # For each match, look-up corresponding value in dictionary
82 return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
78 return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
83
79
84 #-----------------------------------------------------------------------------
80 #-----------------------------------------------------------------------------
85 # Special characters that can be used in prompt templates, mainly bash-like
81 # Special characters that can be used in prompt templates, mainly bash-like
86
82
87 # If $HOME isn't defined (Windows), make it an absurd string so that it can
83 # If $HOME isn't defined (Windows), make it an absurd string so that it can
88 # never be expanded out into '~'. Basically anything which can never be a
84 # never be expanded out into '~'. Basically anything which can never be a
89 # reasonable directory name will do, we just want the $HOME -> '~' operation
85 # reasonable directory name will do, we just want the $HOME -> '~' operation
90 # to become a no-op. We pre-compute $HOME here so it's not done on every
86 # to become a no-op. We pre-compute $HOME here so it's not done on every
91 # prompt call.
87 # prompt call.
92
88
93 # FIXME:
89 # FIXME:
94
90
95 # - This should be turned into a class which does proper namespace management,
91 # - This should be turned into a class which does proper namespace management,
96 # since the prompt specials need to be evaluated in a certain namespace.
92 # since the prompt specials need to be evaluated in a certain namespace.
97 # Currently it's just globals, which need to be managed manually by code
93 # Currently it's just globals, which need to be managed manually by code
98 # below.
94 # below.
99
95
100 # - I also need to split up the color schemes from the prompt specials
96 # - I also need to split up the color schemes from the prompt specials
101 # somehow. I don't have a clean design for that quite yet.
97 # somehow. I don't have a clean design for that quite yet.
102
98
103 HOME = os.environ.get("HOME","//////:::::ZZZZZ,,,~~~")
99 HOME = os.environ.get("HOME","//////:::::ZZZZZ,,,~~~")
104
100
105 # We precompute a few more strings here for the prompt_specials, which are
101 # We precompute a few more strings here for the prompt_specials, which are
106 # fixed once ipython starts. This reduces the runtime overhead of computing
102 # fixed once ipython starts. This reduces the runtime overhead of computing
107 # prompt strings.
103 # prompt strings.
108 USER = os.environ.get("USER")
104 USER = os.environ.get("USER")
109 HOSTNAME = socket.gethostname()
105 HOSTNAME = socket.gethostname()
110 HOSTNAME_SHORT = HOSTNAME.split(".")[0]
106 HOSTNAME_SHORT = HOSTNAME.split(".")[0]
111 ROOT_SYMBOL = "$#"[os.name=='nt' or os.getuid()==0]
107 ROOT_SYMBOL = "$#"[os.name=='nt' or os.getuid()==0]
112
108
113 prompt_specials_color = {
109 prompt_specials_color = {
114 # Prompt/history count
110 # Prompt/history count
115 '%n' : '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
111 '%n' : '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
116 r'\#': '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
112 r'\#': '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
117 # Just the prompt counter number, WITHOUT any coloring wrappers, so users
113 # Just the prompt counter number, WITHOUT any coloring wrappers, so users
118 # can get numbers displayed in whatever color they want.
114 # can get numbers displayed in whatever color they want.
119 r'\N': '${self.cache.prompt_count}',
115 r'\N': '${self.cache.prompt_count}',
120 # Prompt/history count, with the actual digits replaced by dots. Used
116 # Prompt/history count, with the actual digits replaced by dots. Used
121 # mainly in continuation prompts (prompt_in2)
117 # mainly in continuation prompts (prompt_in2)
122 r'\D': '${"."*len(str(self.cache.prompt_count))}',
118 r'\D': '${"."*len(str(self.cache.prompt_count))}',
123 # Current working directory
119 # Current working directory
124 r'\w': '${os.getcwd()}',
120 r'\w': '${os.getcwd()}',
125 # Current time
121 # Current time
126 r'\t' : '${time.strftime("%H:%M:%S")}',
122 r'\t' : '${time.strftime("%H:%M:%S")}',
127 # Basename of current working directory.
123 # Basename of current working directory.
128 # (use os.sep to make this portable across OSes)
124 # (use os.sep to make this portable across OSes)
129 r'\W' : '${os.getcwd().split("%s")[-1]}' % os.sep,
125 r'\W' : '${os.getcwd().split("%s")[-1]}' % os.sep,
130 # These X<N> are an extension to the normal bash prompts. They return
126 # These X<N> are an extension to the normal bash prompts. They return
131 # N terms of the path, after replacing $HOME with '~'
127 # N terms of the path, after replacing $HOME with '~'
132 r'\X0': '${os.getcwd().replace("%s","~")}' % HOME,
128 r'\X0': '${os.getcwd().replace("%s","~")}' % HOME,
133 r'\X1': '${self.cwd_filt(1)}',
129 r'\X1': '${self.cwd_filt(1)}',
134 r'\X2': '${self.cwd_filt(2)}',
130 r'\X2': '${self.cwd_filt(2)}',
135 r'\X3': '${self.cwd_filt(3)}',
131 r'\X3': '${self.cwd_filt(3)}',
136 r'\X4': '${self.cwd_filt(4)}',
132 r'\X4': '${self.cwd_filt(4)}',
137 r'\X5': '${self.cwd_filt(5)}',
133 r'\X5': '${self.cwd_filt(5)}',
138 # Y<N> are similar to X<N>, but they show '~' if it's the directory
134 # Y<N> are similar to X<N>, but they show '~' if it's the directory
139 # N+1 in the list. Somewhat like %cN in tcsh.
135 # N+1 in the list. Somewhat like %cN in tcsh.
140 r'\Y0': '${self.cwd_filt2(0)}',
136 r'\Y0': '${self.cwd_filt2(0)}',
141 r'\Y1': '${self.cwd_filt2(1)}',
137 r'\Y1': '${self.cwd_filt2(1)}',
142 r'\Y2': '${self.cwd_filt2(2)}',
138 r'\Y2': '${self.cwd_filt2(2)}',
143 r'\Y3': '${self.cwd_filt2(3)}',
139 r'\Y3': '${self.cwd_filt2(3)}',
144 r'\Y4': '${self.cwd_filt2(4)}',
140 r'\Y4': '${self.cwd_filt2(4)}',
145 r'\Y5': '${self.cwd_filt2(5)}',
141 r'\Y5': '${self.cwd_filt2(5)}',
146 # Hostname up to first .
142 # Hostname up to first .
147 r'\h': HOSTNAME_SHORT,
143 r'\h': HOSTNAME_SHORT,
148 # Full hostname
144 # Full hostname
149 r'\H': HOSTNAME,
145 r'\H': HOSTNAME,
150 # Username of current user
146 # Username of current user
151 r'\u': USER,
147 r'\u': USER,
152 # Escaped '\'
148 # Escaped '\'
153 '\\\\': '\\',
149 '\\\\': '\\',
154 # Newline
150 # Newline
155 r'\n': '\n',
151 r'\n': '\n',
156 # Carriage return
152 # Carriage return
157 r'\r': '\r',
153 r'\r': '\r',
158 # Release version
154 # Release version
159 r'\v': Release.version,
155 r'\v': Release.version,
160 # Root symbol ($ or #)
156 # Root symbol ($ or #)
161 r'\$': ROOT_SYMBOL,
157 r'\$': ROOT_SYMBOL,
162 }
158 }
163
159
164 # A copy of the prompt_specials dictionary but with all color escapes removed,
160 # A copy of the prompt_specials dictionary but with all color escapes removed,
165 # so we can correctly compute the prompt length for the auto_rewrite method.
161 # so we can correctly compute the prompt length for the auto_rewrite method.
166 prompt_specials_nocolor = prompt_specials_color.copy()
162 prompt_specials_nocolor = prompt_specials_color.copy()
167 prompt_specials_nocolor['%n'] = '${self.cache.prompt_count}'
163 prompt_specials_nocolor['%n'] = '${self.cache.prompt_count}'
168 prompt_specials_nocolor[r'\#'] = '${self.cache.prompt_count}'
164 prompt_specials_nocolor[r'\#'] = '${self.cache.prompt_count}'
169
165
170 # Add in all the InputTermColors color escapes as valid prompt characters.
166 # Add in all the InputTermColors color escapes as valid prompt characters.
171 # They all get added as \\C_COLORNAME, so that we don't have any conflicts
167 # They all get added as \\C_COLORNAME, so that we don't have any conflicts
172 # with a color name which may begin with a letter used by any other of the
168 # with a color name which may begin with a letter used by any other of the
173 # allowed specials. This of course means that \\C will never be allowed for
169 # allowed specials. This of course means that \\C will never be allowed for
174 # anything else.
170 # anything else.
175 input_colors = ColorANSI.InputTermColors
171 input_colors = coloransi.InputTermColors
176 for _color in dir(input_colors):
172 for _color in dir(input_colors):
177 if _color[0] != '_':
173 if _color[0] != '_':
178 c_name = r'\C_'+_color
174 c_name = r'\C_'+_color
179 prompt_specials_color[c_name] = getattr(input_colors,_color)
175 prompt_specials_color[c_name] = getattr(input_colors,_color)
180 prompt_specials_nocolor[c_name] = ''
176 prompt_specials_nocolor[c_name] = ''
181
177
182 # we default to no color for safety. Note that prompt_specials is a global
178 # we default to no color for safety. Note that prompt_specials is a global
183 # variable used by all prompt objects.
179 # variable used by all prompt objects.
184 prompt_specials = prompt_specials_nocolor
180 prompt_specials = prompt_specials_nocolor
185
181
186 #-----------------------------------------------------------------------------
182 #-----------------------------------------------------------------------------
187 def str_safe(arg):
183 def str_safe(arg):
188 """Convert to a string, without ever raising an exception.
184 """Convert to a string, without ever raising an exception.
189
185
190 If str(arg) fails, <ERROR: ... > is returned, where ... is the exception
186 If str(arg) fails, <ERROR: ... > is returned, where ... is the exception
191 error message."""
187 error message."""
192
188
193 try:
189 try:
194 out = str(arg)
190 out = str(arg)
195 except UnicodeError:
191 except UnicodeError:
196 try:
192 try:
197 out = arg.encode('utf_8','replace')
193 out = arg.encode('utf_8','replace')
198 except Exception,msg:
194 except Exception,msg:
199 # let's keep this little duplication here, so that the most common
195 # let's keep this little duplication here, so that the most common
200 # case doesn't suffer from a double try wrapping.
196 # case doesn't suffer from a double try wrapping.
201 out = '<ERROR: %s>' % msg
197 out = '<ERROR: %s>' % msg
202 except Exception,msg:
198 except Exception,msg:
203 out = '<ERROR: %s>' % msg
199 out = '<ERROR: %s>' % msg
204 return out
200 return out
205
201
206 class BasePrompt(object):
202 class BasePrompt(object):
207 """Interactive prompt similar to Mathematica's."""
203 """Interactive prompt similar to Mathematica's."""
208
204
209 def _get_p_template(self):
205 def _get_p_template(self):
210 return self._p_template
206 return self._p_template
211
207
212 def _set_p_template(self,val):
208 def _set_p_template(self,val):
213 self._p_template = val
209 self._p_template = val
214 self.set_p_str()
210 self.set_p_str()
215
211
216 p_template = property(_get_p_template,_set_p_template,
212 p_template = property(_get_p_template,_set_p_template,
217 doc='Template for prompt string creation')
213 doc='Template for prompt string creation')
218
214
219 def __init__(self,cache,sep,prompt,pad_left=False):
215 def __init__(self,cache,sep,prompt,pad_left=False):
220
216
221 # Hack: we access information about the primary prompt through the
217 # Hack: we access information about the primary prompt through the
222 # cache argument. We need this, because we want the secondary prompt
218 # cache argument. We need this, because we want the secondary prompt
223 # to be aligned with the primary one. Color table info is also shared
219 # to be aligned with the primary one. Color table info is also shared
224 # by all prompt classes through the cache. Nice OO spaghetti code!
220 # by all prompt classes through the cache. Nice OO spaghetti code!
225 self.cache = cache
221 self.cache = cache
226 self.sep = sep
222 self.sep = sep
227
223
228 # regexp to count the number of spaces at the end of a prompt
224 # regexp to count the number of spaces at the end of a prompt
229 # expression, useful for prompt auto-rewriting
225 # expression, useful for prompt auto-rewriting
230 self.rspace = re.compile(r'(\s*)$')
226 self.rspace = re.compile(r'(\s*)$')
231 # Flag to left-pad prompt strings to match the length of the primary
227 # Flag to left-pad prompt strings to match the length of the primary
232 # prompt
228 # prompt
233 self.pad_left = pad_left
229 self.pad_left = pad_left
234
230
235 # Set template to create each actual prompt (where numbers change).
231 # Set template to create each actual prompt (where numbers change).
236 # Use a property
232 # Use a property
237 self.p_template = prompt
233 self.p_template = prompt
238 self.set_p_str()
234 self.set_p_str()
239
235
240 def set_p_str(self):
236 def set_p_str(self):
241 """ Set the interpolating prompt strings.
237 """ Set the interpolating prompt strings.
242
238
243 This must be called every time the color settings change, because the
239 This must be called every time the color settings change, because the
244 prompt_specials global may have changed."""
240 prompt_specials global may have changed."""
245
241
246 import os,time # needed in locals for prompt string handling
242 import os,time # needed in locals for prompt string handling
247 loc = locals()
243 loc = locals()
248 self.p_str = ItplNS('%s%s%s' %
244 self.p_str = ItplNS('%s%s%s' %
249 ('${self.sep}${self.col_p}',
245 ('${self.sep}${self.col_p}',
250 multiple_replace(prompt_specials, self.p_template),
246 multiple_replace(prompt_specials, self.p_template),
251 '${self.col_norm}'),self.cache.user_ns,loc)
247 '${self.col_norm}'),self.cache.user_ns,loc)
252
248
253 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
249 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
254 self.p_template),
250 self.p_template),
255 self.cache.user_ns,loc)
251 self.cache.user_ns,loc)
256
252
257 def write(self,msg): # dbg
253 def write(self,msg): # dbg
258 sys.stdout.write(msg)
254 sys.stdout.write(msg)
259 return ''
255 return ''
260
256
261 def __str__(self):
257 def __str__(self):
262 """Return a string form of the prompt.
258 """Return a string form of the prompt.
263
259
264 This for is useful for continuation and output prompts, since it is
260 This for is useful for continuation and output prompts, since it is
265 left-padded to match lengths with the primary one (if the
261 left-padded to match lengths with the primary one (if the
266 self.pad_left attribute is set)."""
262 self.pad_left attribute is set)."""
267
263
268 out_str = str_safe(self.p_str)
264 out_str = str_safe(self.p_str)
269 if self.pad_left:
265 if self.pad_left:
270 # We must find the amount of padding required to match lengths,
266 # We must find the amount of padding required to match lengths,
271 # taking the color escapes (which are invisible on-screen) into
267 # taking the color escapes (which are invisible on-screen) into
272 # account.
268 # account.
273 esc_pad = len(out_str) - len(str_safe(self.p_str_nocolor))
269 esc_pad = len(out_str) - len(str_safe(self.p_str_nocolor))
274 format = '%%%ss' % (len(str(self.cache.last_prompt))+esc_pad)
270 format = '%%%ss' % (len(str(self.cache.last_prompt))+esc_pad)
275 return format % out_str
271 return format % out_str
276 else:
272 else:
277 return out_str
273 return out_str
278
274
279 # these path filters are put in as methods so that we can control the
275 # these path filters are put in as methods so that we can control the
280 # namespace where the prompt strings get evaluated
276 # namespace where the prompt strings get evaluated
281 def cwd_filt(self,depth):
277 def cwd_filt(self,depth):
282 """Return the last depth elements of the current working directory.
278 """Return the last depth elements of the current working directory.
283
279
284 $HOME is always replaced with '~'.
280 $HOME is always replaced with '~'.
285 If depth==0, the full path is returned."""
281 If depth==0, the full path is returned."""
286
282
287 cwd = os.getcwd().replace(HOME,"~")
283 cwd = os.getcwd().replace(HOME,"~")
288 out = os.sep.join(cwd.split(os.sep)[-depth:])
284 out = os.sep.join(cwd.split(os.sep)[-depth:])
289 if out:
285 if out:
290 return out
286 return out
291 else:
287 else:
292 return os.sep
288 return os.sep
293
289
294 def cwd_filt2(self,depth):
290 def cwd_filt2(self,depth):
295 """Return the last depth elements of the current working directory.
291 """Return the last depth elements of the current working directory.
296
292
297 $HOME is always replaced with '~'.
293 $HOME is always replaced with '~'.
298 If depth==0, the full path is returned."""
294 If depth==0, the full path is returned."""
299
295
300 cwd = os.getcwd().replace(HOME,"~").split(os.sep)
296 cwd = os.getcwd().replace(HOME,"~").split(os.sep)
301 if '~' in cwd and len(cwd) == depth+1:
297 if '~' in cwd and len(cwd) == depth+1:
302 depth += 1
298 depth += 1
303 out = os.sep.join(cwd[-depth:])
299 out = os.sep.join(cwd[-depth:])
304 if out:
300 if out:
305 return out
301 return out
306 else:
302 else:
307 return os.sep
303 return os.sep
308
304
309 class Prompt1(BasePrompt):
305 class Prompt1(BasePrompt):
310 """Input interactive prompt similar to Mathematica's."""
306 """Input interactive prompt similar to Mathematica's."""
311
307
312 def __init__(self,cache,sep='\n',prompt='In [\\#]: ',pad_left=True):
308 def __init__(self,cache,sep='\n',prompt='In [\\#]: ',pad_left=True):
313 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
309 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
314
310
315 def set_colors(self):
311 def set_colors(self):
316 self.set_p_str()
312 self.set_p_str()
317 Colors = self.cache.color_table.active_colors # shorthand
313 Colors = self.cache.color_table.active_colors # shorthand
318 self.col_p = Colors.in_prompt
314 self.col_p = Colors.in_prompt
319 self.col_num = Colors.in_number
315 self.col_num = Colors.in_number
320 self.col_norm = Colors.in_normal
316 self.col_norm = Colors.in_normal
321 # We need a non-input version of these escapes for the '--->'
317 # We need a non-input version of these escapes for the '--->'
322 # auto-call prompts used in the auto_rewrite() method.
318 # auto-call prompts used in the auto_rewrite() method.
323 self.col_p_ni = self.col_p.replace('\001','').replace('\002','')
319 self.col_p_ni = self.col_p.replace('\001','').replace('\002','')
324 self.col_norm_ni = Colors.normal
320 self.col_norm_ni = Colors.normal
325
321
326 def __str__(self):
322 def __str__(self):
327 self.cache.prompt_count += 1
323 self.cache.prompt_count += 1
328 self.cache.last_prompt = str_safe(self.p_str_nocolor).split('\n')[-1]
324 self.cache.last_prompt = str_safe(self.p_str_nocolor).split('\n')[-1]
329 return str_safe(self.p_str)
325 return str_safe(self.p_str)
330
326
331 def auto_rewrite(self):
327 def auto_rewrite(self):
332 """Print a string of the form '--->' which lines up with the previous
328 """Print a string of the form '--->' which lines up with the previous
333 input string. Useful for systems which re-write the user input when
329 input string. Useful for systems which re-write the user input when
334 handling automatically special syntaxes."""
330 handling automatically special syntaxes."""
335
331
336 curr = str(self.cache.last_prompt)
332 curr = str(self.cache.last_prompt)
337 nrspaces = len(self.rspace.search(curr).group())
333 nrspaces = len(self.rspace.search(curr).group())
338 return '%s%s>%s%s' % (self.col_p_ni,'-'*(len(curr)-nrspaces-1),
334 return '%s%s>%s%s' % (self.col_p_ni,'-'*(len(curr)-nrspaces-1),
339 ' '*nrspaces,self.col_norm_ni)
335 ' '*nrspaces,self.col_norm_ni)
340
336
341 class PromptOut(BasePrompt):
337 class PromptOut(BasePrompt):
342 """Output interactive prompt similar to Mathematica's."""
338 """Output interactive prompt similar to Mathematica's."""
343
339
344 def __init__(self,cache,sep='',prompt='Out[\\#]: ',pad_left=True):
340 def __init__(self,cache,sep='',prompt='Out[\\#]: ',pad_left=True):
345 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
341 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
346 if not self.p_template:
342 if not self.p_template:
347 self.__str__ = lambda: ''
343 self.__str__ = lambda: ''
348
344
349 def set_colors(self):
345 def set_colors(self):
350 self.set_p_str()
346 self.set_p_str()
351 Colors = self.cache.color_table.active_colors # shorthand
347 Colors = self.cache.color_table.active_colors # shorthand
352 self.col_p = Colors.out_prompt
348 self.col_p = Colors.out_prompt
353 self.col_num = Colors.out_number
349 self.col_num = Colors.out_number
354 self.col_norm = Colors.normal
350 self.col_norm = Colors.normal
355
351
356 class Prompt2(BasePrompt):
352 class Prompt2(BasePrompt):
357 """Interactive continuation prompt."""
353 """Interactive continuation prompt."""
358
354
359 def __init__(self,cache,prompt=' .\\D.: ',pad_left=True):
355 def __init__(self,cache,prompt=' .\\D.: ',pad_left=True):
360 self.cache = cache
356 self.cache = cache
361 self.p_template = prompt
357 self.p_template = prompt
362 self.pad_left = pad_left
358 self.pad_left = pad_left
363 self.set_p_str()
359 self.set_p_str()
364
360
365 def set_p_str(self):
361 def set_p_str(self):
366 import os,time # needed in locals for prompt string handling
362 import os,time # needed in locals for prompt string handling
367 loc = locals()
363 loc = locals()
368 self.p_str = ItplNS('%s%s%s' %
364 self.p_str = ItplNS('%s%s%s' %
369 ('${self.col_p2}',
365 ('${self.col_p2}',
370 multiple_replace(prompt_specials, self.p_template),
366 multiple_replace(prompt_specials, self.p_template),
371 '$self.col_norm'),
367 '$self.col_norm'),
372 self.cache.user_ns,loc)
368 self.cache.user_ns,loc)
373 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
369 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
374 self.p_template),
370 self.p_template),
375 self.cache.user_ns,loc)
371 self.cache.user_ns,loc)
376
372
377 def set_colors(self):
373 def set_colors(self):
378 self.set_p_str()
374 self.set_p_str()
379 Colors = self.cache.color_table.active_colors
375 Colors = self.cache.color_table.active_colors
380 self.col_p2 = Colors.in_prompt2
376 self.col_p2 = Colors.in_prompt2
381 self.col_norm = Colors.in_normal
377 self.col_norm = Colors.in_normal
382 # FIXME (2004-06-16) HACK: prevent crashes for users who haven't
378 # FIXME (2004-06-16) HACK: prevent crashes for users who haven't
383 # updated their prompt_in2 definitions. Remove eventually.
379 # updated their prompt_in2 definitions. Remove eventually.
384 self.col_p = Colors.out_prompt
380 self.col_p = Colors.out_prompt
385 self.col_num = Colors.out_number
381 self.col_num = Colors.out_number
386
382
387
383
388 #-----------------------------------------------------------------------------
384 #-----------------------------------------------------------------------------
389 class CachedOutput:
385 class CachedOutput:
390 """Class for printing output from calculations while keeping a cache of
386 """Class for printing output from calculations while keeping a cache of
391 reults. It dynamically creates global variables prefixed with _ which
387 reults. It dynamically creates global variables prefixed with _ which
392 contain these results.
388 contain these results.
393
389
394 Meant to be used as a sys.displayhook replacement, providing numbered
390 Meant to be used as a sys.displayhook replacement, providing numbered
395 prompts and cache services.
391 prompts and cache services.
396
392
397 Initialize with initial and final values for cache counter (this defines
393 Initialize with initial and final values for cache counter (this defines
398 the maximum size of the cache."""
394 the maximum size of the cache."""
399
395
400 def __init__(self,shell,cache_size,Pprint,
396 def __init__(self,shell,cache_size,Pprint,
401 colors='NoColor',input_sep='\n',
397 colors='NoColor',input_sep='\n',
402 output_sep='\n',output_sep2='',
398 output_sep='\n',output_sep2='',
403 ps1 = None, ps2 = None,ps_out = None,pad_left=True):
399 ps1 = None, ps2 = None,ps_out = None,pad_left=True):
404
400
405 cache_size_min = 3
401 cache_size_min = 3
406 if cache_size <= 0:
402 if cache_size <= 0:
407 self.do_full_cache = 0
403 self.do_full_cache = 0
408 cache_size = 0
404 cache_size = 0
409 elif cache_size < cache_size_min:
405 elif cache_size < cache_size_min:
410 self.do_full_cache = 0
406 self.do_full_cache = 0
411 cache_size = 0
407 cache_size = 0
412 warn('caching was disabled (min value for cache size is %s).' %
408 warn('caching was disabled (min value for cache size is %s).' %
413 cache_size_min,level=3)
409 cache_size_min,level=3)
414 else:
410 else:
415 self.do_full_cache = 1
411 self.do_full_cache = 1
416
412
417 self.cache_size = cache_size
413 self.cache_size = cache_size
418 self.input_sep = input_sep
414 self.input_sep = input_sep
419
415
420 # we need a reference to the user-level namespace
416 # we need a reference to the user-level namespace
421 self.shell = shell
417 self.shell = shell
422 self.user_ns = shell.user_ns
418 self.user_ns = shell.user_ns
423 # and to the user's input
419 # and to the user's input
424 self.input_hist = shell.history.input_cache
420 self.input_hist = shell.history.input_cache
425
421
426 # Set input prompt strings and colors
422 # Set input prompt strings and colors
427 if cache_size == 0:
423 if cache_size == 0:
428 if ps1.find('%n') > -1 or ps1.find(r'\#') > -1 \
424 if ps1.find('%n') > -1 or ps1.find(r'\#') > -1 \
429 or ps1.find(r'\N') > -1:
425 or ps1.find(r'\N') > -1:
430 ps1 = '>>> '
426 ps1 = '>>> '
431 if ps2.find('%n') > -1 or ps2.find(r'\#') > -1 \
427 if ps2.find('%n') > -1 or ps2.find(r'\#') > -1 \
432 or ps2.find(r'\N') > -1:
428 or ps2.find(r'\N') > -1:
433 ps2 = '... '
429 ps2 = '... '
434 self.ps1_str = self._set_prompt_str(ps1,'In [\\#]: ','>>> ')
430 self.ps1_str = self._set_prompt_str(ps1,'In [\\#]: ','>>> ')
435 self.ps2_str = self._set_prompt_str(ps2,' .\\D.: ','... ')
431 self.ps2_str = self._set_prompt_str(ps2,' .\\D.: ','... ')
436 self.ps_out_str = self._set_prompt_str(ps_out,'Out[\\#]: ','')
432 self.ps_out_str = self._set_prompt_str(ps_out,'Out[\\#]: ','')
437
433
438 self.color_table = PromptColors
434 self.color_table = PromptColors
439 self.prompt1 = Prompt1(self,sep=input_sep,prompt=self.ps1_str,
435 self.prompt1 = Prompt1(self,sep=input_sep,prompt=self.ps1_str,
440 pad_left=pad_left)
436 pad_left=pad_left)
441 self.prompt2 = Prompt2(self,prompt=self.ps2_str,pad_left=pad_left)
437 self.prompt2 = Prompt2(self,prompt=self.ps2_str,pad_left=pad_left)
442 self.prompt_out = PromptOut(self,sep='',prompt=self.ps_out_str,
438 self.prompt_out = PromptOut(self,sep='',prompt=self.ps_out_str,
443 pad_left=pad_left)
439 pad_left=pad_left)
444 self.set_colors(colors)
440 self.set_colors(colors)
445
441
446 # other more normal stuff
442 # other more normal stuff
447 # b/c each call to the In[] prompt raises it by 1, even the first.
443 # b/c each call to the In[] prompt raises it by 1, even the first.
448 self.prompt_count = 0
444 self.prompt_count = 0
449 # Store the last prompt string each time, we need it for aligning
445 # Store the last prompt string each time, we need it for aligning
450 # continuation and auto-rewrite prompts
446 # continuation and auto-rewrite prompts
451 self.last_prompt = ''
447 self.last_prompt = ''
452 self.Pprint = Pprint
448 self.Pprint = Pprint
453 self.output_sep = output_sep
449 self.output_sep = output_sep
454 self.output_sep2 = output_sep2
450 self.output_sep2 = output_sep2
455 self._,self.__,self.___ = '','',''
451 self._,self.__,self.___ = '','',''
456 self.pprint_types = map(type,[(),[],{}])
452 self.pprint_types = map(type,[(),[],{}])
457
453
458 # these are deliberately global:
454 # these are deliberately global:
459 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
455 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
460 self.user_ns.update(to_user_ns)
456 self.user_ns.update(to_user_ns)
461
457
462 def _set_prompt_str(self,p_str,cache_def,no_cache_def):
458 def _set_prompt_str(self,p_str,cache_def,no_cache_def):
463 if p_str is None:
459 if p_str is None:
464 if self.do_full_cache:
460 if self.do_full_cache:
465 return cache_def
461 return cache_def
466 else:
462 else:
467 return no_cache_def
463 return no_cache_def
468 else:
464 else:
469 return p_str
465 return p_str
470
466
471 def set_colors(self,colors):
467 def set_colors(self,colors):
472 """Set the active color scheme and configure colors for the three
468 """Set the active color scheme and configure colors for the three
473 prompt subsystems."""
469 prompt subsystems."""
474
470
475 # FIXME: the prompt_specials global should be gobbled inside this
471 # FIXME: the prompt_specials global should be gobbled inside this
476 # class instead. Do it when cleaning up the whole 3-prompt system.
472 # class instead. Do it when cleaning up the whole 3-prompt system.
477 global prompt_specials
473 global prompt_specials
478 if colors.lower()=='nocolor':
474 if colors.lower()=='nocolor':
479 prompt_specials = prompt_specials_nocolor
475 prompt_specials = prompt_specials_nocolor
480 else:
476 else:
481 prompt_specials = prompt_specials_color
477 prompt_specials = prompt_specials_color
482
478
483 self.color_table.set_active_scheme(colors)
479 self.color_table.set_active_scheme(colors)
484 self.prompt1.set_colors()
480 self.prompt1.set_colors()
485 self.prompt2.set_colors()
481 self.prompt2.set_colors()
486 self.prompt_out.set_colors()
482 self.prompt_out.set_colors()
487
483
488 def __call__(self,arg=None):
484 def __call__(self,arg=None):
489 """Printing with history cache management.
485 """Printing with history cache management.
490
486
491 This is invoked everytime the interpreter needs to print, and is
487 This is invoked everytime the interpreter needs to print, and is
492 activated by setting the variable sys.displayhook to it."""
488 activated by setting the variable sys.displayhook to it."""
493
489
494 # If something injected a '_' variable in __builtin__, delete
490 # If something injected a '_' variable in __builtin__, delete
495 # ipython's automatic one so we don't clobber that. gettext() in
491 # ipython's automatic one so we don't clobber that. gettext() in
496 # particular uses _, so we need to stay away from it.
492 # particular uses _, so we need to stay away from it.
497 if '_' in __builtin__.__dict__:
493 if '_' in __builtin__.__dict__:
498 try:
494 try:
499 del self.user_ns['_']
495 del self.user_ns['_']
500 except KeyError:
496 except KeyError:
501 pass
497 pass
502 if arg is not None:
498 if arg is not None:
503 cout_write = Term.cout.write # fast lookup
499 cout_write = Term.cout.write # fast lookup
504 # first handle the cache and counters
500 # first handle the cache and counters
505
501
506 # do not print output if input ends in ';'
502 # do not print output if input ends in ';'
507 if self.input_hist[self.prompt_count].endswith(';\n'):
503 if self.input_hist[self.prompt_count].endswith(';\n'):
508 return
504 return
509 # don't use print, puts an extra space
505 # don't use print, puts an extra space
510 cout_write(self.output_sep)
506 cout_write(self.output_sep)
511 outprompt = self.shell.hooks.generate_output_prompt()
507 outprompt = self.shell.hooks.generate_output_prompt()
512 if self.do_full_cache:
508 if self.do_full_cache:
513 cout_write(outprompt)
509 cout_write(outprompt)
514
510
515 # and now call a possibly user-defined print mechanism
511 # and now call a possibly user-defined print mechanism
516 manipulated_val = self.display(arg)
512 manipulated_val = self.display(arg)
517
513
518 # user display hooks can change the variable to be stored in
514 # user display hooks can change the variable to be stored in
519 # output history
515 # output history
520
516
521 if manipulated_val is not None:
517 if manipulated_val is not None:
522 arg = manipulated_val
518 arg = manipulated_val
523
519
524 # avoid recursive reference when displaying _oh/Out
520 # avoid recursive reference when displaying _oh/Out
525 if arg is not self.user_ns['_oh']:
521 if arg is not self.user_ns['_oh']:
526 self.update(arg)
522 self.update(arg)
527
523
528 cout_write(self.output_sep2)
524 cout_write(self.output_sep2)
529 Term.cout.flush()
525 Term.cout.flush()
530
526
531 def _display(self,arg):
527 def _display(self,arg):
532 """Default printer method, uses pprint.
528 """Default printer method, uses pprint.
533
529
534 Do ip.set_hook("result_display", my_displayhook) for custom result
530 Do ip.set_hook("result_display", my_displayhook) for custom result
535 display, e.g. when your own objects need special formatting.
531 display, e.g. when your own objects need special formatting.
536 """
532 """
537 try:
533 try:
538 return IPython.generics.result_display(arg)
534 return IPython.generics.result_display(arg)
539 except TryNext:
535 except TryNext:
540 return self.shell.hooks.result_display(arg)
536 return self.shell.hooks.result_display(arg)
541
537
542 # Assign the default display method:
538 # Assign the default display method:
543 display = _display
539 display = _display
544
540
545 def update(self,arg):
541 def update(self,arg):
546 #print '***cache_count', self.cache_count # dbg
542 #print '***cache_count', self.cache_count # dbg
547 if len(self.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
543 if len(self.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
548 warn('Output cache limit (currently '+
544 warn('Output cache limit (currently '+
549 `self.cache_size`+' entries) hit.\n'
545 `self.cache_size`+' entries) hit.\n'
550 'Flushing cache and resetting history counter...\n'
546 'Flushing cache and resetting history counter...\n'
551 'The only history variables available will be _,__,___ and _1\n'
547 'The only history variables available will be _,__,___ and _1\n'
552 'with the current result.')
548 'with the current result.')
553
549
554 self.flush()
550 self.flush()
555 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
551 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
556 # we cause buggy behavior for things like gettext).
552 # we cause buggy behavior for things like gettext).
557 if '_' not in __builtin__.__dict__:
553 if '_' not in __builtin__.__dict__:
558 self.___ = self.__
554 self.___ = self.__
559 self.__ = self._
555 self.__ = self._
560 self._ = arg
556 self._ = arg
561 self.user_ns.update({'_':self._,'__':self.__,'___':self.___})
557 self.user_ns.update({'_':self._,'__':self.__,'___':self.___})
562
558
563 # hackish access to top-level namespace to create _1,_2... dynamically
559 # hackish access to top-level namespace to create _1,_2... dynamically
564 to_main = {}
560 to_main = {}
565 if self.do_full_cache:
561 if self.do_full_cache:
566 new_result = '_'+`self.prompt_count`
562 new_result = '_'+`self.prompt_count`
567 to_main[new_result] = arg
563 to_main[new_result] = arg
568 self.user_ns.update(to_main)
564 self.user_ns.update(to_main)
569 self.user_ns['_oh'][self.prompt_count] = arg
565 self.user_ns['_oh'][self.prompt_count] = arg
570
566
571 def flush(self):
567 def flush(self):
572 if not self.do_full_cache:
568 if not self.do_full_cache:
573 raise ValueError,"You shouldn't have reached the cache flush "\
569 raise ValueError,"You shouldn't have reached the cache flush "\
574 "if full caching is not enabled!"
570 "if full caching is not enabled!"
575 # delete auto-generated vars from global namespace
571 # delete auto-generated vars from global namespace
576
572
577 for n in range(1,self.prompt_count + 1):
573 for n in range(1,self.prompt_count + 1):
578 key = '_'+`n`
574 key = '_'+`n`
579 try:
575 try:
580 del self.user_ns[key]
576 del self.user_ns[key]
581 except: pass
577 except: pass
582 self.user_ns['_oh'].clear()
578 self.user_ns['_oh'].clear()
583
579
584 if '_' not in __builtin__.__dict__:
580 if '_' not in __builtin__.__dict__:
585 self.user_ns.update({'_':None,'__':None, '___':None})
581 self.user_ns.update({'_':None,'__':None, '___':None})
586 import gc
582 import gc
587 gc.collect() # xxx needed?
583 gc.collect() # xxx needed?
588
584
@@ -1,965 +1,960 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 # -*- test-case-name: IPython.kernel.test.test_multiengineclient -*-
2 # -*- test-case-name: IPython.kernel.test.test_multiengineclient -*-
3
3
4 """General Classes for IMultiEngine clients."""
4 """General Classes for IMultiEngine clients."""
5
5
6 __docformat__ = "restructuredtext en"
6 __docformat__ = "restructuredtext en"
7
7
8 #-------------------------------------------------------------------------------
8 #-------------------------------------------------------------------------------
9 # Copyright (C) 2008 The IPython Development Team
9 # Copyright (C) 2008 The IPython Development Team
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is in
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
12 # the file COPYING, distributed as part of this software.
13 #-------------------------------------------------------------------------------
13 #-------------------------------------------------------------------------------
14
14
15 #-------------------------------------------------------------------------------
15 #-------------------------------------------------------------------------------
16 # Imports
16 # Imports
17 #-------------------------------------------------------------------------------
17 #-------------------------------------------------------------------------------
18
18
19 import sys
19 import sys
20 import cPickle as pickle
21 from types import FunctionType
22 import linecache
20 import linecache
23 import warnings
21 import warnings
24
22
25 from twisted.internet import reactor
23 from twisted.python import components
26 from twisted.python import components, log
27 from twisted.python.failure import Failure
24 from twisted.python.failure import Failure
28 from zope.interface import Interface, implements, Attribute
25 from zope.interface import Interface, implements, Attribute
29
26
30 from IPython.ColorANSI import TermColors
27 from IPython.utils.coloransi import TermColors
31
28
32 from IPython.kernel.twistedutil import blockingCallFromThread
29 from IPython.kernel.twistedutil import blockingCallFromThread
33 from IPython.kernel import error
30 from IPython.kernel import error
34 from IPython.kernel.parallelfunction import ParallelFunction
31 from IPython.kernel.parallelfunction import ParallelFunction
35 from IPython.kernel.mapper import (
32 from IPython.kernel.mapper import (
36 MultiEngineMapper,
33 MultiEngineMapper,
37 IMultiEngineMapperFactory,
34 IMultiEngineMapperFactory,
38 IMapper
35 IMapper
39 )
36 )
40 from IPython.kernel import map as Map
37
41 from IPython.kernel import multiengine as me
38 from IPython.kernel.multiengine import IFullSynchronousMultiEngine
42 from IPython.kernel.multiengine import (IFullMultiEngine,
43 IFullSynchronousMultiEngine)
44
39
45
40
46 #-------------------------------------------------------------------------------
41 #-------------------------------------------------------------------------------
47 # Pending Result things
42 # Pending Result things
48 #-------------------------------------------------------------------------------
43 #-------------------------------------------------------------------------------
49
44
50 class IPendingResult(Interface):
45 class IPendingResult(Interface):
51 """A representation of a result that is pending.
46 """A representation of a result that is pending.
52
47
53 This class is similar to Twisted's `Deferred` object, but is designed to be
48 This class is similar to Twisted's `Deferred` object, but is designed to be
54 used in a synchronous context.
49 used in a synchronous context.
55 """
50 """
56
51
57 result_id=Attribute("ID of the deferred on the other side")
52 result_id=Attribute("ID of the deferred on the other side")
58 client=Attribute("A client that I came from")
53 client=Attribute("A client that I came from")
59 r=Attribute("An attribute that is a property that calls and returns get_result")
54 r=Attribute("An attribute that is a property that calls and returns get_result")
60
55
61 def get_result(default=None, block=True):
56 def get_result(default=None, block=True):
62 """
57 """
63 Get a result that is pending.
58 Get a result that is pending.
64
59
65 :Parameters:
60 :Parameters:
66 default
61 default
67 The value to return if the result is not ready.
62 The value to return if the result is not ready.
68 block : boolean
63 block : boolean
69 Should I block for the result.
64 Should I block for the result.
70
65
71 :Returns: The actual result or the default value.
66 :Returns: The actual result or the default value.
72 """
67 """
73
68
74 def add_callback(f, *args, **kwargs):
69 def add_callback(f, *args, **kwargs):
75 """
70 """
76 Add a callback that is called with the result.
71 Add a callback that is called with the result.
77
72
78 If the original result is foo, adding a callback will cause
73 If the original result is foo, adding a callback will cause
79 f(foo, *args, **kwargs) to be returned instead. If multiple
74 f(foo, *args, **kwargs) to be returned instead. If multiple
80 callbacks are registered, they are chained together: the result of
75 callbacks are registered, they are chained together: the result of
81 one is passed to the next and so on.
76 one is passed to the next and so on.
82
77
83 Unlike Twisted's Deferred object, there is no errback chain. Thus
78 Unlike Twisted's Deferred object, there is no errback chain. Thus
84 any exception raised will not be caught and handled. User must
79 any exception raised will not be caught and handled. User must
85 catch these by hand when calling `get_result`.
80 catch these by hand when calling `get_result`.
86 """
81 """
87
82
88
83
89 class PendingResult(object):
84 class PendingResult(object):
90 """A representation of a result that is not yet ready.
85 """A representation of a result that is not yet ready.
91
86
92 A user should not create a `PendingResult` instance by hand.
87 A user should not create a `PendingResult` instance by hand.
93
88
94 Methods
89 Methods
95 =======
90 =======
96
91
97 * `get_result`
92 * `get_result`
98 * `add_callback`
93 * `add_callback`
99
94
100 Properties
95 Properties
101 ==========
96 ==========
102 * `r`
97 * `r`
103 """
98 """
104
99
105 def __init__(self, client, result_id):
100 def __init__(self, client, result_id):
106 """Create a PendingResult with a result_id and a client instance.
101 """Create a PendingResult with a result_id and a client instance.
107
102
108 The client should implement `_getPendingResult(result_id, block)`.
103 The client should implement `_getPendingResult(result_id, block)`.
109 """
104 """
110 self.client = client
105 self.client = client
111 self.result_id = result_id
106 self.result_id = result_id
112 self.called = False
107 self.called = False
113 self.raised = False
108 self.raised = False
114 self.callbacks = []
109 self.callbacks = []
115
110
116 def get_result(self, default=None, block=True):
111 def get_result(self, default=None, block=True):
117 """Get a result that is pending.
112 """Get a result that is pending.
118
113
119 This method will connect to an IMultiEngine adapted controller
114 This method will connect to an IMultiEngine adapted controller
120 and see if the result is ready. If the action triggers an exception
115 and see if the result is ready. If the action triggers an exception
121 raise it and record it. This method records the result/exception once it is
116 raise it and record it. This method records the result/exception once it is
122 retrieved. Calling `get_result` again will get this cached result or will
117 retrieved. Calling `get_result` again will get this cached result or will
123 re-raise the exception. The .r attribute is a property that calls
118 re-raise the exception. The .r attribute is a property that calls
124 `get_result` with block=True.
119 `get_result` with block=True.
125
120
126 :Parameters:
121 :Parameters:
127 default
122 default
128 The value to return if the result is not ready.
123 The value to return if the result is not ready.
129 block : boolean
124 block : boolean
130 Should I block for the result.
125 Should I block for the result.
131
126
132 :Returns: The actual result or the default value.
127 :Returns: The actual result or the default value.
133 """
128 """
134
129
135 if self.called:
130 if self.called:
136 if self.raised:
131 if self.raised:
137 raise self.result[0], self.result[1], self.result[2]
132 raise self.result[0], self.result[1], self.result[2]
138 else:
133 else:
139 return self.result
134 return self.result
140 try:
135 try:
141 result = self.client.get_pending_deferred(self.result_id, block)
136 result = self.client.get_pending_deferred(self.result_id, block)
142 except error.ResultNotCompleted:
137 except error.ResultNotCompleted:
143 return default
138 return default
144 except:
139 except:
145 # Reraise other error, but first record them so they can be reraised
140 # Reraise other error, but first record them so they can be reraised
146 # later if .r or get_result is called again.
141 # later if .r or get_result is called again.
147 self.result = sys.exc_info()
142 self.result = sys.exc_info()
148 self.called = True
143 self.called = True
149 self.raised = True
144 self.raised = True
150 raise
145 raise
151 else:
146 else:
152 for cb in self.callbacks:
147 for cb in self.callbacks:
153 result = cb[0](result, *cb[1], **cb[2])
148 result = cb[0](result, *cb[1], **cb[2])
154 self.result = result
149 self.result = result
155 self.called = True
150 self.called = True
156 return result
151 return result
157
152
158 def add_callback(self, f, *args, **kwargs):
153 def add_callback(self, f, *args, **kwargs):
159 """Add a callback that is called with the result.
154 """Add a callback that is called with the result.
160
155
161 If the original result is result, adding a callback will cause
156 If the original result is result, adding a callback will cause
162 f(result, *args, **kwargs) to be returned instead. If multiple
157 f(result, *args, **kwargs) to be returned instead. If multiple
163 callbacks are registered, they are chained together: the result of
158 callbacks are registered, they are chained together: the result of
164 one is passed to the next and so on.
159 one is passed to the next and so on.
165
160
166 Unlike Twisted's Deferred object, there is no errback chain. Thus
161 Unlike Twisted's Deferred object, there is no errback chain. Thus
167 any exception raised will not be caught and handled. User must
162 any exception raised will not be caught and handled. User must
168 catch these by hand when calling `get_result`.
163 catch these by hand when calling `get_result`.
169 """
164 """
170 assert callable(f)
165 assert callable(f)
171 self.callbacks.append((f, args, kwargs))
166 self.callbacks.append((f, args, kwargs))
172
167
173 def __cmp__(self, other):
168 def __cmp__(self, other):
174 if self.result_id < other.result_id:
169 if self.result_id < other.result_id:
175 return -1
170 return -1
176 else:
171 else:
177 return 1
172 return 1
178
173
179 def _get_r(self):
174 def _get_r(self):
180 return self.get_result(block=True)
175 return self.get_result(block=True)
181
176
182 r = property(_get_r)
177 r = property(_get_r)
183 """This property is a shortcut to a `get_result(block=True)`."""
178 """This property is a shortcut to a `get_result(block=True)`."""
184
179
185
180
186 #-------------------------------------------------------------------------------
181 #-------------------------------------------------------------------------------
187 # Pretty printing wrappers for certain lists
182 # Pretty printing wrappers for certain lists
188 #-------------------------------------------------------------------------------
183 #-------------------------------------------------------------------------------
189
184
190 class ResultList(list):
185 class ResultList(list):
191 """A subclass of list that pretty prints the output of `execute`/`get_result`."""
186 """A subclass of list that pretty prints the output of `execute`/`get_result`."""
192
187
193 def __repr__(self):
188 def __repr__(self):
194 output = []
189 output = []
195 # These colored prompts were not working on Windows
190 # These colored prompts were not working on Windows
196 if sys.platform == 'win32':
191 if sys.platform == 'win32':
197 blue = normal = red = green = ''
192 blue = normal = red = green = ''
198 else:
193 else:
199 blue = TermColors.Blue
194 blue = TermColors.Blue
200 normal = TermColors.Normal
195 normal = TermColors.Normal
201 red = TermColors.Red
196 red = TermColors.Red
202 green = TermColors.Green
197 green = TermColors.Green
203 output.append("<Results List>\n")
198 output.append("<Results List>\n")
204 for cmd in self:
199 for cmd in self:
205 if isinstance(cmd, Failure):
200 if isinstance(cmd, Failure):
206 output.append(cmd)
201 output.append(cmd)
207 else:
202 else:
208 target = cmd.get('id',None)
203 target = cmd.get('id',None)
209 cmd_num = cmd.get('number',None)
204 cmd_num = cmd.get('number',None)
210 cmd_stdin = cmd.get('input',{}).get('translated','No Input')
205 cmd_stdin = cmd.get('input',{}).get('translated','No Input')
211 cmd_stdout = cmd.get('stdout', None)
206 cmd_stdout = cmd.get('stdout', None)
212 cmd_stderr = cmd.get('stderr', None)
207 cmd_stderr = cmd.get('stderr', None)
213 output.append("%s[%i]%s In [%i]:%s %s\n" % \
208 output.append("%s[%i]%s In [%i]:%s %s\n" % \
214 (green, target,
209 (green, target,
215 blue, cmd_num, normal, cmd_stdin))
210 blue, cmd_num, normal, cmd_stdin))
216 if cmd_stdout:
211 if cmd_stdout:
217 output.append("%s[%i]%s Out[%i]:%s %s\n" % \
212 output.append("%s[%i]%s Out[%i]:%s %s\n" % \
218 (green, target,
213 (green, target,
219 red, cmd_num, normal, cmd_stdout))
214 red, cmd_num, normal, cmd_stdout))
220 if cmd_stderr:
215 if cmd_stderr:
221 output.append("%s[%i]%s Err[%i]:\n%s %s" % \
216 output.append("%s[%i]%s Err[%i]:\n%s %s" % \
222 (green, target,
217 (green, target,
223 red, cmd_num, normal, cmd_stderr))
218 red, cmd_num, normal, cmd_stderr))
224 return ''.join(output)
219 return ''.join(output)
225
220
226
221
227 def wrapResultList(result):
222 def wrapResultList(result):
228 """A function that wraps the output of `execute`/`get_result` -> `ResultList`."""
223 """A function that wraps the output of `execute`/`get_result` -> `ResultList`."""
229 if len(result) == 0:
224 if len(result) == 0:
230 result = [result]
225 result = [result]
231 return ResultList(result)
226 return ResultList(result)
232
227
233
228
234 class QueueStatusList(list):
229 class QueueStatusList(list):
235 """A subclass of list that pretty prints the output of `queue_status`."""
230 """A subclass of list that pretty prints the output of `queue_status`."""
236
231
237 def __repr__(self):
232 def __repr__(self):
238 output = []
233 output = []
239 output.append("<Queue Status List>\n")
234 output.append("<Queue Status List>\n")
240 for e in self:
235 for e in self:
241 output.append("Engine: %s\n" % repr(e[0]))
236 output.append("Engine: %s\n" % repr(e[0]))
242 output.append(" Pending: %s\n" % repr(e[1]['pending']))
237 output.append(" Pending: %s\n" % repr(e[1]['pending']))
243 for q in e[1]['queue']:
238 for q in e[1]['queue']:
244 output.append(" Command: %s\n" % repr(q))
239 output.append(" Command: %s\n" % repr(q))
245 return ''.join(output)
240 return ''.join(output)
246
241
247
242
248 #-------------------------------------------------------------------------------
243 #-------------------------------------------------------------------------------
249 # InteractiveMultiEngineClient
244 # InteractiveMultiEngineClient
250 #-------------------------------------------------------------------------------
245 #-------------------------------------------------------------------------------
251
246
252 class InteractiveMultiEngineClient(object):
247 class InteractiveMultiEngineClient(object):
253 """A mixin class that add a few methods to a multiengine client.
248 """A mixin class that add a few methods to a multiengine client.
254
249
255 The methods in this mixin class are designed for interactive usage.
250 The methods in this mixin class are designed for interactive usage.
256 """
251 """
257
252
258 def activate(self):
253 def activate(self):
259 """Make this `MultiEngineClient` active for parallel magic commands.
254 """Make this `MultiEngineClient` active for parallel magic commands.
260
255
261 IPython has a magic command syntax to work with `MultiEngineClient` objects.
256 IPython has a magic command syntax to work with `MultiEngineClient` objects.
262 In a given IPython session there is a single active one. While
257 In a given IPython session there is a single active one. While
263 there can be many `MultiEngineClient` created and used by the user,
258 there can be many `MultiEngineClient` created and used by the user,
264 there is only one active one. The active `MultiEngineClient` is used whenever
259 there is only one active one. The active `MultiEngineClient` is used whenever
265 the magic commands %px and %autopx are used.
260 the magic commands %px and %autopx are used.
266
261
267 The activate() method is called on a given `MultiEngineClient` to make it
262 The activate() method is called on a given `MultiEngineClient` to make it
268 active. Once this has been done, the magic commands can be used.
263 active. Once this has been done, the magic commands can be used.
269 """
264 """
270
265
271 try:
266 try:
272 __IPYTHON__.activeController = self
267 __IPYTHON__.activeController = self
273 except NameError:
268 except NameError:
274 print "The IPython Controller magics only work within IPython."
269 print "The IPython Controller magics only work within IPython."
275
270
276 def __setitem__(self, key, value):
271 def __setitem__(self, key, value):
277 """Add a dictionary interface for pushing/pulling.
272 """Add a dictionary interface for pushing/pulling.
278
273
279 This functions as a shorthand for `push`.
274 This functions as a shorthand for `push`.
280
275
281 :Parameters:
276 :Parameters:
282 key : str
277 key : str
283 What to call the remote object.
278 What to call the remote object.
284 value : object
279 value : object
285 The local Python object to push.
280 The local Python object to push.
286 """
281 """
287 targets, block = self._findTargetsAndBlock()
282 targets, block = self._findTargetsAndBlock()
288 return self.push({key:value}, targets=targets, block=block)
283 return self.push({key:value}, targets=targets, block=block)
289
284
290 def __getitem__(self, key):
285 def __getitem__(self, key):
291 """Add a dictionary interface for pushing/pulling.
286 """Add a dictionary interface for pushing/pulling.
292
287
293 This functions as a shorthand to `pull`.
288 This functions as a shorthand to `pull`.
294
289
295 :Parameters:
290 :Parameters:
296 - `key`: A string representing the key.
291 - `key`: A string representing the key.
297 """
292 """
298 if isinstance(key, str):
293 if isinstance(key, str):
299 targets, block = self._findTargetsAndBlock()
294 targets, block = self._findTargetsAndBlock()
300 return self.pull(key, targets=targets, block=block)
295 return self.pull(key, targets=targets, block=block)
301 else:
296 else:
302 raise TypeError("__getitem__ only takes strs")
297 raise TypeError("__getitem__ only takes strs")
303
298
304 def __len__(self):
299 def __len__(self):
305 """Return the number of available engines."""
300 """Return the number of available engines."""
306 return len(self.get_ids())
301 return len(self.get_ids())
307
302
308 #---------------------------------------------------------------------------
303 #---------------------------------------------------------------------------
309 # Make this a context manager for with
304 # Make this a context manager for with
310 #---------------------------------------------------------------------------
305 #---------------------------------------------------------------------------
311
306
312 def findsource_file(self,f):
307 def findsource_file(self,f):
313 linecache.checkcache()
308 linecache.checkcache()
314 s = findsource(f.f_code)
309 s = findsource(f.f_code) # findsource is not defined!
315 lnum = f.f_lineno
310 lnum = f.f_lineno
316 wsource = s[0][f.f_lineno:]
311 wsource = s[0][f.f_lineno:]
317 return strip_whitespace(wsource)
312 return strip_whitespace(wsource)
318
313
319 def findsource_ipython(self,f):
314 def findsource_ipython(self,f):
320 from IPython import ipapi
315 from IPython import ipapi
321 self.ip = ipapi.get()
316 self.ip = ipapi.get()
322 wsource = [l+'\n' for l in
317 wsource = [l+'\n' for l in
323 self.ip.IP.input_hist_raw[-1].splitlines()[1:]]
318 self.ip.IP.input_hist_raw[-1].splitlines()[1:]]
324 return strip_whitespace(wsource)
319 return strip_whitespace(wsource)
325
320
326 def __enter__(self):
321 def __enter__(self):
327 f = sys._getframe(1)
322 f = sys._getframe(1)
328 local_ns = f.f_locals
323 local_ns = f.f_locals
329 global_ns = f.f_globals
324 global_ns = f.f_globals
330 if f.f_code.co_filename == '<ipython console>':
325 if f.f_code.co_filename == '<ipython console>':
331 s = self.findsource_ipython(f)
326 s = self.findsource_ipython(f)
332 else:
327 else:
333 s = self.findsource_file(f)
328 s = self.findsource_file(f)
334
329
335 self._with_context_result = self.execute(s)
330 self._with_context_result = self.execute(s)
336
331
337 def __exit__ (self, etype, value, tb):
332 def __exit__ (self, etype, value, tb):
338 if issubclass(etype,error.StopLocalExecution):
333 if issubclass(etype,error.StopLocalExecution):
339 return True
334 return True
340
335
341
336
342 def remote():
337 def remote():
343 m = 'Special exception to stop local execution of parallel code.'
338 m = 'Special exception to stop local execution of parallel code.'
344 raise error.StopLocalExecution(m)
339 raise error.StopLocalExecution(m)
345
340
346 def strip_whitespace(source):
341 def strip_whitespace(source):
347 # Expand tabs to avoid any confusion.
342 # Expand tabs to avoid any confusion.
348 wsource = [l.expandtabs(4) for l in source]
343 wsource = [l.expandtabs(4) for l in source]
349 # Detect the indentation level
344 # Detect the indentation level
350 done = False
345 done = False
351 for line in wsource:
346 for line in wsource:
352 if line.isspace():
347 if line.isspace():
353 continue
348 continue
354 for col,char in enumerate(line):
349 for col,char in enumerate(line):
355 if char != ' ':
350 if char != ' ':
356 done = True
351 done = True
357 break
352 break
358 if done:
353 if done:
359 break
354 break
360 # Now we know how much leading space there is in the code. Next, we
355 # Now we know how much leading space there is in the code. Next, we
361 # extract up to the first line that has less indentation.
356 # extract up to the first line that has less indentation.
362 # WARNINGS: we skip comments that may be misindented, but we do NOT yet
357 # WARNINGS: we skip comments that may be misindented, but we do NOT yet
363 # detect triple quoted strings that may have flush left text.
358 # detect triple quoted strings that may have flush left text.
364 for lno,line in enumerate(wsource):
359 for lno,line in enumerate(wsource):
365 lead = line[:col]
360 lead = line[:col]
366 if lead.isspace():
361 if lead.isspace():
367 continue
362 continue
368 else:
363 else:
369 if not lead.lstrip().startswith('#'):
364 if not lead.lstrip().startswith('#'):
370 break
365 break
371 # The real 'with' source is up to lno
366 # The real 'with' source is up to lno
372 src_lines = [l[col:] for l in wsource[:lno+1]]
367 src_lines = [l[col:] for l in wsource[:lno+1]]
373
368
374 # Finally, check that the source's first non-comment line begins with the
369 # Finally, check that the source's first non-comment line begins with the
375 # special call 'remote()'
370 # special call 'remote()'
376 for nline,line in enumerate(src_lines):
371 for nline,line in enumerate(src_lines):
377 if line.isspace() or line.startswith('#'):
372 if line.isspace() or line.startswith('#'):
378 continue
373 continue
379 if 'remote()' in line:
374 if 'remote()' in line:
380 break
375 break
381 else:
376 else:
382 raise ValueError('remote() call missing at the start of code')
377 raise ValueError('remote() call missing at the start of code')
383 src = ''.join(src_lines[nline+1:])
378 src = ''.join(src_lines[nline+1:])
384 #print 'SRC:\n<<<<<<<>>>>>>>\n%s<<<<<>>>>>>' % src # dbg
379 #print 'SRC:\n<<<<<<<>>>>>>>\n%s<<<<<>>>>>>' % src # dbg
385 return src
380 return src
386
381
387
382
388 #-------------------------------------------------------------------------------
383 #-------------------------------------------------------------------------------
389 # The top-level MultiEngine client adaptor
384 # The top-level MultiEngine client adaptor
390 #-------------------------------------------------------------------------------
385 #-------------------------------------------------------------------------------
391
386
392
387
393 _prop_warn = """\
388 _prop_warn = """\
394
389
395 We are currently refactoring the task dependency system. This might
390 We are currently refactoring the task dependency system. This might
396 involve the removal of this method and other methods related to engine
391 involve the removal of this method and other methods related to engine
397 properties. Please see the docstrings for IPython.kernel.TaskRejectError
392 properties. Please see the docstrings for IPython.kernel.TaskRejectError
398 for more information."""
393 for more information."""
399
394
400
395
401 class IFullBlockingMultiEngineClient(Interface):
396 class IFullBlockingMultiEngineClient(Interface):
402 pass
397 pass
403
398
404
399
405 class FullBlockingMultiEngineClient(InteractiveMultiEngineClient):
400 class FullBlockingMultiEngineClient(InteractiveMultiEngineClient):
406 """
401 """
407 A blocking client to the `IMultiEngine` controller interface.
402 A blocking client to the `IMultiEngine` controller interface.
408
403
409 This class allows users to use a set of engines for a parallel
404 This class allows users to use a set of engines for a parallel
410 computation through the `IMultiEngine` interface. In this interface,
405 computation through the `IMultiEngine` interface. In this interface,
411 each engine has a specific id (an int) that is used to refer to the
406 each engine has a specific id (an int) that is used to refer to the
412 engine, run code on it, etc.
407 engine, run code on it, etc.
413 """
408 """
414
409
415 implements(
410 implements(
416 IFullBlockingMultiEngineClient,
411 IFullBlockingMultiEngineClient,
417 IMultiEngineMapperFactory,
412 IMultiEngineMapperFactory,
418 IMapper
413 IMapper
419 )
414 )
420
415
421 def __init__(self, smultiengine):
416 def __init__(self, smultiengine):
422 self.smultiengine = smultiengine
417 self.smultiengine = smultiengine
423 self.block = True
418 self.block = True
424 self.targets = 'all'
419 self.targets = 'all'
425
420
426 def _findBlock(self, block=None):
421 def _findBlock(self, block=None):
427 if block is None:
422 if block is None:
428 return self.block
423 return self.block
429 else:
424 else:
430 if block in (True, False):
425 if block in (True, False):
431 return block
426 return block
432 else:
427 else:
433 raise ValueError("block must be True or False")
428 raise ValueError("block must be True or False")
434
429
435 def _findTargets(self, targets=None):
430 def _findTargets(self, targets=None):
436 if targets is None:
431 if targets is None:
437 return self.targets
432 return self.targets
438 else:
433 else:
439 if not isinstance(targets, (str,list,tuple,int)):
434 if not isinstance(targets, (str,list,tuple,int)):
440 raise ValueError("targets must be a str, list, tuple or int")
435 raise ValueError("targets must be a str, list, tuple or int")
441 return targets
436 return targets
442
437
443 def _findTargetsAndBlock(self, targets=None, block=None):
438 def _findTargetsAndBlock(self, targets=None, block=None):
444 return self._findTargets(targets), self._findBlock(block)
439 return self._findTargets(targets), self._findBlock(block)
445
440
446 def _blockFromThread(self, function, *args, **kwargs):
441 def _blockFromThread(self, function, *args, **kwargs):
447 block = kwargs.get('block', None)
442 block = kwargs.get('block', None)
448 if block is None:
443 if block is None:
449 raise error.MissingBlockArgument("'block' keyword argument is missing")
444 raise error.MissingBlockArgument("'block' keyword argument is missing")
450 result = blockingCallFromThread(function, *args, **kwargs)
445 result = blockingCallFromThread(function, *args, **kwargs)
451 if not block:
446 if not block:
452 result = PendingResult(self, result)
447 result = PendingResult(self, result)
453 return result
448 return result
454
449
455 def get_pending_deferred(self, deferredID, block):
450 def get_pending_deferred(self, deferredID, block):
456 return blockingCallFromThread(self.smultiengine.get_pending_deferred, deferredID, block)
451 return blockingCallFromThread(self.smultiengine.get_pending_deferred, deferredID, block)
457
452
458 def barrier(self, pendingResults):
453 def barrier(self, pendingResults):
459 """Synchronize a set of `PendingResults`.
454 """Synchronize a set of `PendingResults`.
460
455
461 This method is a synchronization primitive that waits for a set of
456 This method is a synchronization primitive that waits for a set of
462 `PendingResult` objects to complete. More specifically, barier does
457 `PendingResult` objects to complete. More specifically, barier does
463 the following.
458 the following.
464
459
465 * The `PendingResult`s are sorted by result_id.
460 * The `PendingResult`s are sorted by result_id.
466 * The `get_result` method is called for each `PendingResult` sequentially
461 * The `get_result` method is called for each `PendingResult` sequentially
467 with block=True.
462 with block=True.
468 * If a `PendingResult` gets a result that is an exception, it is
463 * If a `PendingResult` gets a result that is an exception, it is
469 trapped and can be re-raised later by calling `get_result` again.
464 trapped and can be re-raised later by calling `get_result` again.
470 * The `PendingResult`s are flushed from the controller.
465 * The `PendingResult`s are flushed from the controller.
471
466
472 After barrier has been called on a `PendingResult`, its results can
467 After barrier has been called on a `PendingResult`, its results can
473 be retrieved by calling `get_result` again or accesing the `r` attribute
468 be retrieved by calling `get_result` again or accesing the `r` attribute
474 of the instance.
469 of the instance.
475 """
470 """
476
471
477 # Convert to list for sorting and check class type
472 # Convert to list for sorting and check class type
478 prList = list(pendingResults)
473 prList = list(pendingResults)
479 for pr in prList:
474 for pr in prList:
480 if not isinstance(pr, PendingResult):
475 if not isinstance(pr, PendingResult):
481 raise error.NotAPendingResult("Objects passed to barrier must be PendingResult instances")
476 raise error.NotAPendingResult("Objects passed to barrier must be PendingResult instances")
482
477
483 # Sort the PendingResults so they are in order
478 # Sort the PendingResults so they are in order
484 prList.sort()
479 prList.sort()
485 # Block on each PendingResult object
480 # Block on each PendingResult object
486 for pr in prList:
481 for pr in prList:
487 try:
482 try:
488 result = pr.get_result(block=True)
483 result = pr.get_result(block=True)
489 except Exception:
484 except Exception:
490 pass
485 pass
491
486
492 def flush(self):
487 def flush(self):
493 """
488 """
494 Clear all pending deferreds/results from the controller.
489 Clear all pending deferreds/results from the controller.
495
490
496 For each `PendingResult` that is created by this client, the controller
491 For each `PendingResult` that is created by this client, the controller
497 holds on to the result for that `PendingResult`. This can be a problem
492 holds on to the result for that `PendingResult`. This can be a problem
498 if there are a large number of `PendingResult` objects that are created.
493 if there are a large number of `PendingResult` objects that are created.
499
494
500 Once the result of the `PendingResult` has been retrieved, the result
495 Once the result of the `PendingResult` has been retrieved, the result
501 is removed from the controller, but if a user doesn't get a result (
496 is removed from the controller, but if a user doesn't get a result (
502 they just ignore the `PendingResult`) the result is kept forever on the
497 they just ignore the `PendingResult`) the result is kept forever on the
503 controller. This method allows the user to clear out all un-retrieved
498 controller. This method allows the user to clear out all un-retrieved
504 results on the controller.
499 results on the controller.
505 """
500 """
506 r = blockingCallFromThread(self.smultiengine.clear_pending_deferreds)
501 r = blockingCallFromThread(self.smultiengine.clear_pending_deferreds)
507 return r
502 return r
508
503
509 clear_pending_results = flush
504 clear_pending_results = flush
510
505
511 #---------------------------------------------------------------------------
506 #---------------------------------------------------------------------------
512 # IEngineMultiplexer related methods
507 # IEngineMultiplexer related methods
513 #---------------------------------------------------------------------------
508 #---------------------------------------------------------------------------
514
509
515 def execute(self, lines, targets=None, block=None):
510 def execute(self, lines, targets=None, block=None):
516 """
511 """
517 Execute code on a set of engines.
512 Execute code on a set of engines.
518
513
519 :Parameters:
514 :Parameters:
520 lines : str
515 lines : str
521 The Python code to execute as a string
516 The Python code to execute as a string
522 targets : id or list of ids
517 targets : id or list of ids
523 The engine to use for the execution
518 The engine to use for the execution
524 block : boolean
519 block : boolean
525 If False, this method will return the actual result. If False,
520 If False, this method will return the actual result. If False,
526 a `PendingResult` is returned which can be used to get the result
521 a `PendingResult` is returned which can be used to get the result
527 at a later time.
522 at a later time.
528 """
523 """
529 targets, block = self._findTargetsAndBlock(targets, block)
524 targets, block = self._findTargetsAndBlock(targets, block)
530 result = blockingCallFromThread(self.smultiengine.execute, lines,
525 result = blockingCallFromThread(self.smultiengine.execute, lines,
531 targets=targets, block=block)
526 targets=targets, block=block)
532 if block:
527 if block:
533 result = ResultList(result)
528 result = ResultList(result)
534 else:
529 else:
535 result = PendingResult(self, result)
530 result = PendingResult(self, result)
536 result.add_callback(wrapResultList)
531 result.add_callback(wrapResultList)
537 return result
532 return result
538
533
539 def push(self, namespace, targets=None, block=None):
534 def push(self, namespace, targets=None, block=None):
540 """
535 """
541 Push a dictionary of keys and values to engines namespace.
536 Push a dictionary of keys and values to engines namespace.
542
537
543 Each engine has a persistent namespace. This method is used to push
538 Each engine has a persistent namespace. This method is used to push
544 Python objects into that namespace.
539 Python objects into that namespace.
545
540
546 The objects in the namespace must be pickleable.
541 The objects in the namespace must be pickleable.
547
542
548 :Parameters:
543 :Parameters:
549 namespace : dict
544 namespace : dict
550 A dict that contains Python objects to be injected into
545 A dict that contains Python objects to be injected into
551 the engine persistent namespace.
546 the engine persistent namespace.
552 targets : id or list of ids
547 targets : id or list of ids
553 The engine to use for the execution
548 The engine to use for the execution
554 block : boolean
549 block : boolean
555 If False, this method will return the actual result. If False,
550 If False, this method will return the actual result. If False,
556 a `PendingResult` is returned which can be used to get the result
551 a `PendingResult` is returned which can be used to get the result
557 at a later time.
552 at a later time.
558 """
553 """
559 targets, block = self._findTargetsAndBlock(targets, block)
554 targets, block = self._findTargetsAndBlock(targets, block)
560 return self._blockFromThread(self.smultiengine.push, namespace,
555 return self._blockFromThread(self.smultiengine.push, namespace,
561 targets=targets, block=block)
556 targets=targets, block=block)
562
557
563 def pull(self, keys, targets=None, block=None):
558 def pull(self, keys, targets=None, block=None):
564 """
559 """
565 Pull Python objects by key out of engines namespaces.
560 Pull Python objects by key out of engines namespaces.
566
561
567 :Parameters:
562 :Parameters:
568 keys : str or list of str
563 keys : str or list of str
569 The names of the variables to be pulled
564 The names of the variables to be pulled
570 targets : id or list of ids
565 targets : id or list of ids
571 The engine to use for the execution
566 The engine to use for the execution
572 block : boolean
567 block : boolean
573 If False, this method will return the actual result. If False,
568 If False, this method will return the actual result. If False,
574 a `PendingResult` is returned which can be used to get the result
569 a `PendingResult` is returned which can be used to get the result
575 at a later time.
570 at a later time.
576 """
571 """
577 targets, block = self._findTargetsAndBlock(targets, block)
572 targets, block = self._findTargetsAndBlock(targets, block)
578 return self._blockFromThread(self.smultiengine.pull, keys, targets=targets, block=block)
573 return self._blockFromThread(self.smultiengine.pull, keys, targets=targets, block=block)
579
574
580 def push_function(self, namespace, targets=None, block=None):
575 def push_function(self, namespace, targets=None, block=None):
581 """
576 """
582 Push a Python function to an engine.
577 Push a Python function to an engine.
583
578
584 This method is used to push a Python function to an engine. This
579 This method is used to push a Python function to an engine. This
585 method can then be used in code on the engines. Closures are not supported.
580 method can then be used in code on the engines. Closures are not supported.
586
581
587 :Parameters:
582 :Parameters:
588 namespace : dict
583 namespace : dict
589 A dict whose values are the functions to be pushed. The keys give
584 A dict whose values are the functions to be pushed. The keys give
590 that names that the function will appear as in the engines
585 that names that the function will appear as in the engines
591 namespace.
586 namespace.
592 targets : id or list of ids
587 targets : id or list of ids
593 The engine to use for the execution
588 The engine to use for the execution
594 block : boolean
589 block : boolean
595 If False, this method will return the actual result. If False,
590 If False, this method will return the actual result. If False,
596 a `PendingResult` is returned which can be used to get the result
591 a `PendingResult` is returned which can be used to get the result
597 at a later time.
592 at a later time.
598 """
593 """
599 targets, block = self._findTargetsAndBlock(targets, block)
594 targets, block = self._findTargetsAndBlock(targets, block)
600 return self._blockFromThread(self.smultiengine.push_function, namespace, targets=targets, block=block)
595 return self._blockFromThread(self.smultiengine.push_function, namespace, targets=targets, block=block)
601
596
602 def pull_function(self, keys, targets=None, block=None):
597 def pull_function(self, keys, targets=None, block=None):
603 """
598 """
604 Pull a Python function from an engine.
599 Pull a Python function from an engine.
605
600
606 This method is used to pull a Python function from an engine.
601 This method is used to pull a Python function from an engine.
607 Closures are not supported.
602 Closures are not supported.
608
603
609 :Parameters:
604 :Parameters:
610 keys : str or list of str
605 keys : str or list of str
611 The names of the functions to be pulled
606 The names of the functions to be pulled
612 targets : id or list of ids
607 targets : id or list of ids
613 The engine to use for the execution
608 The engine to use for the execution
614 block : boolean
609 block : boolean
615 If False, this method will return the actual result. If False,
610 If False, this method will return the actual result. If False,
616 a `PendingResult` is returned which can be used to get the result
611 a `PendingResult` is returned which can be used to get the result
617 at a later time.
612 at a later time.
618 """
613 """
619 targets, block = self._findTargetsAndBlock(targets, block)
614 targets, block = self._findTargetsAndBlock(targets, block)
620 return self._blockFromThread(self.smultiengine.pull_function, keys, targets=targets, block=block)
615 return self._blockFromThread(self.smultiengine.pull_function, keys, targets=targets, block=block)
621
616
622 def push_serialized(self, namespace, targets=None, block=None):
617 def push_serialized(self, namespace, targets=None, block=None):
623 targets, block = self._findTargetsAndBlock(targets, block)
618 targets, block = self._findTargetsAndBlock(targets, block)
624 return self._blockFromThread(self.smultiengine.push_serialized, namespace, targets=targets, block=block)
619 return self._blockFromThread(self.smultiengine.push_serialized, namespace, targets=targets, block=block)
625
620
626 def pull_serialized(self, keys, targets=None, block=None):
621 def pull_serialized(self, keys, targets=None, block=None):
627 targets, block = self._findTargetsAndBlock(targets, block)
622 targets, block = self._findTargetsAndBlock(targets, block)
628 return self._blockFromThread(self.smultiengine.pull_serialized, keys, targets=targets, block=block)
623 return self._blockFromThread(self.smultiengine.pull_serialized, keys, targets=targets, block=block)
629
624
630 def get_result(self, i=None, targets=None, block=None):
625 def get_result(self, i=None, targets=None, block=None):
631 """
626 """
632 Get a previous result.
627 Get a previous result.
633
628
634 When code is executed in an engine, a dict is created and returned. This
629 When code is executed in an engine, a dict is created and returned. This
635 method retrieves that dict for previous commands.
630 method retrieves that dict for previous commands.
636
631
637 :Parameters:
632 :Parameters:
638 i : int
633 i : int
639 The number of the result to get
634 The number of the result to get
640 targets : id or list of ids
635 targets : id or list of ids
641 The engine to use for the execution
636 The engine to use for the execution
642 block : boolean
637 block : boolean
643 If False, this method will return the actual result. If False,
638 If False, this method will return the actual result. If False,
644 a `PendingResult` is returned which can be used to get the result
639 a `PendingResult` is returned which can be used to get the result
645 at a later time.
640 at a later time.
646 """
641 """
647 targets, block = self._findTargetsAndBlock(targets, block)
642 targets, block = self._findTargetsAndBlock(targets, block)
648 result = blockingCallFromThread(self.smultiengine.get_result, i, targets=targets, block=block)
643 result = blockingCallFromThread(self.smultiengine.get_result, i, targets=targets, block=block)
649 if block:
644 if block:
650 result = ResultList(result)
645 result = ResultList(result)
651 else:
646 else:
652 result = PendingResult(self, result)
647 result = PendingResult(self, result)
653 result.add_callback(wrapResultList)
648 result.add_callback(wrapResultList)
654 return result
649 return result
655
650
656 def reset(self, targets=None, block=None):
651 def reset(self, targets=None, block=None):
657 """
652 """
658 Reset an engine.
653 Reset an engine.
659
654
660 This method clears out the namespace of an engine.
655 This method clears out the namespace of an engine.
661
656
662 :Parameters:
657 :Parameters:
663 targets : id or list of ids
658 targets : id or list of ids
664 The engine to use for the execution
659 The engine to use for the execution
665 block : boolean
660 block : boolean
666 If False, this method will return the actual result. If False,
661 If False, this method will return the actual result. If False,
667 a `PendingResult` is returned which can be used to get the result
662 a `PendingResult` is returned which can be used to get the result
668 at a later time.
663 at a later time.
669 """
664 """
670 targets, block = self._findTargetsAndBlock(targets, block)
665 targets, block = self._findTargetsAndBlock(targets, block)
671 return self._blockFromThread(self.smultiengine.reset, targets=targets, block=block)
666 return self._blockFromThread(self.smultiengine.reset, targets=targets, block=block)
672
667
673 def keys(self, targets=None, block=None):
668 def keys(self, targets=None, block=None):
674 """
669 """
675 Get a list of all the variables in an engine's namespace.
670 Get a list of all the variables in an engine's namespace.
676
671
677 :Parameters:
672 :Parameters:
678 targets : id or list of ids
673 targets : id or list of ids
679 The engine to use for the execution
674 The engine to use for the execution
680 block : boolean
675 block : boolean
681 If False, this method will return the actual result. If False,
676 If False, this method will return the actual result. If False,
682 a `PendingResult` is returned which can be used to get the result
677 a `PendingResult` is returned which can be used to get the result
683 at a later time.
678 at a later time.
684 """
679 """
685 targets, block = self._findTargetsAndBlock(targets, block)
680 targets, block = self._findTargetsAndBlock(targets, block)
686 return self._blockFromThread(self.smultiengine.keys, targets=targets, block=block)
681 return self._blockFromThread(self.smultiengine.keys, targets=targets, block=block)
687
682
688 def kill(self, controller=False, targets=None, block=None):
683 def kill(self, controller=False, targets=None, block=None):
689 """
684 """
690 Kill the engines and controller.
685 Kill the engines and controller.
691
686
692 This method is used to stop the engine and controller by calling
687 This method is used to stop the engine and controller by calling
693 `reactor.stop`.
688 `reactor.stop`.
694
689
695 :Parameters:
690 :Parameters:
696 controller : boolean
691 controller : boolean
697 If True, kill the engines and controller. If False, just the
692 If True, kill the engines and controller. If False, just the
698 engines
693 engines
699 targets : id or list of ids
694 targets : id or list of ids
700 The engine to use for the execution
695 The engine to use for the execution
701 block : boolean
696 block : boolean
702 If False, this method will return the actual result. If False,
697 If False, this method will return the actual result. If False,
703 a `PendingResult` is returned which can be used to get the result
698 a `PendingResult` is returned which can be used to get the result
704 at a later time.
699 at a later time.
705 """
700 """
706 targets, block = self._findTargetsAndBlock(targets, block)
701 targets, block = self._findTargetsAndBlock(targets, block)
707 return self._blockFromThread(self.smultiengine.kill, controller, targets=targets, block=block)
702 return self._blockFromThread(self.smultiengine.kill, controller, targets=targets, block=block)
708
703
709 def clear_queue(self, targets=None, block=None):
704 def clear_queue(self, targets=None, block=None):
710 """
705 """
711 Clear out the controller's queue for an engine.
706 Clear out the controller's queue for an engine.
712
707
713 The controller maintains a queue for each engine. This clear it out.
708 The controller maintains a queue for each engine. This clear it out.
714
709
715 :Parameters:
710 :Parameters:
716 targets : id or list of ids
711 targets : id or list of ids
717 The engine to use for the execution
712 The engine to use for the execution
718 block : boolean
713 block : boolean
719 If False, this method will return the actual result. If False,
714 If False, this method will return the actual result. If False,
720 a `PendingResult` is returned which can be used to get the result
715 a `PendingResult` is returned which can be used to get the result
721 at a later time.
716 at a later time.
722 """
717 """
723 targets, block = self._findTargetsAndBlock(targets, block)
718 targets, block = self._findTargetsAndBlock(targets, block)
724 return self._blockFromThread(self.smultiengine.clear_queue, targets=targets, block=block)
719 return self._blockFromThread(self.smultiengine.clear_queue, targets=targets, block=block)
725
720
726 def queue_status(self, targets=None, block=None):
721 def queue_status(self, targets=None, block=None):
727 """
722 """
728 Get the status of an engines queue.
723 Get the status of an engines queue.
729
724
730 :Parameters:
725 :Parameters:
731 targets : id or list of ids
726 targets : id or list of ids
732 The engine to use for the execution
727 The engine to use for the execution
733 block : boolean
728 block : boolean
734 If False, this method will return the actual result. If False,
729 If False, this method will return the actual result. If False,
735 a `PendingResult` is returned which can be used to get the result
730 a `PendingResult` is returned which can be used to get the result
736 at a later time.
731 at a later time.
737 """
732 """
738 targets, block = self._findTargetsAndBlock(targets, block)
733 targets, block = self._findTargetsAndBlock(targets, block)
739 return self._blockFromThread(self.smultiengine.queue_status, targets=targets, block=block)
734 return self._blockFromThread(self.smultiengine.queue_status, targets=targets, block=block)
740
735
741 def set_properties(self, properties, targets=None, block=None):
736 def set_properties(self, properties, targets=None, block=None):
742 warnings.warn(_prop_warn)
737 warnings.warn(_prop_warn)
743 targets, block = self._findTargetsAndBlock(targets, block)
738 targets, block = self._findTargetsAndBlock(targets, block)
744 return self._blockFromThread(self.smultiengine.set_properties, properties, targets=targets, block=block)
739 return self._blockFromThread(self.smultiengine.set_properties, properties, targets=targets, block=block)
745
740
746 def get_properties(self, keys=None, targets=None, block=None):
741 def get_properties(self, keys=None, targets=None, block=None):
747 warnings.warn(_prop_warn)
742 warnings.warn(_prop_warn)
748 targets, block = self._findTargetsAndBlock(targets, block)
743 targets, block = self._findTargetsAndBlock(targets, block)
749 return self._blockFromThread(self.smultiengine.get_properties, keys, targets=targets, block=block)
744 return self._blockFromThread(self.smultiengine.get_properties, keys, targets=targets, block=block)
750
745
751 def has_properties(self, keys, targets=None, block=None):
746 def has_properties(self, keys, targets=None, block=None):
752 warnings.warn(_prop_warn)
747 warnings.warn(_prop_warn)
753 targets, block = self._findTargetsAndBlock(targets, block)
748 targets, block = self._findTargetsAndBlock(targets, block)
754 return self._blockFromThread(self.smultiengine.has_properties, keys, targets=targets, block=block)
749 return self._blockFromThread(self.smultiengine.has_properties, keys, targets=targets, block=block)
755
750
756 def del_properties(self, keys, targets=None, block=None):
751 def del_properties(self, keys, targets=None, block=None):
757 warnings.warn(_prop_warn)
752 warnings.warn(_prop_warn)
758 targets, block = self._findTargetsAndBlock(targets, block)
753 targets, block = self._findTargetsAndBlock(targets, block)
759 return self._blockFromThread(self.smultiengine.del_properties, keys, targets=targets, block=block)
754 return self._blockFromThread(self.smultiengine.del_properties, keys, targets=targets, block=block)
760
755
761 def clear_properties(self, targets=None, block=None):
756 def clear_properties(self, targets=None, block=None):
762 warnings.warn(_prop_warn)
757 warnings.warn(_prop_warn)
763 targets, block = self._findTargetsAndBlock(targets, block)
758 targets, block = self._findTargetsAndBlock(targets, block)
764 return self._blockFromThread(self.smultiengine.clear_properties, targets=targets, block=block)
759 return self._blockFromThread(self.smultiengine.clear_properties, targets=targets, block=block)
765
760
766 #---------------------------------------------------------------------------
761 #---------------------------------------------------------------------------
767 # IMultiEngine related methods
762 # IMultiEngine related methods
768 #---------------------------------------------------------------------------
763 #---------------------------------------------------------------------------
769
764
770 def get_ids(self):
765 def get_ids(self):
771 """
766 """
772 Returns the ids of currently registered engines.
767 Returns the ids of currently registered engines.
773 """
768 """
774 result = blockingCallFromThread(self.smultiengine.get_ids)
769 result = blockingCallFromThread(self.smultiengine.get_ids)
775 return result
770 return result
776
771
777 #---------------------------------------------------------------------------
772 #---------------------------------------------------------------------------
778 # IMultiEngineCoordinator
773 # IMultiEngineCoordinator
779 #---------------------------------------------------------------------------
774 #---------------------------------------------------------------------------
780
775
781 def scatter(self, key, seq, dist='b', flatten=False, targets=None, block=None):
776 def scatter(self, key, seq, dist='b', flatten=False, targets=None, block=None):
782 """
777 """
783 Partition a Python sequence and send the partitions to a set of engines.
778 Partition a Python sequence and send the partitions to a set of engines.
784 """
779 """
785 targets, block = self._findTargetsAndBlock(targets, block)
780 targets, block = self._findTargetsAndBlock(targets, block)
786 return self._blockFromThread(self.smultiengine.scatter, key, seq,
781 return self._blockFromThread(self.smultiengine.scatter, key, seq,
787 dist, flatten, targets=targets, block=block)
782 dist, flatten, targets=targets, block=block)
788
783
789 def gather(self, key, dist='b', targets=None, block=None):
784 def gather(self, key, dist='b', targets=None, block=None):
790 """
785 """
791 Gather a partitioned sequence on a set of engines as a single local seq.
786 Gather a partitioned sequence on a set of engines as a single local seq.
792 """
787 """
793 targets, block = self._findTargetsAndBlock(targets, block)
788 targets, block = self._findTargetsAndBlock(targets, block)
794 return self._blockFromThread(self.smultiengine.gather, key, dist,
789 return self._blockFromThread(self.smultiengine.gather, key, dist,
795 targets=targets, block=block)
790 targets=targets, block=block)
796
791
797 def raw_map(self, func, seq, dist='b', targets=None, block=None):
792 def raw_map(self, func, seq, dist='b', targets=None, block=None):
798 """
793 """
799 A parallelized version of Python's builtin map.
794 A parallelized version of Python's builtin map.
800
795
801 This has a slightly different syntax than the builtin `map`.
796 This has a slightly different syntax than the builtin `map`.
802 This is needed because we need to have keyword arguments and thus
797 This is needed because we need to have keyword arguments and thus
803 can't use *args to capture all the sequences. Instead, they must
798 can't use *args to capture all the sequences. Instead, they must
804 be passed in a list or tuple.
799 be passed in a list or tuple.
805
800
806 raw_map(func, seqs) -> map(func, seqs[0], seqs[1], ...)
801 raw_map(func, seqs) -> map(func, seqs[0], seqs[1], ...)
807
802
808 Most users will want to use parallel functions or the `mapper`
803 Most users will want to use parallel functions or the `mapper`
809 and `map` methods for an API that follows that of the builtin
804 and `map` methods for an API that follows that of the builtin
810 `map`.
805 `map`.
811 """
806 """
812 targets, block = self._findTargetsAndBlock(targets, block)
807 targets, block = self._findTargetsAndBlock(targets, block)
813 return self._blockFromThread(self.smultiengine.raw_map, func, seq,
808 return self._blockFromThread(self.smultiengine.raw_map, func, seq,
814 dist, targets=targets, block=block)
809 dist, targets=targets, block=block)
815
810
816 def map(self, func, *sequences):
811 def map(self, func, *sequences):
817 """
812 """
818 A parallel version of Python's builtin `map` function.
813 A parallel version of Python's builtin `map` function.
819
814
820 This method applies a function to sequences of arguments. It
815 This method applies a function to sequences of arguments. It
821 follows the same syntax as the builtin `map`.
816 follows the same syntax as the builtin `map`.
822
817
823 This method creates a mapper objects by calling `self.mapper` with
818 This method creates a mapper objects by calling `self.mapper` with
824 no arguments and then uses that mapper to do the mapping. See
819 no arguments and then uses that mapper to do the mapping. See
825 the documentation of `mapper` for more details.
820 the documentation of `mapper` for more details.
826 """
821 """
827 return self.mapper().map(func, *sequences)
822 return self.mapper().map(func, *sequences)
828
823
829 def mapper(self, dist='b', targets='all', block=None):
824 def mapper(self, dist='b', targets='all', block=None):
830 """
825 """
831 Create a mapper object that has a `map` method.
826 Create a mapper object that has a `map` method.
832
827
833 This method returns an object that implements the `IMapper`
828 This method returns an object that implements the `IMapper`
834 interface. This method is a factory that is used to control how
829 interface. This method is a factory that is used to control how
835 the map happens.
830 the map happens.
836
831
837 :Parameters:
832 :Parameters:
838 dist : str
833 dist : str
839 What decomposition to use, 'b' is the only one supported
834 What decomposition to use, 'b' is the only one supported
840 currently
835 currently
841 targets : str, int, sequence of ints
836 targets : str, int, sequence of ints
842 Which engines to use for the map
837 Which engines to use for the map
843 block : boolean
838 block : boolean
844 Should calls to `map` block or not
839 Should calls to `map` block or not
845 """
840 """
846 return MultiEngineMapper(self, dist, targets, block)
841 return MultiEngineMapper(self, dist, targets, block)
847
842
848 def parallel(self, dist='b', targets=None, block=None):
843 def parallel(self, dist='b', targets=None, block=None):
849 """
844 """
850 A decorator that turns a function into a parallel function.
845 A decorator that turns a function into a parallel function.
851
846
852 This can be used as:
847 This can be used as:
853
848
854 @parallel()
849 @parallel()
855 def f(x, y)
850 def f(x, y)
856 ...
851 ...
857
852
858 f(range(10), range(10))
853 f(range(10), range(10))
859
854
860 This causes f(0,0), f(1,1), ... to be called in parallel.
855 This causes f(0,0), f(1,1), ... to be called in parallel.
861
856
862 :Parameters:
857 :Parameters:
863 dist : str
858 dist : str
864 What decomposition to use, 'b' is the only one supported
859 What decomposition to use, 'b' is the only one supported
865 currently
860 currently
866 targets : str, int, sequence of ints
861 targets : str, int, sequence of ints
867 Which engines to use for the map
862 Which engines to use for the map
868 block : boolean
863 block : boolean
869 Should calls to `map` block or not
864 Should calls to `map` block or not
870 """
865 """
871 targets, block = self._findTargetsAndBlock(targets, block)
866 targets, block = self._findTargetsAndBlock(targets, block)
872 mapper = self.mapper(dist, targets, block)
867 mapper = self.mapper(dist, targets, block)
873 pf = ParallelFunction(mapper)
868 pf = ParallelFunction(mapper)
874 return pf
869 return pf
875
870
876 #---------------------------------------------------------------------------
871 #---------------------------------------------------------------------------
877 # IMultiEngineExtras
872 # IMultiEngineExtras
878 #---------------------------------------------------------------------------
873 #---------------------------------------------------------------------------
879
874
880 def zip_pull(self, keys, targets=None, block=None):
875 def zip_pull(self, keys, targets=None, block=None):
881 targets, block = self._findTargetsAndBlock(targets, block)
876 targets, block = self._findTargetsAndBlock(targets, block)
882 return self._blockFromThread(self.smultiengine.zip_pull, keys,
877 return self._blockFromThread(self.smultiengine.zip_pull, keys,
883 targets=targets, block=block)
878 targets=targets, block=block)
884
879
885 def run(self, filename, targets=None, block=None):
880 def run(self, filename, targets=None, block=None):
886 """
881 """
887 Run a Python code in a file on the engines.
882 Run a Python code in a file on the engines.
888
883
889 :Parameters:
884 :Parameters:
890 filename : str
885 filename : str
891 The name of the local file to run
886 The name of the local file to run
892 targets : id or list of ids
887 targets : id or list of ids
893 The engine to use for the execution
888 The engine to use for the execution
894 block : boolean
889 block : boolean
895 If False, this method will return the actual result. If False,
890 If False, this method will return the actual result. If False,
896 a `PendingResult` is returned which can be used to get the result
891 a `PendingResult` is returned which can be used to get the result
897 at a later time.
892 at a later time.
898 """
893 """
899 targets, block = self._findTargetsAndBlock(targets, block)
894 targets, block = self._findTargetsAndBlock(targets, block)
900 return self._blockFromThread(self.smultiengine.run, filename,
895 return self._blockFromThread(self.smultiengine.run, filename,
901 targets=targets, block=block)
896 targets=targets, block=block)
902
897
903 def benchmark(self, push_size=10000):
898 def benchmark(self, push_size=10000):
904 """
899 """
905 Run performance benchmarks for the current IPython cluster.
900 Run performance benchmarks for the current IPython cluster.
906
901
907 This method tests both the latency of sending command and data to the
902 This method tests both the latency of sending command and data to the
908 engines as well as the throughput of sending large objects to the
903 engines as well as the throughput of sending large objects to the
909 engines using push. The latency is measured by having one or more
904 engines using push. The latency is measured by having one or more
910 engines execute the command 'pass'. The throughput is measure by
905 engines execute the command 'pass'. The throughput is measure by
911 sending an NumPy array of size `push_size` to one or more engines.
906 sending an NumPy array of size `push_size` to one or more engines.
912
907
913 These benchmarks will vary widely on different hardware and networks
908 These benchmarks will vary widely on different hardware and networks
914 and thus can be used to get an idea of the performance characteristics
909 and thus can be used to get an idea of the performance characteristics
915 of a particular configuration of an IPython controller and engines.
910 of a particular configuration of an IPython controller and engines.
916
911
917 This function is not testable within our current testing framework.
912 This function is not testable within our current testing framework.
918 """
913 """
919 import timeit, __builtin__
914 import timeit, __builtin__
920 __builtin__._mec_self = self
915 __builtin__._mec_self = self
921 benchmarks = {}
916 benchmarks = {}
922 repeat = 3
917 repeat = 3
923 count = 10
918 count = 10
924
919
925 timer = timeit.Timer('_mec_self.execute("pass",0)')
920 timer = timeit.Timer('_mec_self.execute("pass",0)')
926 result = 1000*min(timer.repeat(repeat,count))/count
921 result = 1000*min(timer.repeat(repeat,count))/count
927 benchmarks['single_engine_latency'] = (result,'msec')
922 benchmarks['single_engine_latency'] = (result,'msec')
928
923
929 timer = timeit.Timer('_mec_self.execute("pass")')
924 timer = timeit.Timer('_mec_self.execute("pass")')
930 result = 1000*min(timer.repeat(repeat,count))/count
925 result = 1000*min(timer.repeat(repeat,count))/count
931 benchmarks['all_engine_latency'] = (result,'msec')
926 benchmarks['all_engine_latency'] = (result,'msec')
932
927
933 try:
928 try:
934 import numpy as np
929 import numpy as np
935 except:
930 except:
936 pass
931 pass
937 else:
932 else:
938 timer = timeit.Timer(
933 timer = timeit.Timer(
939 "_mec_self.push(d)",
934 "_mec_self.push(d)",
940 "import numpy as np; d = dict(a=np.zeros(%r,dtype='float64'))" % push_size
935 "import numpy as np; d = dict(a=np.zeros(%r,dtype='float64'))" % push_size
941 )
936 )
942 result = min(timer.repeat(repeat,count))/count
937 result = min(timer.repeat(repeat,count))/count
943 benchmarks['all_engine_push'] = (1e-6*push_size*8/result, 'MB/sec')
938 benchmarks['all_engine_push'] = (1e-6*push_size*8/result, 'MB/sec')
944
939
945 try:
940 try:
946 import numpy as np
941 import numpy as np
947 except:
942 except:
948 pass
943 pass
949 else:
944 else:
950 timer = timeit.Timer(
945 timer = timeit.Timer(
951 "_mec_self.push(d,0)",
946 "_mec_self.push(d,0)",
952 "import numpy as np; d = dict(a=np.zeros(%r,dtype='float64'))" % push_size
947 "import numpy as np; d = dict(a=np.zeros(%r,dtype='float64'))" % push_size
953 )
948 )
954 result = min(timer.repeat(repeat,count))/count
949 result = min(timer.repeat(repeat,count))/count
955 benchmarks['single_engine_push'] = (1e-6*push_size*8/result, 'MB/sec')
950 benchmarks['single_engine_push'] = (1e-6*push_size*8/result, 'MB/sec')
956
951
957 return benchmarks
952 return benchmarks
958
953
959
954
960 components.registerAdapter(FullBlockingMultiEngineClient,
955 components.registerAdapter(FullBlockingMultiEngineClient,
961 IFullSynchronousMultiEngine, IFullBlockingMultiEngineClient)
956 IFullSynchronousMultiEngine, IFullBlockingMultiEngineClient)
962
957
963
958
964
959
965
960
@@ -1,300 +1,300 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """IPython Test Suite Runner.
2 """IPython Test Suite Runner.
3
3
4 This module provides a main entry point to a user script to test IPython
4 This module provides a main entry point to a user script to test IPython
5 itself from the command line. There are two ways of running this script:
5 itself from the command line. There are two ways of running this script:
6
6
7 1. With the syntax `iptest all`. This runs our entire test suite by
7 1. With the syntax `iptest all`. This runs our entire test suite by
8 calling this script (with different arguments) or trial recursively. This
8 calling this script (with different arguments) or trial recursively. This
9 causes modules and package to be tested in different processes, using nose
9 causes modules and package to be tested in different processes, using nose
10 or trial where appropriate.
10 or trial where appropriate.
11 2. With the regular nose syntax, like `iptest -vvs IPython`. In this form
11 2. With the regular nose syntax, like `iptest -vvs IPython`. In this form
12 the script simply calls nose, but with special command line flags and
12 the script simply calls nose, but with special command line flags and
13 plugins loaded.
13 plugins loaded.
14
14
15 For now, this script requires that both nose and twisted are installed. This
15 For now, this script requires that both nose and twisted are installed. This
16 will change in the future.
16 will change in the future.
17 """
17 """
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Module imports
20 # Module imports
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 import os
23 import os
24 import os.path as path
24 import os.path as path
25 import sys
25 import sys
26 import subprocess
26 import subprocess
27 import time
27 import time
28 import warnings
28 import warnings
29
29
30 import nose.plugins.builtin
30 import nose.plugins.builtin
31 from nose.core import TestProgram
31 from nose.core import TestProgram
32
32
33 from IPython.platutils import find_cmd
33 from IPython.platutils import find_cmd
34 from IPython.testing.plugin.ipdoctest import IPythonDoctest
34 from IPython.testing.plugin.ipdoctest import IPythonDoctest
35
35
36 pjoin = path.join
36 pjoin = path.join
37
37
38 #-----------------------------------------------------------------------------
38 #-----------------------------------------------------------------------------
39 # Logic for skipping doctests
39 # Logic for skipping doctests
40 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
41
41
42 def test_for(mod):
42 def test_for(mod):
43 """Test to see if mod is importable."""
43 """Test to see if mod is importable."""
44 try:
44 try:
45 __import__(mod)
45 __import__(mod)
46 except ImportError:
46 except ImportError:
47 return False
47 return False
48 else:
48 else:
49 return True
49 return True
50
50
51 have_curses = test_for('_curses')
51 have_curses = test_for('_curses')
52 have_wx = test_for('wx')
52 have_wx = test_for('wx')
53 have_zi = test_for('zope.interface')
53 have_zi = test_for('zope.interface')
54 have_twisted = test_for('twisted')
54 have_twisted = test_for('twisted')
55 have_foolscap = test_for('foolscap')
55 have_foolscap = test_for('foolscap')
56 have_objc = test_for('objc')
56 have_objc = test_for('objc')
57 have_pexpect = test_for('pexpect')
57 have_pexpect = test_for('pexpect')
58
58
59 # For the IPythonDoctest plugin, we need to exclude certain patterns that cause
59 # For the IPythonDoctest plugin, we need to exclude certain patterns that cause
60 # testing problems. We should strive to minimize the number of skipped
60 # testing problems. We should strive to minimize the number of skipped
61 # modules, since this means untested code. As the testing machinery
61 # modules, since this means untested code. As the testing machinery
62 # solidifies, this list should eventually become empty.
62 # solidifies, this list should eventually become empty.
63 EXCLUDE = [pjoin('IPython', 'external'),
63 EXCLUDE = [pjoin('IPython', 'external'),
64 pjoin('IPython', 'frontend', 'process', 'winprocess.py'),
64 pjoin('IPython', 'frontend', 'process', 'winprocess.py'),
65 pjoin('IPython_doctest_plugin'),
65 pjoin('IPython_doctest_plugin'),
66 pjoin('IPython', 'Gnuplot'),
66 pjoin('IPython', 'Gnuplot'),
67 pjoin('IPython', 'Extensions', 'ipy_'),
67 pjoin('IPython', 'Extensions', 'ipy_'),
68 pjoin('IPython', 'Extensions', 'clearcmd'),
68 pjoin('IPython', 'Extensions', 'clearcmd'),
69 pjoin('IPython', 'Extensions', 'PhysicalQInteractive'),
69 pjoin('IPython', 'Extensions', 'PhysicalQInteractive'),
70 pjoin('IPython', 'Extensions', 'scitedirector'),
70 pjoin('IPython', 'Extensions', 'scitedirector'),
71 pjoin('IPython', 'Extensions', 'numeric_formats'),
71 pjoin('IPython', 'Extensions', 'numeric_formats'),
72 pjoin('IPython', 'testing', 'attic'),
72 pjoin('IPython', 'testing', 'attic'),
73 pjoin('IPython', 'testing', 'tutils'),
73 pjoin('IPython', 'testing', 'tutils'),
74 pjoin('IPython', 'testing', 'tools'),
74 pjoin('IPython', 'testing', 'tools'),
75 pjoin('IPython', 'testing', 'mkdoctests')
75 pjoin('IPython', 'testing', 'mkdoctests')
76 ]
76 ]
77
77
78 if not have_wx:
78 if not have_wx:
79 EXCLUDE.append(pjoin('IPython', 'Extensions', 'igrid'))
79 EXCLUDE.append(pjoin('IPython', 'Extensions', 'igrid'))
80 EXCLUDE.append(pjoin('IPython', 'gui'))
80 EXCLUDE.append(pjoin('IPython', 'gui'))
81 EXCLUDE.append(pjoin('IPython', 'frontend', 'wx'))
81 EXCLUDE.append(pjoin('IPython', 'frontend', 'wx'))
82
82
83 if not have_objc:
83 if not have_objc:
84 EXCLUDE.append(pjoin('IPython', 'frontend', 'cocoa'))
84 EXCLUDE.append(pjoin('IPython', 'frontend', 'cocoa'))
85
85
86 if not have_curses:
86 if not have_curses:
87 EXCLUDE.append(pjoin('IPython', 'Extensions', 'ibrowse'))
87 EXCLUDE.append(pjoin('IPython', 'Extensions', 'ibrowse'))
88
88
89 if not sys.platform == 'win32':
89 if not sys.platform == 'win32':
90 EXCLUDE.append(pjoin('IPython', 'platutils_win32'))
90 EXCLUDE.append(pjoin('IPython', 'platutils_win32'))
91
91
92 # These have to be skipped on win32 because the use echo, rm, cd, etc.
92 # These have to be skipped on win32 because the use echo, rm, cd, etc.
93 # See ticket https://bugs.launchpad.net/bugs/366982
93 # See ticket https://bugs.launchpad.net/bugs/366982
94 if sys.platform == 'win32':
94 if sys.platform == 'win32':
95 EXCLUDE.append(pjoin('IPython', 'testing', 'plugin', 'test_exampleip'))
95 EXCLUDE.append(pjoin('IPython', 'testing', 'plugin', 'test_exampleip'))
96 EXCLUDE.append(pjoin('IPython', 'testing', 'plugin', 'dtexample'))
96 EXCLUDE.append(pjoin('IPython', 'testing', 'plugin', 'dtexample'))
97
97
98 if not os.name == 'posix':
98 if not os.name == 'posix':
99 EXCLUDE.append(pjoin('IPython', 'platutils_posix'))
99 EXCLUDE.append(pjoin('IPython', 'platutils_posix'))
100
100
101 if not have_pexpect:
101 if not have_pexpect:
102 EXCLUDE.append(pjoin('IPython', 'irunner'))
102 EXCLUDE.append(pjoin('IPython', 'irunner'))
103
103
104 # This is needed for the reg-exp to match on win32 in the ipdoctest plugin.
104 # This is needed for the reg-exp to match on win32 in the ipdoctest plugin.
105 if sys.platform == 'win32':
105 if sys.platform == 'win32':
106 EXCLUDE = [s.replace('\\','\\\\') for s in EXCLUDE]
106 EXCLUDE = [s.replace('\\','\\\\') for s in EXCLUDE]
107
107
108
108
109 #-----------------------------------------------------------------------------
109 #-----------------------------------------------------------------------------
110 # Functions and classes
110 # Functions and classes
111 #-----------------------------------------------------------------------------
111 #-----------------------------------------------------------------------------
112
112
113 def run_iptest():
113 def run_iptest():
114 """Run the IPython test suite using nose.
114 """Run the IPython test suite using nose.
115
115
116 This function is called when this script is **not** called with the form
116 This function is called when this script is **not** called with the form
117 `iptest all`. It simply calls nose with appropriate command line flags
117 `iptest all`. It simply calls nose with appropriate command line flags
118 and accepts all of the standard nose arguments.
118 and accepts all of the standard nose arguments.
119 """
119 """
120
120
121 warnings.filterwarnings('ignore',
121 warnings.filterwarnings('ignore',
122 'This will be removed soon. Use IPython.testing.util instead')
122 'This will be removed soon. Use IPython.testing.util instead')
123
123
124 argv = sys.argv + [
124 argv = sys.argv + [
125 # Loading ipdoctest causes problems with Twisted.
125 # Loading ipdoctest causes problems with Twisted.
126 # I am removing this as a temporary fix to get the
126 # I am removing this as a temporary fix to get the
127 # test suite back into working shape. Our nose
127 # test suite back into working shape. Our nose
128 # plugin needs to be gone through with a fine
128 # plugin needs to be gone through with a fine
129 # toothed comb to find what is causing the problem.
129 # toothed comb to find what is causing the problem.
130 '--with-ipdoctest',
130 '--with-ipdoctest',
131 '--ipdoctest-tests','--ipdoctest-extension=txt',
131 '--ipdoctest-tests','--ipdoctest-extension=txt',
132 '--detailed-errors',
132 '--detailed-errors',
133
133
134 # We add --exe because of setuptools' imbecility (it
134 # We add --exe because of setuptools' imbecility (it
135 # blindly does chmod +x on ALL files). Nose does the
135 # blindly does chmod +x on ALL files). Nose does the
136 # right thing and it tries to avoid executables,
136 # right thing and it tries to avoid executables,
137 # setuptools unfortunately forces our hand here. This
137 # setuptools unfortunately forces our hand here. This
138 # has been discussed on the distutils list and the
138 # has been discussed on the distutils list and the
139 # setuptools devs refuse to fix this problem!
139 # setuptools devs refuse to fix this problem!
140 '--exe',
140 '--exe',
141 ]
141 ]
142
142
143 # Detect if any tests were required by explicitly calling an IPython
143 # Detect if any tests were required by explicitly calling an IPython
144 # submodule or giving a specific path
144 # submodule or giving a specific path
145 has_tests = False
145 has_tests = False
146 for arg in sys.argv:
146 for arg in sys.argv:
147 if 'IPython' in arg or arg.endswith('.py') or \
147 if 'IPython' in arg or arg.endswith('.py') or \
148 (':' in arg and '.py' in arg):
148 (':' in arg and '.py' in arg):
149 has_tests = True
149 has_tests = True
150 break
150 break
151
151
152 # If nothing was specifically requested, test full IPython
152 # If nothing was specifically requested, test full IPython
153 if not has_tests:
153 if not has_tests:
154 argv.append('IPython')
154 argv.append('IPython')
155
155
156 # Construct list of plugins, omitting the existing doctest plugin, which
156 # Construct list of plugins, omitting the existing doctest plugin, which
157 # ours replaces (and extends).
157 # ours replaces (and extends).
158 plugins = [IPythonDoctest(EXCLUDE)]
158 plugins = [IPythonDoctest(EXCLUDE)]
159 for p in nose.plugins.builtin.plugins:
159 for p in nose.plugins.builtin.plugins:
160 plug = p()
160 plug = p()
161 if plug.name == 'doctest':
161 if plug.name == 'doctest':
162 continue
162 continue
163
163
164 #print '*** adding plugin:',plug.name # dbg
164 #print '*** adding plugin:',plug.name # dbg
165 plugins.append(plug)
165 plugins.append(plug)
166
166
167 TestProgram(argv=argv,plugins=plugins)
167 TestProgram(argv=argv,plugins=plugins)
168
168
169
169
170 class IPTester(object):
170 class IPTester(object):
171 """Call that calls iptest or trial in a subprocess.
171 """Call that calls iptest or trial in a subprocess.
172 """
172 """
173 def __init__(self,runner='iptest',params=None):
173 def __init__(self,runner='iptest',params=None):
174 """ """
174 """ """
175 if runner == 'iptest':
175 if runner == 'iptest':
176 self.runner = ['iptest','-v']
176 self.runner = ['iptest','-v']
177 else:
177 else:
178 self.runner = [find_cmd('trial')]
178 self.runner = [find_cmd('trial')]
179 if params is None:
179 if params is None:
180 params = []
180 params = []
181 if isinstance(params,str):
181 if isinstance(params,str):
182 params = [params]
182 params = [params]
183 self.params = params
183 self.params = params
184
184
185 # Assemble call
185 # Assemble call
186 self.call_args = self.runner+self.params
186 self.call_args = self.runner+self.params
187
187
188 def run(self):
188 def run(self):
189 """Run the stored commands"""
189 """Run the stored commands"""
190 return subprocess.call(self.call_args)
190 return subprocess.call(self.call_args)
191
191
192
192
193 def make_runners():
193 def make_runners():
194 """Define the modules and packages that need to be tested.
194 """Define the modules and packages that need to be tested.
195 """
195 """
196
196
197 # This omits additional top-level modules that should not be doctested.
197 # This omits additional top-level modules that should not be doctested.
198 # XXX: Shell.py is also ommited because of a bug in the skip_doctest
198 # XXX: Shell.py is also ommited because of a bug in the skip_doctest
199 # decorator. See ticket https://bugs.launchpad.net/bugs/366209
199 # decorator. See ticket https://bugs.launchpad.net/bugs/366209
200 top_mod = \
200 top_mod = \
201 ['background_jobs.py', 'ColorANSI.py', 'completer.py', 'ConfigLoader.py',
201 ['background_jobs.py', 'coloransi.py', 'completer.py', 'ConfigLoader.py',
202 'CrashHandler.py', 'Debugger.py', 'deep_reload.py', 'demo.py',
202 'CrashHandler.py', 'Debugger.py', 'deep_reload.py', 'demo.py',
203 'DPyGetOpt.py', 'dtutils.py', 'excolors.py', 'FakeModule.py',
203 'DPyGetOpt.py', 'dtutils.py', 'excolors.py', 'FakeModule.py',
204 'generics.py', 'genutils.py', 'history.py', 'hooks.py', 'ipapi.py',
204 'generics.py', 'genutils.py', 'history.py', 'hooks.py', 'ipapi.py',
205 'iplib.py', 'ipmaker.py', 'ipstruct.py', 'Itpl.py',
205 'iplib.py', 'ipmaker.py', 'ipstruct.py', 'Itpl.py',
206 'Logger.py', 'macro.py', 'Magic.py', 'OInspect.py',
206 'Logger.py', 'macro.py', 'Magic.py', 'OInspect.py',
207 'OutputTrap.py', 'platutils.py', 'prefilter.py', 'Prompts.py',
207 'OutputTrap.py', 'platutils.py', 'prefilter.py', 'Prompts.py',
208 'PyColorize.py', 'Release.py', 'rlineimpl.py', 'shadowns.py',
208 'PyColorize.py', 'Release.py', 'rlineimpl.py', 'shadowns.py',
209 'shellglobals.py', 'strdispatch.py', 'twshell.py',
209 'shellglobals.py', 'strdispatch.py', 'twshell.py',
210 'ultraTB.py', 'upgrade_dir.py', 'usage.py', 'wildcard.py',
210 'ultraTB.py', 'upgrade_dir.py', 'usage.py', 'wildcard.py',
211 # See note above for why this is skipped
211 # See note above for why this is skipped
212 # 'Shell.py',
212 # 'Shell.py',
213 'winconsole.py']
213 'winconsole.py']
214
214
215 if have_pexpect:
215 if have_pexpect:
216 top_mod.append('irunner.py')
216 top_mod.append('irunner.py')
217
217
218 if sys.platform == 'win32':
218 if sys.platform == 'win32':
219 top_mod.append('platutils_win32.py')
219 top_mod.append('platutils_win32.py')
220 elif os.name == 'posix':
220 elif os.name == 'posix':
221 top_mod.append('platutils_posix.py')
221 top_mod.append('platutils_posix.py')
222 else:
222 else:
223 top_mod.append('platutils_dummy.py')
223 top_mod.append('platutils_dummy.py')
224
224
225 # These are tested by nose, so skip IPython.kernel
225 # These are tested by nose, so skip IPython.kernel
226 top_pack = ['config','Extensions','frontend',
226 top_pack = ['config','Extensions','frontend',
227 'testing','tests','tools','UserConfig']
227 'testing','tests','tools','UserConfig']
228
228
229 if have_wx:
229 if have_wx:
230 top_pack.append('gui')
230 top_pack.append('gui')
231
231
232 modules = ['IPython.%s' % m[:-3] for m in top_mod ]
232 modules = ['IPython.%s' % m[:-3] for m in top_mod ]
233 packages = ['IPython.%s' % m for m in top_pack ]
233 packages = ['IPython.%s' % m for m in top_pack ]
234
234
235 # Make runners
235 # Make runners
236 runners = dict(zip(top_pack, [IPTester(params=v) for v in packages]))
236 runners = dict(zip(top_pack, [IPTester(params=v) for v in packages]))
237
237
238 # Test IPython.kernel using trial if twisted is installed
238 # Test IPython.kernel using trial if twisted is installed
239 if have_zi and have_twisted and have_foolscap:
239 if have_zi and have_twisted and have_foolscap:
240 runners['trial'] = IPTester('trial',['IPython'])
240 runners['trial'] = IPTester('trial',['IPython'])
241
241
242 runners['modules'] = IPTester(params=modules)
242 runners['modules'] = IPTester(params=modules)
243
243
244 return runners
244 return runners
245
245
246
246
247 def run_iptestall():
247 def run_iptestall():
248 """Run the entire IPython test suite by calling nose and trial.
248 """Run the entire IPython test suite by calling nose and trial.
249
249
250 This function constructs :class:`IPTester` instances for all IPython
250 This function constructs :class:`IPTester` instances for all IPython
251 modules and package and then runs each of them. This causes the modules
251 modules and package and then runs each of them. This causes the modules
252 and packages of IPython to be tested each in their own subprocess using
252 and packages of IPython to be tested each in their own subprocess using
253 nose or twisted.trial appropriately.
253 nose or twisted.trial appropriately.
254 """
254 """
255 runners = make_runners()
255 runners = make_runners()
256 # Run all test runners, tracking execution time
256 # Run all test runners, tracking execution time
257 failed = {}
257 failed = {}
258 t_start = time.time()
258 t_start = time.time()
259 for name,runner in runners.iteritems():
259 for name,runner in runners.iteritems():
260 print '*'*77
260 print '*'*77
261 print 'IPython test set:',name
261 print 'IPython test set:',name
262 res = runner.run()
262 res = runner.run()
263 if res:
263 if res:
264 failed[name] = res
264 failed[name] = res
265 t_end = time.time()
265 t_end = time.time()
266 t_tests = t_end - t_start
266 t_tests = t_end - t_start
267 nrunners = len(runners)
267 nrunners = len(runners)
268 nfail = len(failed)
268 nfail = len(failed)
269 # summarize results
269 # summarize results
270 print
270 print
271 print '*'*77
271 print '*'*77
272 print 'Ran %s test sets in %.3fs' % (nrunners, t_tests)
272 print 'Ran %s test sets in %.3fs' % (nrunners, t_tests)
273 print
273 print
274 if not failed:
274 if not failed:
275 print 'OK'
275 print 'OK'
276 else:
276 else:
277 # If anything went wrong, point out what command to rerun manually to
277 # If anything went wrong, point out what command to rerun manually to
278 # see the actual errors and individual summary
278 # see the actual errors and individual summary
279 print 'ERROR - %s out of %s test sets failed.' % (nfail, nrunners)
279 print 'ERROR - %s out of %s test sets failed.' % (nfail, nrunners)
280 for name in failed:
280 for name in failed:
281 failed_runner = runners[name]
281 failed_runner = runners[name]
282 print '-'*40
282 print '-'*40
283 print 'Runner failed:',name
283 print 'Runner failed:',name
284 print 'You may wish to rerun this one individually, with:'
284 print 'You may wish to rerun this one individually, with:'
285 print ' '.join(failed_runner.call_args)
285 print ' '.join(failed_runner.call_args)
286 print
286 print
287
287
288
288
289 def main():
289 def main():
290 if len(sys.argv) == 1:
290 if len(sys.argv) == 1:
291 run_iptestall()
291 run_iptestall()
292 else:
292 else:
293 if sys.argv[1] == 'all':
293 if sys.argv[1] == 'all':
294 run_iptestall()
294 run_iptestall()
295 else:
295 else:
296 run_iptest()
296 run_iptest()
297
297
298
298
299 if __name__ == '__main__':
299 if __name__ == '__main__':
300 main() No newline at end of file
300 main()
1 NO CONTENT: file renamed from IPython/ColorANSI.py to IPython/utils/coloransi.py
NO CONTENT: file renamed from IPython/ColorANSI.py to IPython/utils/coloransi.py
@@ -1,228 +1,239 b''
1 =============================
1 =============================
2 IPython module reorganization
2 IPython module reorganization
3 =============================
3 =============================
4
4
5 Currently, IPython has many top-level modules that serve many different purposes.
5 Currently, IPython has many top-level modules that serve many different purposes.
6 The lack of organization make it very difficult for developers to work on IPython
6 The lack of organization make it very difficult for developers to work on IPython
7 and understand its design. This document contains notes about how we will reorganize
7 and understand its design. This document contains notes about how we will reorganize
8 the modules into sub-packages.
8 the modules into sub-packages.
9
9
10 .. warning::
10 .. warning::
11
11
12 This effort will possibly break third party packages that use IPython as
12 This effort will possibly break third party packages that use IPython as
13 a library or hack on the IPython internals.
13 a library or hack on the IPython internals.
14
14
15 .. warning::
15 .. warning::
16
16
17 This effort will result in the removal from IPython of certain modules
17 This effort will result in the removal from IPython of certain modules
18 that are not used anymore, don't currently work, are unmaintained, etc.
18 that are not used anymore, don't currently work, are unmaintained, etc.
19
19
20
20
21 Current subpackges
21 Current subpackges
22 ==================
22 ==================
23
23
24 IPython currently has the following sub-packages:
24 IPython currently has the following sub-packages:
25
25
26 * :mod:`IPython.config`
26 * :mod:`IPython.config`
27
27
28 * :mod:`IPython.Extensions`
28 * :mod:`IPython.Extensions`
29
29
30 * :mod:`IPython.external`
30 * :mod:`IPython.external`
31
31
32 * :mod:`IPython.frontend`
32 * :mod:`IPython.frontend`
33
33
34 * :mod:`IPython.gui`
34 * :mod:`IPython.gui`
35
35
36 * :mod:`IPython.kernel`
36 * :mod:`IPython.kernel`
37
37
38 * :mod:`IPython.testing`
38 * :mod:`IPython.testing`
39
39
40 * :mod:`IPython.tests`
40 * :mod:`IPython.tests`
41
41
42 * :mod:`IPython.tools`
42 * :mod:`IPython.tools`
43
43
44 * :mod:`IPython.UserConfig`
44 * :mod:`IPython.UserConfig`
45
45
46 New Subpackages to be created
46 New Subpackages to be created
47 =============================
47 =============================
48
48
49 We propose to create the following new sub-packages:
49 We propose to create the following new sub-packages:
50
50
51 * :mod:`IPython.core`. This sub-package will contain the core of the IPython
51 * :mod:`IPython.core`. This sub-package will contain the core of the IPython
52 interpreter, but none of its extended capabilities.
52 interpreter, but none of its extended capabilities.
53
53
54 * :mod:`IPython.lib`. IPython has many extended capabilities that are not part
54 * :mod:`IPython.lib`. IPython has many extended capabilities that are not part
55 of the IPython core. These things will go here. Any better names than
55 of the IPython core. These things will go here. Any better names than
56 :mod:`IPython.lib`?
56 :mod:`IPython.lib`?
57
57
58 * :mod:`IPython.utils`. This sub-package will contain anything that might
58 * :mod:`IPython.utils`. This sub-package will contain anything that might
59 eventually be found in the Python standard library, like things in
59 eventually be found in the Python standard library, like things in
60 :mod:`genutils`. Each sub-module in this sub-package should contain
60 :mod:`genutils`. Each sub-module in this sub-package should contain
61 functions and classes that serve a single purpose.
61 functions and classes that serve a single purpose.
62
62
63 * :mod:`IPython.deathrow`. This is for code that is untested and/or rotting
63 * :mod:`IPython.deathrow`. This is for code that is untested and/or rotting
64 and needs to be removed from IPython. Eventually all this code will either
64 and needs to be removed from IPython. Eventually all this code will either
65 i) be revived by someone willing to maintain it with tests and docs and
65 i) be revived by someone willing to maintain it with tests and docs and
66 re-included into IPython or 2) be removed from IPython proper, but put into
66 re-included into IPython or 2) be removed from IPython proper, but put into
67 a separate top-level (not IPython) package that we keep around. No new code
67 a separate top-level (not IPython) package that we keep around. No new code
68 will be allowed here.
68 will be allowed here.
69
69
70 * :mod:`IPython.quarantine`. This is for code that doesn't meet IPython's
70 * :mod:`IPython.quarantine`. This is for code that doesn't meet IPython's
71 standards, but that we plan on keeping. To be moved out of this sub-package
71 standards, but that we plan on keeping. To be moved out of this sub-package
72 a module needs to have a maintainer, tests and documentation.
72 a module needs to have a maintainer, tests and documentation.
73
73
74 Prodecure
75 =========
76
77 1. Move the file to its new location with its new name.
78 2. Rename all import statements to reflect the change.
79 3. Run PyFlakes on each changes module.
80 3. Add tests/test_imports.py to test it.
81
82 Need to modify iptests to properly skip modules that are no longer top
83 level modules.
84
74 Where things will be moved
85 Where things will be moved
75 ==========================
86 ==========================
76
87
77 * :file:`ColorANSI.py`. Move to :file:`IPython/core/coloransi.py`. Maybe move to
88 * :file:`ColorANSI.py`. Move to :file:`IPython/core/coloransi.py`. Maybe move to
78 :mod:`IPython.lib` or :mod:`IPython.python`?
89 :mod:`IPython.lib` or :mod:`IPython.python`?
79
90
80 * :file:`ConfigLoader.py`. Move to :file:`IPython/config/configloader.py`.
91 * :file:`ConfigLoader.py`. Move to :file:`IPython/config/configloader.py`.
81
92
82 * :file:`CrashHandler.py`. Move to :file:`IPython/core/crashhandler`.
93 * :file:`CrashHandler.py`. Move to :file:`IPython/core/crashhandler`.
83
94
84 * :file:`DPyGetOpt.py`. Move to :mod:`IPython.sandbox` and replace with newer options parser.
95 * :file:`DPyGetOpt.py`. Move to :mod:`IPython.sandbox` and replace with newer options parser.
85
96
86 * :file:`Debugger.py`. Move to :file:`IPython/core/debugger.py`.
97 * :file:`Debugger.py`. Move to :file:`IPython/core/debugger.py`.
87
98
88 * :file:`Extensions`. This needs to be gone through separately. Minimally,
99 * :file:`Extensions`. This needs to be gone through separately. Minimally,
89 the package should be renamed to :file:`extensions`.
100 the package should be renamed to :file:`extensions`.
90
101
91 * :file:`FakeModule.py`. Move to :file:`IPython/core/fakemodule.py`.
102 * :file:`FakeModule.py`. Move to :file:`IPython/core/fakemodule.py`.
92
103
93 * :file:`Gnuplot2.py`. Move to :file:`IPython.sandbox`.
104 * :file:`Gnuplot2.py`. Move to :file:`IPython.sandbox`.
94
105
95 * :file:`GnuplotInteractive.py`. Move to :file:`IPython.sandbox`.
106 * :file:`GnuplotInteractive.py`. Move to :file:`IPython.sandbox`.
96
107
97 * :file:`GnuplotRuntime.py`. Move to :file:`IPython.sandbox`.
108 * :file:`GnuplotRuntime.py`. Move to :file:`IPython.sandbox`.
98
109
99 * :file:`Itpl.py`. Remove. Version already in :file:`IPython.external`.
110 * :file:`Itpl.py`. Remove. Version already in :file:`IPython.external`.
100
111
101 * :file:`Logger.py`. Move to :file:`IPython/core/logger.py`.
112 * :file:`Logger.py`. Move to :file:`IPython/core/logger.py`.
102
113
103 * :file:`Magic.py`. Move to :file:`IPython/core/magic.py`.
114 * :file:`Magic.py`. Move to :file:`IPython/core/magic.py`.
104
115
105 * :file:`OInspect.py`. Move to :file:`IPython/core/oinspect.py`.
116 * :file:`OInspect.py`. Move to :file:`IPython/core/oinspect.py`.
106
117
107 * :file:`OutputTrap.py`. Move to :file:`IPython/core/outputtrap.py`.
118 * :file:`OutputTrap.py`. Move to :file:`IPython/core/outputtrap.py`.
108
119
109 * :file:`Prompts.py`. Move to :file:`IPython/core/prompts.py` or
120 * :file:`Prompts.py`. Move to :file:`IPython/core/prompts.py` or
110 :file:`IPython/frontend/prompts.py`.
121 :file:`IPython/frontend/prompts.py`.
111
122
112 * :file:`PyColorize.py`. Replace with pygments? If not, move to
123 * :file:`PyColorize.py`. Replace with pygments? If not, move to
113 :file:`IPython/core/pycolorize.py`. Maybe move to :mod:`IPython.lib` or
124 :file:`IPython/core/pycolorize.py`. Maybe move to :mod:`IPython.lib` or
114 :mod:`IPython.python`?
125 :mod:`IPython.python`?
115
126
116 * :file:`Release.py`. Move to ??? or remove?
127 * :file:`Release.py`. Move to ??? or remove?
117
128
118 * :file:`Shell.py`. Move to :file:`IPython.core.shell.py` or
129 * :file:`Shell.py`. Move to :file:`IPython.core.shell.py` or
119 :file:`IPython/frontend/shell.py`.
130 :file:`IPython/frontend/shell.py`.
120
131
121 * :file:`UserConfig`. Move to a subdirectory of :file:`IPython.config`.
132 * :file:`UserConfig`. Move to a subdirectory of :file:`IPython.config`.
122
133
123 * :file:`background_jobs.py`. Move to :file:`IPython/lib/backgroundjobs.py`.
134 * :file:`background_jobs.py`. Move to :file:`IPython/lib/backgroundjobs.py`.
124
135
125 * :file:`completer.py`. Move to :file:`IPython/core/completer.py`.
136 * :file:`completer.py`. Move to :file:`IPython/core/completer.py`.
126
137
127 * :file:`config`. Good where it is!
138 * :file:`config`. Good where it is!
128
139
129 * :file:`deep_reload.py`. Move to :file:`IPython/lib/deepreload.py`.
140 * :file:`deep_reload.py`. Move to :file:`IPython/lib/deepreload.py`.
130
141
131 * :file:`demo.py`. Move to :file:`IPython/lib/demo.py`.
142 * :file:`demo.py`. Move to :file:`IPython/lib/demo.py`.
132
143
133 * :file:`dtutils.py`. Remove or move to :file:`IPython.testing` or
144 * :file:`dtutils.py`. Remove or move to :file:`IPython.testing` or
134 :file:`IPython.lib`.
145 :file:`IPython.lib`.
135
146
136 * :file:`excolors.py`. Move to :file:`IPython.core` or :file:`IPython.config`.
147 * :file:`excolors.py`. Move to :file:`IPython.core` or :file:`IPython.config`.
137 Maybe move to :mod:`IPython.lib` or :mod:`IPython.python`?
148 Maybe move to :mod:`IPython.lib` or :mod:`IPython.python`?
138
149
139 * :file:`external`. Good where it is!
150 * :file:`external`. Good where it is!
140
151
141 * :file:`frontend`. Good where it is!
152 * :file:`frontend`. Good where it is!
142
153
143 * :file:`generics.py`. Move to :file:`IPython.python`.
154 * :file:`generics.py`. Move to :file:`IPython.python`.
144
155
145 * :file:`genutils.py`. Move to :file:`IPython.python` and break up into different
156 * :file:`genutils.py`. Move to :file:`IPython.python` and break up into different
146 modules.
157 modules.
147
158
148 * :file:`gui`. Eventually this should be moved to a subdir of
159 * :file:`gui`. Eventually this should be moved to a subdir of
149 :file:`IPython.frontend`.
160 :file:`IPython.frontend`.
150
161
151 * :file:`history.py`. Move to :file:`IPython.core`.
162 * :file:`history.py`. Move to :file:`IPython.core`.
152
163
153 * :file:`hooks.py`. Move to :file:`IPython.core`.
164 * :file:`hooks.py`. Move to :file:`IPython.core`.
154
165
155 * :file:`ipapi.py`. Move to :file:`IPython.core`.
166 * :file:`ipapi.py`. Move to :file:`IPython.core`.
156
167
157 * :file:`iplib.py`. Move to :file:`IPython.core`.
168 * :file:`iplib.py`. Move to :file:`IPython.core`.
158
169
159 * :file:`ipmaker.py`: Move to :file:`IPython.core`.
170 * :file:`ipmaker.py`: Move to :file:`IPython.core`.
160
171
161 * :file:`ipstruct.py`. Move to :file:`IPython.python`.
172 * :file:`ipstruct.py`. Move to :file:`IPython.python`.
162
173
163 * :file:`irunner.py`. Move to :file:`IPython.scripts`.
174 * :file:`irunner.py`. Move to :file:`IPython.scripts`.
164
175
165 * :file:`kernel`. Good where it is.
176 * :file:`kernel`. Good where it is.
166
177
167 * :file:`macro.py`. Move to :file:`IPython.core`.
178 * :file:`macro.py`. Move to :file:`IPython.core`.
168
179
169 * :file:`numutils.py`. Move to :file:`IPython.sandbox`.
180 * :file:`numutils.py`. Move to :file:`IPython.sandbox`.
170
181
171 * :file:`platutils.py`. Move to :file:`IPython.python`.
182 * :file:`platutils.py`. Move to :file:`IPython.python`.
172
183
173 * :file:`platutils_dummy.py`. Move to :file:`IPython.python`.
184 * :file:`platutils_dummy.py`. Move to :file:`IPython.python`.
174
185
175 * :file:`platutils_posix.py`. Move to :file:`IPython.python`.
186 * :file:`platutils_posix.py`. Move to :file:`IPython.python`.
176
187
177 * :file:`platutils_win32.py`. Move to :file:`IPython.python`.
188 * :file:`platutils_win32.py`. Move to :file:`IPython.python`.
178
189
179 * :file:`prefilter.py`: Move to :file:`IPython.core`.
190 * :file:`prefilter.py`: Move to :file:`IPython.core`.
180
191
181 * :file:`rlineimpl.py`. Move to :file:`IPython.core`.
192 * :file:`rlineimpl.py`. Move to :file:`IPython.core`.
182
193
183 * :file:`shadowns.py`. Move to :file:`IPython.core`.
194 * :file:`shadowns.py`. Move to :file:`IPython.core`.
184
195
185 * :file:`shellglobals.py`. Move to :file:`IPython.core`.
196 * :file:`shellglobals.py`. Move to :file:`IPython.core`.
186
197
187 * :file:`strdispatch.py`. Move to :file:`IPython.python`.
198 * :file:`strdispatch.py`. Move to :file:`IPython.python`.
188
199
189 * :file:`testing`. Good where it is.
200 * :file:`testing`. Good where it is.
190
201
191 * :file:`tests`. Good where it is.
202 * :file:`tests`. Good where it is.
192
203
193 * :file:`tools`. Things in here need to be looked at and moved elsewhere like
204 * :file:`tools`. Things in here need to be looked at and moved elsewhere like
194 :file:`IPython.python`.
205 :file:`IPython.python`.
195
206
196 * :file:`twshell.py`. Move to :file:`IPython.sandbox`.
207 * :file:`twshell.py`. Move to :file:`IPython.sandbox`.
197
208
198 * :file:`ultraTB.py`. Move to :file:`IPython/core/ultratb.py`.
209 * :file:`ultraTB.py`. Move to :file:`IPython/core/ultratb.py`.
199
210
200 * :file:`upgrade_dir.py`. Move to :file:`IPython/python/upgradedir.py`.
211 * :file:`upgrade_dir.py`. Move to :file:`IPython/python/upgradedir.py`.
201
212
202 * :file:`usage.py`. Move to :file:`IPython.core`.
213 * :file:`usage.py`. Move to :file:`IPython.core`.
203
214
204 * :file:`wildcard.py`. Move to :file:`IPython.python` or :file:`IPython.core`.
215 * :file:`wildcard.py`. Move to :file:`IPython.python` or :file:`IPython.core`.
205
216
206 * :file:`winconsole.py`. Move to :file:`IPython.lib`.
217 * :file:`winconsole.py`. Move to :file:`IPython.lib`.
207
218
208 Other things
219 Other things
209 ============
220 ============
210
221
211 When these files are moved around, a number of other things will happen at the same time:
222 When these files are moved around, a number of other things will happen at the same time:
212
223
213 1. Test files will be created for each module in IPython. Minimally, all
224 1. Test files will be created for each module in IPython. Minimally, all
214 modules will be imported as a part of the test. This will serve as a
225 modules will be imported as a part of the test. This will serve as a
215 test of the module reorganization. These tests will be put into new
226 test of the module reorganization. These tests will be put into new
216 :file:`tests` subdirectories that each package will have.
227 :file:`tests` subdirectories that each package will have.
217
228
218 2. PyFlakes and other code checkers will be run to look for problems.
229 2. PyFlakes and other code checkers will be run to look for problems.
219
230
220 3. Modules will be renamed to comply with PEP 8 naming conventions: all
231 3. Modules will be renamed to comply with PEP 8 naming conventions: all
221 lowercase and no special characters like ``-`` or ``_``.
232 lowercase and no special characters like ``-`` or ``_``.
222
233
223 4. Existing tests will be moved to the appropriate :file:`tests`
234 4. Existing tests will be moved to the appropriate :file:`tests`
224 subdirectories.
235 subdirectories.
225
236
226
237
227
238
228
239
General Comments 0
You need to be logged in to leave comments. Login now