##// END OF EJS Templates
Release.py => core/release.py and imports updated.
Brian Granger -
Show More
@@ -1,270 +1,270
1 """Shell mode for IPython.
1 """Shell mode for IPython.
2
2
3 Start ipython in shell mode by invoking "ipython -p sh"
3 Start ipython in shell mode by invoking "ipython -p sh"
4
4
5 (the old version, "ipython -p pysh" still works but this is the more "modern"
5 (the old version, "ipython -p pysh" still works but this is the more "modern"
6 shell mode and is recommended for users who don't care about pysh-mode
6 shell mode and is recommended for users who don't care about pysh-mode
7 compatibility)
7 compatibility)
8 """
8 """
9
9
10 from IPython.core import ipapi
10 from IPython.core import ipapi
11 import os,re,textwrap
11 import os,re,textwrap
12
12
13 # The import below effectively obsoletes your old-style ipythonrc[.ini],
13 # The import below effectively obsoletes your old-style ipythonrc[.ini],
14 # so consider yourself warned!
14 # so consider yourself warned!
15
15
16 import ipy_defaults
16 import ipy_defaults
17
17
18 def main():
18 def main():
19 ip = ipapi.get()
19 ip = ipapi.get()
20 o = ip.options
20 o = ip.options
21 # autocall to "full" mode (smart mode is default, I like full mode)
21 # autocall to "full" mode (smart mode is default, I like full mode)
22
22
23 o.autocall = 2
23 o.autocall = 2
24
24
25 # Jason Orendorff's path class is handy to have in user namespace
25 # Jason Orendorff's path class is handy to have in user namespace
26 # if you are doing shell-like stuff
26 # if you are doing shell-like stuff
27 try:
27 try:
28 ip.ex("from IPython.external.path import path" )
28 ip.ex("from IPython.external.path import path" )
29 except ImportError:
29 except ImportError:
30 pass
30 pass
31
31
32 # beefed up %env is handy in shell mode
32 # beefed up %env is handy in shell mode
33 import envpersist
33 import envpersist
34
34
35 # To see where mycmd resides (in path/aliases), do %which mycmd
35 # To see where mycmd resides (in path/aliases), do %which mycmd
36 import ipy_which
36 import ipy_which
37
37
38 # tab completers for hg, svn, ...
38 # tab completers for hg, svn, ...
39 import ipy_app_completers
39 import ipy_app_completers
40
40
41 # To make executables foo and bar in mybin usable without PATH change, do:
41 # To make executables foo and bar in mybin usable without PATH change, do:
42 # %rehashdir c:/mybin
42 # %rehashdir c:/mybin
43 # %store foo
43 # %store foo
44 # %store bar
44 # %store bar
45 import ipy_rehashdir
45 import ipy_rehashdir
46
46
47 # does not work without subprocess module!
47 # does not work without subprocess module!
48 #import ipy_signals
48 #import ipy_signals
49
49
50 ip.ex('import os')
50 ip.ex('import os')
51 ip.ex("def up(): os.chdir('..')")
51 ip.ex("def up(): os.chdir('..')")
52 ip.user_ns['LA'] = LastArgFinder()
52 ip.user_ns['LA'] = LastArgFinder()
53
53
54 # You can assign to _prompt_title variable
54 # You can assign to _prompt_title variable
55 # to provide some extra information for prompt
55 # to provide some extra information for prompt
56 # (e.g. the current mode, host/username...)
56 # (e.g. the current mode, host/username...)
57
57
58 ip.user_ns['_prompt_title'] = ''
58 ip.user_ns['_prompt_title'] = ''
59
59
60 # Nice prompt
60 # Nice prompt
61 o.prompt_in1= r'\C_Green${_prompt_title}\C_LightBlue[\C_LightCyan\Y2\C_LightBlue]\C_Green|\#> '
61 o.prompt_in1= r'\C_Green${_prompt_title}\C_LightBlue[\C_LightCyan\Y2\C_LightBlue]\C_Green|\#> '
62 o.prompt_in2= r'\C_Green|\C_LightGreen\D\C_Green> '
62 o.prompt_in2= r'\C_Green|\C_LightGreen\D\C_Green> '
63 o.prompt_out= '<\#> '
63 o.prompt_out= '<\#> '
64
64
65 from IPython import Release
65 from IPython.core import release
66
66
67 import sys
67 import sys
68 # Non-chatty banner
68 # Non-chatty banner
69 o.banner = "IPython %s [on Py %s]\n" % (Release.version,sys.version.split(None,1)[0])
69 o.banner = "IPython %s [on Py %s]\n" % (release.version,sys.version.split(None,1)[0])
70
70
71
71
72 ip.IP.default_option('cd','-q')
72 ip.IP.default_option('cd','-q')
73 ip.IP.default_option('macro', '-r')
73 ip.IP.default_option('macro', '-r')
74 # If you only rarely want to execute the things you %edit...
74 # If you only rarely want to execute the things you %edit...
75 #ip.IP.default_option('edit','-x')
75 #ip.IP.default_option('edit','-x')
76
76
77
77
78 o.prompts_pad_left="1"
78 o.prompts_pad_left="1"
79 # Remove all blank lines in between prompts, like a normal shell.
79 # Remove all blank lines in between prompts, like a normal shell.
80 o.separate_in="0"
80 o.separate_in="0"
81 o.separate_out="0"
81 o.separate_out="0"
82 o.separate_out2="0"
82 o.separate_out2="0"
83
83
84 # now alias all syscommands
84 # now alias all syscommands
85
85
86 db = ip.db
86 db = ip.db
87
87
88 syscmds = db.get("syscmdlist",[] )
88 syscmds = db.get("syscmdlist",[] )
89 if not syscmds:
89 if not syscmds:
90 print textwrap.dedent("""
90 print textwrap.dedent("""
91 System command list not initialized, probably the first run...
91 System command list not initialized, probably the first run...
92 running %rehashx to refresh the command list. Run %rehashx
92 running %rehashx to refresh the command list. Run %rehashx
93 again to refresh command list (after installing new software etc.)
93 again to refresh command list (after installing new software etc.)
94 """)
94 """)
95 ip.magic('rehashx')
95 ip.magic('rehashx')
96 syscmds = db.get("syscmdlist")
96 syscmds = db.get("syscmdlist")
97
97
98 # lowcase aliases on win32 only
98 # lowcase aliases on win32 only
99 if os.name == 'posix':
99 if os.name == 'posix':
100 mapper = lambda s:s
100 mapper = lambda s:s
101 else:
101 else:
102 def mapper(s): return s.lower()
102 def mapper(s): return s.lower()
103
103
104 for cmd in syscmds:
104 for cmd in syscmds:
105 # print "sys",cmd #dbg
105 # print "sys",cmd #dbg
106 noext, ext = os.path.splitext(cmd)
106 noext, ext = os.path.splitext(cmd)
107 if ext.lower() == '.exe':
107 if ext.lower() == '.exe':
108 cmd = noext
108 cmd = noext
109
109
110 key = mapper(cmd)
110 key = mapper(cmd)
111 if key not in ip.IP.alias_table:
111 if key not in ip.IP.alias_table:
112 # Dots will be removed from alias names, since ipython
112 # Dots will be removed from alias names, since ipython
113 # assumes names with dots to be python code
113 # assumes names with dots to be python code
114
114
115 ip.defalias(key.replace('.',''), cmd)
115 ip.defalias(key.replace('.',''), cmd)
116
116
117 # mglob combines 'find', recursion, exclusion... '%mglob?' to learn more
117 # mglob combines 'find', recursion, exclusion... '%mglob?' to learn more
118 ip.load("IPython.external.mglob")
118 ip.load("IPython.external.mglob")
119
119
120 # win32 is crippled w/o cygwin, try to help it a little bit
120 # win32 is crippled w/o cygwin, try to help it a little bit
121 if sys.platform == 'win32':
121 if sys.platform == 'win32':
122 if 'cygwin' in os.environ['PATH'].lower():
122 if 'cygwin' in os.environ['PATH'].lower():
123 # use the colors of cygwin ls (recommended)
123 # use the colors of cygwin ls (recommended)
124 ip.defalias('d', 'ls -F --color=auto')
124 ip.defalias('d', 'ls -F --color=auto')
125 else:
125 else:
126 # get icp, imv, imkdir, igrep, irm,...
126 # get icp, imv, imkdir, igrep, irm,...
127 ip.load('ipy_fsops')
127 ip.load('ipy_fsops')
128
128
129 # and the next best thing to real 'ls -F'
129 # and the next best thing to real 'ls -F'
130 ip.defalias('d','dir /w /og /on')
130 ip.defalias('d','dir /w /og /on')
131
131
132 ip.set_hook('input_prefilter', slash_prefilter_f)
132 ip.set_hook('input_prefilter', slash_prefilter_f)
133 extend_shell_behavior(ip)
133 extend_shell_behavior(ip)
134
134
135 class LastArgFinder:
135 class LastArgFinder:
136 """ Allow $LA to work as "last argument of previous command", like $! in bash
136 """ Allow $LA to work as "last argument of previous command", like $! in bash
137
137
138 To call this in normal IPython code, do LA()
138 To call this in normal IPython code, do LA()
139 """
139 """
140 def __call__(self, hist_idx = None):
140 def __call__(self, hist_idx = None):
141 ip = ipapi.get()
141 ip = ipapi.get()
142 if hist_idx is None:
142 if hist_idx is None:
143 return str(self)
143 return str(self)
144 return ip.IP.input_hist_raw[hist_idx].strip().split()[-1]
144 return ip.IP.input_hist_raw[hist_idx].strip().split()[-1]
145 def __str__(self):
145 def __str__(self):
146 ip = ipapi.get()
146 ip = ipapi.get()
147 for cmd in reversed(ip.IP.input_hist_raw):
147 for cmd in reversed(ip.IP.input_hist_raw):
148 parts = cmd.strip().split()
148 parts = cmd.strip().split()
149 if len(parts) < 2 or parts[-1] in ['$LA', 'LA()']:
149 if len(parts) < 2 or parts[-1] in ['$LA', 'LA()']:
150 continue
150 continue
151 return parts[-1]
151 return parts[-1]
152 return ""
152 return ""
153
153
154 def slash_prefilter_f(self,line):
154 def slash_prefilter_f(self,line):
155 """ ./foo, ~/foo and /bin/foo now run foo as system command
155 """ ./foo, ~/foo and /bin/foo now run foo as system command
156
156
157 Removes the need for doing !./foo, !~/foo or !/bin/foo
157 Removes the need for doing !./foo, !~/foo or !/bin/foo
158 """
158 """
159 from IPython.utils import genutils
159 from IPython.utils import genutils
160 if re.match('(?:[.~]|/[a-zA-Z_0-9]+)/', line):
160 if re.match('(?:[.~]|/[a-zA-Z_0-9]+)/', line):
161 return "_ip.system(" + genutils.make_quoted_expr(line)+")"
161 return "_ip.system(" + genutils.make_quoted_expr(line)+")"
162 raise ipapi.TryNext
162 raise ipapi.TryNext
163
163
164 # XXX You do not need to understand the next function!
164 # XXX You do not need to understand the next function!
165 # This should probably be moved out of profile
165 # This should probably be moved out of profile
166
166
167 def extend_shell_behavior(ip):
167 def extend_shell_behavior(ip):
168
168
169 # Instead of making signature a global variable tie it to IPSHELL.
169 # Instead of making signature a global variable tie it to IPSHELL.
170 # In future if it is required to distinguish between different
170 # In future if it is required to distinguish between different
171 # shells we can assign a signature per shell basis
171 # shells we can assign a signature per shell basis
172 ip.IP.__sig__ = 0xa005
172 ip.IP.__sig__ = 0xa005
173 # mark the IPSHELL with this signature
173 # mark the IPSHELL with this signature
174 ip.IP.user_ns['__builtins__'].__dict__['__sig__'] = ip.IP.__sig__
174 ip.IP.user_ns['__builtins__'].__dict__['__sig__'] = ip.IP.__sig__
175
175
176 from IPython.external.Itpl import ItplNS
176 from IPython.external.Itpl import ItplNS
177 from IPython.utils.genutils import shell
177 from IPython.utils.genutils import shell
178 # utility to expand user variables via Itpl
178 # utility to expand user variables via Itpl
179 # xxx do something sensible with depth?
179 # xxx do something sensible with depth?
180 ip.IP.var_expand = lambda cmd, lvars=None, depth=2: \
180 ip.IP.var_expand = lambda cmd, lvars=None, depth=2: \
181 str(ItplNS(cmd, ip.IP.user_ns, get_locals()))
181 str(ItplNS(cmd, ip.IP.user_ns, get_locals()))
182
182
183 def get_locals():
183 def get_locals():
184 """ Substituting a variable through Itpl deep inside the IPSHELL stack
184 """ Substituting a variable through Itpl deep inside the IPSHELL stack
185 requires the knowledge of all the variables in scope upto the last
185 requires the knowledge of all the variables in scope upto the last
186 IPSHELL frame. This routine simply merges all the local variables
186 IPSHELL frame. This routine simply merges all the local variables
187 on the IPSHELL stack without worrying about their scope rules
187 on the IPSHELL stack without worrying about their scope rules
188 """
188 """
189 import sys
189 import sys
190 # note lambda expression constitues a function call
190 # note lambda expression constitues a function call
191 # hence fno should be incremented by one
191 # hence fno should be incremented by one
192 getsig = lambda fno: sys._getframe(fno+1).f_globals \
192 getsig = lambda fno: sys._getframe(fno+1).f_globals \
193 ['__builtins__'].__dict__['__sig__']
193 ['__builtins__'].__dict__['__sig__']
194 getlvars = lambda fno: sys._getframe(fno+1).f_locals
194 getlvars = lambda fno: sys._getframe(fno+1).f_locals
195 # trackback until we enter the IPSHELL
195 # trackback until we enter the IPSHELL
196 frame_no = 1
196 frame_no = 1
197 sig = ip.IP.__sig__
197 sig = ip.IP.__sig__
198 fsig = ~sig
198 fsig = ~sig
199 while fsig != sig :
199 while fsig != sig :
200 try:
200 try:
201 fsig = getsig(frame_no)
201 fsig = getsig(frame_no)
202 except (AttributeError, KeyError):
202 except (AttributeError, KeyError):
203 frame_no += 1
203 frame_no += 1
204 except ValueError:
204 except ValueError:
205 # stack is depleted
205 # stack is depleted
206 # call did not originate from IPSHELL
206 # call did not originate from IPSHELL
207 return {}
207 return {}
208 first_frame = frame_no
208 first_frame = frame_no
209 # walk further back until we exit from IPSHELL or deplete stack
209 # walk further back until we exit from IPSHELL or deplete stack
210 try:
210 try:
211 while(sig == getsig(frame_no+1)):
211 while(sig == getsig(frame_no+1)):
212 frame_no += 1
212 frame_no += 1
213 except (AttributeError, KeyError, ValueError):
213 except (AttributeError, KeyError, ValueError):
214 pass
214 pass
215 # merge the locals from top down hence overriding
215 # merge the locals from top down hence overriding
216 # any re-definitions of variables, functions etc.
216 # any re-definitions of variables, functions etc.
217 lvars = {}
217 lvars = {}
218 for fno in range(frame_no, first_frame-1, -1):
218 for fno in range(frame_no, first_frame-1, -1):
219 lvars.update(getlvars(fno))
219 lvars.update(getlvars(fno))
220 #print '\n'*5, first_frame, frame_no, '\n', lvars, '\n'*5 #dbg
220 #print '\n'*5, first_frame, frame_no, '\n', lvars, '\n'*5 #dbg
221 return lvars
221 return lvars
222
222
223 def _runlines(lines):
223 def _runlines(lines):
224 """Run a string of one or more lines of source.
224 """Run a string of one or more lines of source.
225
225
226 This method is capable of running a string containing multiple source
226 This method is capable of running a string containing multiple source
227 lines, as if they had been entered at the IPython prompt. Since it
227 lines, as if they had been entered at the IPython prompt. Since it
228 exposes IPython's processing machinery, the given strings can contain
228 exposes IPython's processing machinery, the given strings can contain
229 magic calls (%magic), special shell access (!cmd), etc."""
229 magic calls (%magic), special shell access (!cmd), etc."""
230
230
231 # We must start with a clean buffer, in case this is run from an
231 # We must start with a clean buffer, in case this is run from an
232 # interactive IPython session (via a magic, for example).
232 # interactive IPython session (via a magic, for example).
233 ip.IP.resetbuffer()
233 ip.IP.resetbuffer()
234 lines = lines.split('\n')
234 lines = lines.split('\n')
235 more = 0
235 more = 0
236 command = ''
236 command = ''
237 for line in lines:
237 for line in lines:
238 # skip blank lines so we don't mess up the prompt counter, but do
238 # skip blank lines so we don't mess up the prompt counter, but do
239 # NOT skip even a blank line if we are in a code block (more is
239 # NOT skip even a blank line if we are in a code block (more is
240 # true)
240 # true)
241 # if command is not empty trim the line
241 # if command is not empty trim the line
242 if command != '' :
242 if command != '' :
243 line = line.strip()
243 line = line.strip()
244 # add the broken line to the command
244 # add the broken line to the command
245 if line and line[-1] == '\\' :
245 if line and line[-1] == '\\' :
246 command += line[0:-1] + ' '
246 command += line[0:-1] + ' '
247 more = True
247 more = True
248 continue
248 continue
249 else :
249 else :
250 # add the last (current) line to the command
250 # add the last (current) line to the command
251 command += line
251 command += line
252 if command or more:
252 if command or more:
253 # push to raw history, so hist line numbers stay in sync
253 # push to raw history, so hist line numbers stay in sync
254 ip.IP.input_hist_raw.append("# " + command + "\n")
254 ip.IP.input_hist_raw.append("# " + command + "\n")
255
255
256 more = ip.IP.push(ip.IP.prefilter(command,more))
256 more = ip.IP.push(ip.IP.prefilter(command,more))
257 command = ''
257 command = ''
258 # IPython's runsource returns None if there was an error
258 # IPython's runsource returns None if there was an error
259 # compiling the code. This allows us to stop processing right
259 # compiling the code. This allows us to stop processing right
260 # away, so the user gets the error message at the right place.
260 # away, so the user gets the error message at the right place.
261 if more is None:
261 if more is None:
262 break
262 break
263 # final newline in case the input didn't have it, so that the code
263 # final newline in case the input didn't have it, so that the code
264 # actually does get executed
264 # actually does get executed
265 if more:
265 if more:
266 ip.IP.push('\n')
266 ip.IP.push('\n')
267
267
268 ip.IP.runlines = _runlines
268 ip.IP.runlines = _runlines
269
269
270 main()
270 main()
@@ -1,321 +1,321
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """ An ipython profile for zope and plone.
2 """ An ipython profile for zope and plone.
3
3
4 Some ideas stolen from http://www.tomster.org.
4 Some ideas stolen from http://www.tomster.org.
5
5
6
6
7 Authors
7 Authors
8 -------
8 -------
9 - Stefan Eletzhofer <stefan.eletzhofer@inquant.de>
9 - Stefan Eletzhofer <stefan.eletzhofer@inquant.de>
10 """
10 """
11
11
12 # File: ipy_profile_zope.py
12 # File: ipy_profile_zope.py
13 #
13 #
14 # Copyright (c) InQuant GmbH
14 # Copyright (c) InQuant GmbH
15 #
15 #
16 #
16 #
17 # Distributed under the terms of the BSD License. The full license is in
17 # Distributed under the terms of the BSD License. The full license is in
18 # the file COPYING, distributed as part of this software.
18 # the file COPYING, distributed as part of this software.
19
19
20 from IPython.core import ipapi
20 from IPython.core import ipapi
21 from IPython import Release
21 from IPython.core import release
22 from types import StringType
22 from types import StringType
23 import sys
23 import sys
24 import os
24 import os
25 import textwrap
25 import textwrap
26
26
27 # The import below effectively obsoletes your old-style ipythonrc[.ini],
27 # The import below effectively obsoletes your old-style ipythonrc[.ini],
28 # so consider yourself warned!
28 # so consider yourself warned!
29 # import ipy_defaults
29 # import ipy_defaults
30
30
31 _marker = []
31 _marker = []
32 def shasattr(obj, attr, acquire=False):
32 def shasattr(obj, attr, acquire=False):
33 """ See Archetypes/utils.py
33 """ See Archetypes/utils.py
34 """
34 """
35 if not acquire:
35 if not acquire:
36 obj = obj.aq_base
36 obj = obj.aq_base
37 return getattr(obj, attr, _marker) is not _marker
37 return getattr(obj, attr, _marker) is not _marker
38
38
39 class ZopeDebug(object):
39 class ZopeDebug(object):
40 def __init__(self):
40 def __init__(self):
41
41
42 self.instancehome = os.environ.get( "INSTANCE_HOME" )
42 self.instancehome = os.environ.get( "INSTANCE_HOME" )
43
43
44 configfile = os.environ.get( "CONFIG_FILE" )
44 configfile = os.environ.get( "CONFIG_FILE" )
45 if configfile is None and self.instancehome is not None:
45 if configfile is None and self.instancehome is not None:
46 configfile = os.path.join( self.instancehome, "etc", "zope.conf" )
46 configfile = os.path.join( self.instancehome, "etc", "zope.conf" )
47
47
48 if configfile is None:
48 if configfile is None:
49 raise RuntimeError( "CONFIG_FILE env not set" )
49 raise RuntimeError( "CONFIG_FILE env not set" )
50
50
51 print "CONFIG_FILE=", configfile
51 print "CONFIG_FILE=", configfile
52 print "INSTANCE_HOME=", self.instancehome
52 print "INSTANCE_HOME=", self.instancehome
53
53
54 self.configfile = configfile
54 self.configfile = configfile
55
55
56 try:
56 try:
57 from Zope2 import configure
57 from Zope2 import configure
58 except ImportError:
58 except ImportError:
59 from Zope import configure
59 from Zope import configure
60
60
61 configure( configfile )
61 configure( configfile )
62
62
63 try:
63 try:
64 import Zope2
64 import Zope2
65 app = Zope2.app()
65 app = Zope2.app()
66 except ImportError:
66 except ImportError:
67 import Zope
67 import Zope
68 app = Zope.app()
68 app = Zope.app()
69
69
70 from Testing.makerequest import makerequest
70 from Testing.makerequest import makerequest
71 self.app = makerequest( app )
71 self.app = makerequest( app )
72
72
73 try:
73 try:
74 self._make_permissive()
74 self._make_permissive()
75 print "Permissive security installed"
75 print "Permissive security installed"
76 except:
76 except:
77 print "Permissive security NOT installed"
77 print "Permissive security NOT installed"
78
78
79 self._pwd = self.portal or self.app
79 self._pwd = self.portal or self.app
80
80
81 try:
81 try:
82 from zope.component import getSiteManager
82 from zope.component import getSiteManager
83 from zope.component import getGlobalSiteManager
83 from zope.component import getGlobalSiteManager
84 from zope.app.component.hooks import setSite
84 from zope.app.component.hooks import setSite
85
85
86 if self.portal is not None:
86 if self.portal is not None:
87 setSite( self.portal )
87 setSite( self.portal )
88
88
89 gsm = getGlobalSiteManager()
89 gsm = getGlobalSiteManager()
90 sm = getSiteManager()
90 sm = getSiteManager()
91
91
92 if sm is gsm:
92 if sm is gsm:
93 print "ERROR SETTING SITE!"
93 print "ERROR SETTING SITE!"
94 except:
94 except:
95 pass
95 pass
96
96
97
97
98 @property
98 @property
99 def utils(self):
99 def utils(self):
100 class Utils(object):
100 class Utils(object):
101 commit = self.commit
101 commit = self.commit
102 sync = self.sync
102 sync = self.sync
103 objectInfo = self.objectInfo
103 objectInfo = self.objectInfo
104 ls = self.ls
104 ls = self.ls
105 pwd = self.pwd
105 pwd = self.pwd
106 cd = self.cd
106 cd = self.cd
107 su = self.su
107 su = self.su
108 getCatalogInfo = self.getCatalogInfo
108 getCatalogInfo = self.getCatalogInfo
109
109
110 @property
110 @property
111 def cwd(self):
111 def cwd(self):
112 return self.pwd()
112 return self.pwd()
113
113
114 return Utils()
114 return Utils()
115
115
116 @property
116 @property
117 def namespace(self):
117 def namespace(self):
118 return dict( utils=self.utils, app=self.app, portal=self.portal )
118 return dict( utils=self.utils, app=self.app, portal=self.portal )
119
119
120 @property
120 @property
121 def portal(self):
121 def portal(self):
122 portals = self.app.objectValues( "Plone Site" )
122 portals = self.app.objectValues( "Plone Site" )
123 if len(portals):
123 if len(portals):
124 return portals[0]
124 return portals[0]
125 else:
125 else:
126 raise KeyError( "No Plone Site found.")
126 raise KeyError( "No Plone Site found.")
127
127
128 def pwd(self):
128 def pwd(self):
129 return self._pwd
129 return self._pwd
130
130
131 def _make_permissive(self):
131 def _make_permissive(self):
132 """
132 """
133 Make a permissive security manager with all rights. Hell,
133 Make a permissive security manager with all rights. Hell,
134 we're developers, aren't we? Security is for whimps. :)
134 we're developers, aren't we? Security is for whimps. :)
135 """
135 """
136 from Products.CMFCore.tests.base.security import PermissiveSecurityPolicy
136 from Products.CMFCore.tests.base.security import PermissiveSecurityPolicy
137 import AccessControl
137 import AccessControl
138 from AccessControl.SecurityManagement import newSecurityManager
138 from AccessControl.SecurityManagement import newSecurityManager
139 from AccessControl.SecurityManager import setSecurityPolicy
139 from AccessControl.SecurityManager import setSecurityPolicy
140
140
141 _policy = PermissiveSecurityPolicy()
141 _policy = PermissiveSecurityPolicy()
142 self.oldpolicy = setSecurityPolicy(_policy)
142 self.oldpolicy = setSecurityPolicy(_policy)
143 newSecurityManager(None, AccessControl.User.system)
143 newSecurityManager(None, AccessControl.User.system)
144
144
145 def su(self, username):
145 def su(self, username):
146 """ Change to named user.
146 """ Change to named user.
147 """
147 """
148 # TODO Make it easy to change back to permissive security.
148 # TODO Make it easy to change back to permissive security.
149 user = self.portal.acl_users.getUser(username)
149 user = self.portal.acl_users.getUser(username)
150 if not user:
150 if not user:
151 print "Can't find %s in %s" % (username, self.portal.acl_users)
151 print "Can't find %s in %s" % (username, self.portal.acl_users)
152 return
152 return
153
153
154 from AccessControl import ZopeSecurityPolicy
154 from AccessControl import ZopeSecurityPolicy
155 import AccessControl
155 import AccessControl
156 from AccessControl.SecurityManagement import newSecurityManager, getSecurityManager
156 from AccessControl.SecurityManagement import newSecurityManager, getSecurityManager
157 from AccessControl.SecurityManager import setSecurityPolicy
157 from AccessControl.SecurityManager import setSecurityPolicy
158
158
159 _policy = ZopeSecurityPolicy
159 _policy = ZopeSecurityPolicy
160 self.oldpolicy = setSecurityPolicy(_policy)
160 self.oldpolicy = setSecurityPolicy(_policy)
161 wrapped_user = user.__of__(self.portal.acl_users)
161 wrapped_user = user.__of__(self.portal.acl_users)
162 newSecurityManager(None, user)
162 newSecurityManager(None, user)
163 print 'User changed.'
163 print 'User changed.'
164 return getSecurityManager().getUser()
164 return getSecurityManager().getUser()
165
165
166 def getCatalogInfo(self, obj=None, catalog='portal_catalog', query=None, sort_on='created', sort_order='reverse' ):
166 def getCatalogInfo(self, obj=None, catalog='portal_catalog', query=None, sort_on='created', sort_order='reverse' ):
167 """ Inspect portal_catalog. Pass an object or object id for a
167 """ Inspect portal_catalog. Pass an object or object id for a
168 default query on that object, or pass an explicit query.
168 default query on that object, or pass an explicit query.
169 """
169 """
170 if obj and query:
170 if obj and query:
171 print "Ignoring %s, using query." % obj
171 print "Ignoring %s, using query." % obj
172
172
173 catalog = self.portal.get(catalog)
173 catalog = self.portal.get(catalog)
174 if not catalog:
174 if not catalog:
175 return 'No catalog'
175 return 'No catalog'
176
176
177 indexes = catalog._catalog.indexes
177 indexes = catalog._catalog.indexes
178 if not query:
178 if not query:
179 if type(obj) is StringType:
179 if type(obj) is StringType:
180 cwd = self.pwd()
180 cwd = self.pwd()
181 obj = cwd.unrestrictedTraverse( obj )
181 obj = cwd.unrestrictedTraverse( obj )
182 # If the default in the signature is mutable, its value will
182 # If the default in the signature is mutable, its value will
183 # persist across invocations.
183 # persist across invocations.
184 query = {}
184 query = {}
185 if indexes.get('path'):
185 if indexes.get('path'):
186 from string import join
186 from string import join
187 path = join(obj.getPhysicalPath(), '/')
187 path = join(obj.getPhysicalPath(), '/')
188 query.update({'path': path})
188 query.update({'path': path})
189 if indexes.get('getID'):
189 if indexes.get('getID'):
190 query.update({'getID': obj.id, })
190 query.update({'getID': obj.id, })
191 if indexes.get('UID') and shasattr(obj, 'UID'):
191 if indexes.get('UID') and shasattr(obj, 'UID'):
192 query.update({'UID': obj.UID(), })
192 query.update({'UID': obj.UID(), })
193 if indexes.get(sort_on):
193 if indexes.get(sort_on):
194 query.update({'sort_on': sort_on, 'sort_order': sort_order})
194 query.update({'sort_on': sort_on, 'sort_order': sort_order})
195 if not query:
195 if not query:
196 return 'Empty query'
196 return 'Empty query'
197 results = catalog(**query)
197 results = catalog(**query)
198
198
199 result_info = []
199 result_info = []
200 for r in results:
200 for r in results:
201 rid = r.getRID()
201 rid = r.getRID()
202 if rid:
202 if rid:
203 result_info.append(
203 result_info.append(
204 {'path': catalog.getpath(rid),
204 {'path': catalog.getpath(rid),
205 'metadata': catalog.getMetadataForRID(rid),
205 'metadata': catalog.getMetadataForRID(rid),
206 'indexes': catalog.getIndexDataForRID(rid), }
206 'indexes': catalog.getIndexDataForRID(rid), }
207 )
207 )
208 else:
208 else:
209 result_info.append({'missing': rid})
209 result_info.append({'missing': rid})
210
210
211 if len(result_info) == 1:
211 if len(result_info) == 1:
212 return result_info[0]
212 return result_info[0]
213 return result_info
213 return result_info
214
214
215 def commit(self):
215 def commit(self):
216 """
216 """
217 Commit the transaction.
217 Commit the transaction.
218 """
218 """
219 try:
219 try:
220 import transaction
220 import transaction
221 transaction.get().commit()
221 transaction.get().commit()
222 except ImportError:
222 except ImportError:
223 get_transaction().commit()
223 get_transaction().commit()
224
224
225 def sync(self):
225 def sync(self):
226 """
226 """
227 Sync the app's view of the zodb.
227 Sync the app's view of the zodb.
228 """
228 """
229 self.app._p_jar.sync()
229 self.app._p_jar.sync()
230
230
231 def objectInfo( self, o ):
231 def objectInfo( self, o ):
232 """
232 """
233 Return a descriptive string of an object
233 Return a descriptive string of an object
234 """
234 """
235 Title = ""
235 Title = ""
236 t = getattr( o, 'Title', None )
236 t = getattr( o, 'Title', None )
237 if t:
237 if t:
238 Title = t()
238 Title = t()
239 return {'id': o.getId(),
239 return {'id': o.getId(),
240 'Title': Title,
240 'Title': Title,
241 'portal_type': getattr( o, 'portal_type', o.meta_type),
241 'portal_type': getattr( o, 'portal_type', o.meta_type),
242 'folderish': o.isPrincipiaFolderish
242 'folderish': o.isPrincipiaFolderish
243 }
243 }
244
244
245 def cd( self, path ):
245 def cd( self, path ):
246 """
246 """
247 Change current dir to a specific folder.
247 Change current dir to a specific folder.
248
248
249 cd( ".." )
249 cd( ".." )
250 cd( "/plone/Members/admin" )
250 cd( "/plone/Members/admin" )
251 cd( portal.Members.admin )
251 cd( portal.Members.admin )
252 etc.
252 etc.
253 """
253 """
254 if type(path) is not StringType:
254 if type(path) is not StringType:
255 path = '/'.join(path.getPhysicalPath())
255 path = '/'.join(path.getPhysicalPath())
256 cwd = self.pwd()
256 cwd = self.pwd()
257 x = cwd.unrestrictedTraverse( path )
257 x = cwd.unrestrictedTraverse( path )
258 if x is None:
258 if x is None:
259 raise KeyError( "Can't cd to %s" % path )
259 raise KeyError( "Can't cd to %s" % path )
260
260
261 print "%s -> %s" % ( self.pwd().getId(), x.getId() )
261 print "%s -> %s" % ( self.pwd().getId(), x.getId() )
262 self._pwd = x
262 self._pwd = x
263
263
264 def ls( self, x=None ):
264 def ls( self, x=None ):
265 """
265 """
266 List object(s)
266 List object(s)
267 """
267 """
268 if type(x) is StringType:
268 if type(x) is StringType:
269 cwd = self.pwd()
269 cwd = self.pwd()
270 x = cwd.unrestrictedTraverse( x )
270 x = cwd.unrestrictedTraverse( x )
271 if x is None:
271 if x is None:
272 x = self.pwd()
272 x = self.pwd()
273 if x.isPrincipiaFolderish:
273 if x.isPrincipiaFolderish:
274 return [self.objectInfo(o) for id, o in x.objectItems()]
274 return [self.objectInfo(o) for id, o in x.objectItems()]
275 else:
275 else:
276 return self.objectInfo( x )
276 return self.objectInfo( x )
277
277
278 zope_debug = None
278 zope_debug = None
279
279
280 def ipy_set_trace():
280 def ipy_set_trace():
281 from IPython.core import debugger
281 from IPython.core import debugger
282 debugger.Pdb().set_trace()
282 debugger.Pdb().set_trace()
283
283
284 def main():
284 def main():
285 global zope_debug
285 global zope_debug
286 ip = ipapi.get()
286 ip = ipapi.get()
287 o = ip.options
287 o = ip.options
288 # autocall to "full" mode (smart mode is default, I like full mode)
288 # autocall to "full" mode (smart mode is default, I like full mode)
289
289
290 SOFTWARE_HOME = os.environ.get( "SOFTWARE_HOME" )
290 SOFTWARE_HOME = os.environ.get( "SOFTWARE_HOME" )
291 sys.path.append( SOFTWARE_HOME )
291 sys.path.append( SOFTWARE_HOME )
292 print "SOFTWARE_HOME=%s\n" % SOFTWARE_HOME
292 print "SOFTWARE_HOME=%s\n" % SOFTWARE_HOME
293
293
294 zope_debug = ZopeDebug()
294 zope_debug = ZopeDebug()
295
295
296 # <HACK ALERT>
296 # <HACK ALERT>
297 import pdb;
297 import pdb;
298 pdb.set_trace = ipy_set_trace
298 pdb.set_trace = ipy_set_trace
299 # </HACK ALERT>
299 # </HACK ALERT>
300
300
301 # I like my banner minimal.
301 # I like my banner minimal.
302 o.banner = "ZOPE Py %s IPy %s\n" % (sys.version.split('\n')[0],Release.version)
302 o.banner = "ZOPE Py %s IPy %s\n" % (sys.version.split('\n')[0],release.version)
303
303
304 print textwrap.dedent("""\
304 print textwrap.dedent("""\
305 ZOPE mode iPython shell.
305 ZOPE mode iPython shell.
306
306
307 Bound names:
307 Bound names:
308 app
308 app
309 portal
309 portal
310 utils.{ %s }
310 utils.{ %s }
311
311
312 Uses the $SOFTWARE_HOME and $CONFIG_FILE environment
312 Uses the $SOFTWARE_HOME and $CONFIG_FILE environment
313 variables.
313 variables.
314 """ % ( ",".join([ x for x in dir(zope_debug.utils) if not x.startswith("_") ] ) ) )
314 """ % ( ",".join([ x for x in dir(zope_debug.utils) if not x.startswith("_") ] ) ) )
315
315
316
316
317 ip.user_ns.update( zope_debug.namespace )
317 ip.user_ns.update( zope_debug.namespace )
318
318
319
319
320 main()
320 main()
321 # vim: set ft=python ts=4 sw=4 expandtab :
321 # vim: set ft=python ts=4 sw=4 expandtab :
@@ -1,72 +1,73
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__ = ['IPython.core.ipapi','utils.generics','utils.ipstruct','Release','Shell']
51 __all__ = ['IPython.core.ipapi','utils.generics','utils.ipstruct',
52 'core.release','Shell']
52
53
53 # Load __all__ in IPython namespace so that a simple 'import IPython' gives
54 # Load __all__ in IPython namespace so that a simple 'import IPython' gives
54 # access to them via IPython.<name>
55 # access to them via IPython.<name>
55 glob,loc = globals(),locals()
56 glob,loc = globals(),locals()
56 for name in __all__:
57 for name in __all__:
57 #print 'Importing: ',name # dbg
58 #print 'Importing: ',name # dbg
58 __import__(name,glob,loc,[])
59 __import__(name,glob,loc,[])
59
60
60 import Shell
61 import Shell
61
62
62 # Release data
63 # Release data
63 from IPython import Release # do it explicitly so pydoc can see it - pydoc bug
64 from IPython.core import release # do it explicitly so pydoc can see it - pydoc bug
64 __author__ = '%s <%s>\n%s <%s>\n%s <%s>' % \
65 __author__ = '%s <%s>\n%s <%s>\n%s <%s>' % \
65 ( Release.authors['Fernando'] + Release.authors['Janko'] + \
66 ( release.authors['Fernando'] + release.authors['Janko'] + \
66 Release.authors['Nathan'] )
67 release.authors['Nathan'] )
67 __license__ = Release.license
68 __license__ = release.license
68 __version__ = Release.version
69 __version__ = release.version
69 __revision__ = Release.revision
70 __revision__ = release.revision
70
71
71 # Namespace cleanup
72 # Namespace cleanup
72 del name,glob,loc
73 del name,glob,loc
@@ -1,229 +1,229
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """sys.excepthook for IPython itself, leaves a detailed report on disk.
2 """sys.excepthook for IPython itself, leaves a detailed report on disk.
3
3
4
4
5 Authors
5 Authors
6 -------
6 -------
7 - Fernando Perez <Fernando.Perez@berkeley.edu>
7 - Fernando Perez <Fernando.Perez@berkeley.edu>
8 """
8 """
9
9
10 #*****************************************************************************
10 #*****************************************************************************
11 # Copyright (C) 2008-2009 The IPython Development Team
11 # Copyright (C) 2008-2009 The IPython Development Team
12 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
12 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
13 #
13 #
14 # Distributed under the terms of the BSD License. The full license is in
14 # Distributed under the terms of the BSD License. The full license is in
15 # the file COPYING, distributed as part of this software.
15 # the file COPYING, distributed as part of this software.
16 #*****************************************************************************
16 #*****************************************************************************
17
17
18 #****************************************************************************
18 #****************************************************************************
19 # Required modules
19 # Required modules
20
20
21 # From the standard library
21 # From the standard library
22 import os
22 import os
23 import sys
23 import sys
24 from pprint import pformat
24 from pprint import pformat
25
25
26 # Our own
26 # Our own
27 from IPython import Release
27 from IPython.core import release
28 from IPython import ultraTB
28 from IPython import ultraTB
29 from IPython.external.Itpl import itpl
29 from IPython.external.Itpl import itpl
30
30
31 from IPython.utils.genutils import *
31 from IPython.utils.genutils import *
32
32
33 #****************************************************************************
33 #****************************************************************************
34 class CrashHandler:
34 class CrashHandler:
35 """Customizable crash handlers for IPython-based systems.
35 """Customizable crash handlers for IPython-based systems.
36
36
37 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
38 sys.excepthook, i.e., the __call__ signature is:
38 sys.excepthook, i.e., the __call__ signature is:
39
39
40 def __call__(self,etype, evalue, etb)
40 def __call__(self,etype, evalue, etb)
41
41
42 """
42 """
43
43
44 def __init__(self,IP,app_name,contact_name,contact_email,
44 def __init__(self,IP,app_name,contact_name,contact_email,
45 bug_tracker,crash_report_fname,
45 bug_tracker,crash_report_fname,
46 show_crash_traceback=True):
46 show_crash_traceback=True):
47 """New crash handler.
47 """New crash handler.
48
48
49 Inputs:
49 Inputs:
50
50
51 - 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
52 for internal information.
52 for internal information.
53
53
54 - app_name: a string containing the name of your application.
54 - app_name: a string containing the name of your application.
55
55
56 - 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.
57
57
58 - contact_email: a string with the email address of the contact.
58 - contact_email: a string with the email address of the contact.
59
59
60 - 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.
61
61
62 - 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
63 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
64 as determined by the running IPython instance.
64 as determined by the running IPython instance.
65
65
66 Optional inputs:
66 Optional inputs:
67
67
68 - show_crash_traceback(True): if false, don't print the crash
68 - show_crash_traceback(True): if false, don't print the crash
69 traceback on stderr, only generate the on-disk report
69 traceback on stderr, only generate the on-disk report
70
70
71
71
72 Non-argument instance attributes:
72 Non-argument instance attributes:
73
73
74 These instances contain some non-argument attributes which allow for
74 These instances contain some non-argument attributes which allow for
75 further customization of the crash handler's behavior. Please see the
75 further customization of the crash handler's behavior. Please see the
76 source for further details.
76 source for further details.
77 """
77 """
78
78
79 # apply args into instance
79 # apply args into instance
80 self.IP = IP # IPython instance
80 self.IP = IP # IPython instance
81 self.app_name = app_name
81 self.app_name = app_name
82 self.contact_name = contact_name
82 self.contact_name = contact_name
83 self.contact_email = contact_email
83 self.contact_email = contact_email
84 self.bug_tracker = bug_tracker
84 self.bug_tracker = bug_tracker
85 self.crash_report_fname = crash_report_fname
85 self.crash_report_fname = crash_report_fname
86 self.show_crash_traceback = show_crash_traceback
86 self.show_crash_traceback = show_crash_traceback
87
87
88 # Hardcoded defaults, which can be overridden either by subclasses or
88 # Hardcoded defaults, which can be overridden either by subclasses or
89 # at runtime for the instance.
89 # at runtime for the instance.
90
90
91 # Template for the user message. Subclasses which completely override
91 # Template for the user message. Subclasses which completely override
92 # 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
93 # 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.
94 self.user_message_template = """
94 self.user_message_template = """
95 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...
96
96
97 A crash report was automatically generated with the following information:
97 A crash report was automatically generated with the following information:
98 - A verbatim copy of the crash traceback.
98 - A verbatim copy of the crash traceback.
99 - A copy of your input history during this session.
99 - A copy of your input history during this session.
100 - Data on your current $self.app_name configuration.
100 - Data on your current $self.app_name configuration.
101
101
102 It was left in the file named:
102 It was left in the file named:
103 \t'$self.crash_report_fname'
103 \t'$self.crash_report_fname'
104 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
105 them in understanding and correcting the problem.
105 them in understanding and correcting the problem.
106
106
107 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
108 with the subject '$self.app_name Crash Report'.
108 with the subject '$self.app_name Crash Report'.
109
109
110 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):
111 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
112
112
113 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:
114 $self.bug_tracker
114 $self.bug_tracker
115 """
115 """
116
116
117 def __call__(self,etype, evalue, etb):
117 def __call__(self,etype, evalue, etb):
118 """Handle an exception, call for compatible with sys.excepthook"""
118 """Handle an exception, call for compatible with sys.excepthook"""
119
119
120 # Report tracebacks shouldn't use color in general (safer for users)
120 # Report tracebacks shouldn't use color in general (safer for users)
121 color_scheme = 'NoColor'
121 color_scheme = 'NoColor'
122
122
123 # Use this ONLY for developer debugging (keep commented out for release)
123 # Use this ONLY for developer debugging (keep commented out for release)
124 #color_scheme = 'Linux' # dbg
124 #color_scheme = 'Linux' # dbg
125
125
126 try:
126 try:
127 rptdir = self.IP.rc.ipythondir
127 rptdir = self.IP.rc.ipythondir
128 except:
128 except:
129 rptdir = os.getcwd()
129 rptdir = os.getcwd()
130 if not os.path.isdir(rptdir):
130 if not os.path.isdir(rptdir):
131 rptdir = os.getcwd()
131 rptdir = os.getcwd()
132 report_name = os.path.join(rptdir,self.crash_report_fname)
132 report_name = os.path.join(rptdir,self.crash_report_fname)
133 # 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
134 # properly expanded out in the user message template
134 # properly expanded out in the user message template
135 self.crash_report_fname = report_name
135 self.crash_report_fname = report_name
136 TBhandler = ultraTB.VerboseTB(color_scheme=color_scheme,
136 TBhandler = ultraTB.VerboseTB(color_scheme=color_scheme,
137 long_header=1)
137 long_header=1)
138 traceback = TBhandler.text(etype,evalue,etb,context=31)
138 traceback = TBhandler.text(etype,evalue,etb,context=31)
139
139
140 # print traceback to screen
140 # print traceback to screen
141 if self.show_crash_traceback:
141 if self.show_crash_traceback:
142 print >> sys.stderr, traceback
142 print >> sys.stderr, traceback
143
143
144 # and generate a complete report on disk
144 # and generate a complete report on disk
145 try:
145 try:
146 report = open(report_name,'w')
146 report = open(report_name,'w')
147 except:
147 except:
148 print >> sys.stderr, 'Could not create crash report on disk.'
148 print >> sys.stderr, 'Could not create crash report on disk.'
149 return
149 return
150
150
151 # Inform user on stderr of what happened
151 # Inform user on stderr of what happened
152 msg = itpl('\n'+'*'*70+'\n'+self.user_message_template)
152 msg = itpl('\n'+'*'*70+'\n'+self.user_message_template)
153 print >> sys.stderr, msg
153 print >> sys.stderr, msg
154
154
155 # Construct report on disk
155 # Construct report on disk
156 report.write(self.make_report(traceback))
156 report.write(self.make_report(traceback))
157 report.close()
157 report.close()
158 raw_input("Press enter to exit:")
158 raw_input("Press enter to exit:")
159
159
160 def make_report(self,traceback):
160 def make_report(self,traceback):
161 """Return a string containing a crash report."""
161 """Return a string containing a crash report."""
162
162
163 sec_sep = '\n\n'+'*'*75+'\n\n'
163 sec_sep = '\n\n'+'*'*75+'\n\n'
164
164
165 report = []
165 report = []
166 rpt_add = report.append
166 rpt_add = report.append
167
167
168 rpt_add('*'*75+'\n\n'+'IPython post-mortem report\n\n')
168 rpt_add('*'*75+'\n\n'+'IPython post-mortem report\n\n')
169 rpt_add('IPython version: %s \n\n' % Release.version)
169 rpt_add('IPython version: %s \n\n' % release.version)
170 rpt_add('BZR revision : %s \n\n' % Release.revision)
170 rpt_add('BZR revision : %s \n\n' % release.revision)
171 rpt_add('Platform info : os.name -> %s, sys.platform -> %s' %
171 rpt_add('Platform info : os.name -> %s, sys.platform -> %s' %
172 (os.name,sys.platform) )
172 (os.name,sys.platform) )
173 rpt_add(sec_sep+'Current user configuration structure:\n\n')
173 rpt_add(sec_sep+'Current user configuration structure:\n\n')
174 rpt_add(pformat(self.IP.rc.dict()))
174 rpt_add(pformat(self.IP.rc.dict()))
175 rpt_add(sec_sep+'Crash traceback:\n\n' + traceback)
175 rpt_add(sec_sep+'Crash traceback:\n\n' + traceback)
176 try:
176 try:
177 rpt_add(sec_sep+"History of session input:")
177 rpt_add(sec_sep+"History of session input:")
178 for line in self.IP.user_ns['_ih']:
178 for line in self.IP.user_ns['_ih']:
179 rpt_add(line)
179 rpt_add(line)
180 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')
181 rpt_add(self.IP._last_input_line+'\n')
181 rpt_add(self.IP._last_input_line+'\n')
182 except:
182 except:
183 pass
183 pass
184
184
185 return ''.join(report)
185 return ''.join(report)
186
186
187 class IPythonCrashHandler(CrashHandler):
187 class IPythonCrashHandler(CrashHandler):
188 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
188 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
189
189
190 def __init__(self,IP):
190 def __init__(self,IP):
191
191
192 # 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
193 AUTHOR_CONTACT = 'Ville'
193 AUTHOR_CONTACT = 'Ville'
194
194
195 # Set argument defaults
195 # Set argument defaults
196 app_name = 'IPython'
196 app_name = 'IPython'
197 bug_tracker = 'https://bugs.launchpad.net/ipython/+filebug'
197 bug_tracker = 'https://bugs.launchpad.net/ipython/+filebug'
198 contact_name,contact_email = Release.authors[AUTHOR_CONTACT][:2]
198 contact_name,contact_email = release.authors[AUTHOR_CONTACT][:2]
199 crash_report_fname = 'IPython_crash_report.txt'
199 crash_report_fname = 'IPython_crash_report.txt'
200 # Call parent constructor
200 # Call parent constructor
201 CrashHandler.__init__(self,IP,app_name,contact_name,contact_email,
201 CrashHandler.__init__(self,IP,app_name,contact_name,contact_email,
202 bug_tracker,crash_report_fname)
202 bug_tracker,crash_report_fname)
203
203
204 def make_report(self,traceback):
204 def make_report(self,traceback):
205 """Return a string containing a crash report."""
205 """Return a string containing a crash report."""
206
206
207 sec_sep = '\n\n'+'*'*75+'\n\n'
207 sec_sep = '\n\n'+'*'*75+'\n\n'
208
208
209 report = []
209 report = []
210 rpt_add = report.append
210 rpt_add = report.append
211
211
212 rpt_add('*'*75+'\n\n'+'IPython post-mortem report\n\n')
212 rpt_add('*'*75+'\n\n'+'IPython post-mortem report\n\n')
213 rpt_add('IPython version: %s \n\n' % Release.version)
213 rpt_add('IPython version: %s \n\n' % release.version)
214 rpt_add('BZR revision : %s \n\n' % Release.revision)
214 rpt_add('BZR revision : %s \n\n' % release.revision)
215 rpt_add('Platform info : os.name -> %s, sys.platform -> %s' %
215 rpt_add('Platform info : os.name -> %s, sys.platform -> %s' %
216 (os.name,sys.platform) )
216 (os.name,sys.platform) )
217 rpt_add(sec_sep+'Current user configuration structure:\n\n')
217 rpt_add(sec_sep+'Current user configuration structure:\n\n')
218 rpt_add(pformat(self.IP.rc.dict()))
218 rpt_add(pformat(self.IP.rc.dict()))
219 rpt_add(sec_sep+'Crash traceback:\n\n' + traceback)
219 rpt_add(sec_sep+'Crash traceback:\n\n' + traceback)
220 try:
220 try:
221 rpt_add(sec_sep+"History of session input:")
221 rpt_add(sec_sep+"History of session input:")
222 for line in self.IP.user_ns['_ih']:
222 for line in self.IP.user_ns['_ih']:
223 rpt_add(line)
223 rpt_add(line)
224 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')
225 rpt_add(self.IP._last_input_line+'\n')
225 rpt_add(self.IP._last_input_line+'\n')
226 except:
226 except:
227 pass
227 pass
228
228
229 return ''.join(report)
229 return ''.join(report)
@@ -1,771 +1,771
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.1 or better.
5 Requires Python 2.1 or better.
6
6
7 This file contains the main make_IPython() starter function.
7 This file contains the main make_IPython() starter function.
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 try:
18 try:
19 credits._Printer__data = """
19 credits._Printer__data = """
20 Python: %s
20 Python: %s
21
21
22 IPython: The IPython Development Team.
22 IPython: The IPython Development Team.
23 See http://ipython.scipy.org for more information.""" \
23 See http://ipython.scipy.org for more information.""" \
24 % credits._Printer__data
24 % credits._Printer__data
25
25
26 copyright._Printer__data += """
26 copyright._Printer__data += """
27
27
28 Copyright (c) 2008-2009 The IPython Development Team.
28 Copyright (c) 2008-2009 The IPython Development Team.
29 Copyright (c) 2001-2007 Fernando Perez, Janko Hauser, Nathan Gray.
29 Copyright (c) 2001-2007 Fernando Perez, Janko Hauser, Nathan Gray.
30 All Rights Reserved."""
30 All Rights Reserved."""
31 except NameError:
31 except NameError:
32 # Can happen if ipython was started with 'python -S', so that site.py is
32 # Can happen if ipython was started with 'python -S', so that site.py is
33 # not loaded
33 # not loaded
34 pass
34 pass
35
35
36 #****************************************************************************
36 #****************************************************************************
37 # Required modules
37 # Required modules
38
38
39 # From the standard library
39 # From the standard library
40 import __main__
40 import __main__
41 import __builtin__
41 import __builtin__
42 import os
42 import os
43 import sys
43 import sys
44 from pprint import pprint
44 from pprint import pprint
45
45
46 # Our own
46 # Our own
47 from IPython.utils import DPyGetOpt
47 from IPython.utils import DPyGetOpt
48 from IPython import Release
48 from IPython.core import release
49 from IPython.utils.ipstruct import Struct
49 from IPython.utils.ipstruct import Struct
50 from IPython.core.outputtrap import OutputTrap
50 from IPython.core.outputtrap import OutputTrap
51 from IPython.config.configloader import ConfigLoader
51 from IPython.config.configloader import ConfigLoader
52 from IPython.core.iplib import InteractiveShell
52 from IPython.core.iplib import InteractiveShell
53 from IPython.usage import cmd_line_usage,interactive_usage
53 from IPython.usage import cmd_line_usage,interactive_usage
54 from IPython.utils.genutils import *
54 from IPython.utils.genutils import *
55
55
56 def force_import(modname,force_reload=False):
56 def force_import(modname,force_reload=False):
57 if modname in sys.modules and force_reload:
57 if modname in sys.modules and force_reload:
58 info("reloading: %s" % modname)
58 info("reloading: %s" % modname)
59 reload(sys.modules[modname])
59 reload(sys.modules[modname])
60 else:
60 else:
61 __import__(modname)
61 __import__(modname)
62
62
63
63
64 #-----------------------------------------------------------------------------
64 #-----------------------------------------------------------------------------
65 def make_IPython(argv=None,user_ns=None,user_global_ns=None,debug=1,
65 def make_IPython(argv=None,user_ns=None,user_global_ns=None,debug=1,
66 rc_override=None,shell_class=InteractiveShell,
66 rc_override=None,shell_class=InteractiveShell,
67 embedded=False,**kw):
67 embedded=False,**kw):
68 """This is a dump of IPython into a single function.
68 """This is a dump of IPython into a single function.
69
69
70 Later it will have to be broken up in a sensible manner.
70 Later it will have to be broken up in a sensible manner.
71
71
72 Arguments:
72 Arguments:
73
73
74 - argv: a list similar to sys.argv[1:]. It should NOT contain the desired
74 - argv: a list similar to sys.argv[1:]. It should NOT contain the desired
75 script name, b/c DPyGetOpt strips the first argument only for the real
75 script name, b/c DPyGetOpt strips the first argument only for the real
76 sys.argv.
76 sys.argv.
77
77
78 - user_ns: a dict to be used as the user's namespace."""
78 - user_ns: a dict to be used as the user's namespace."""
79
79
80 #----------------------------------------------------------------------
80 #----------------------------------------------------------------------
81 # Defaults and initialization
81 # Defaults and initialization
82
82
83 # For developer debugging, deactivates crash handler and uses pdb.
83 # For developer debugging, deactivates crash handler and uses pdb.
84 DEVDEBUG = False
84 DEVDEBUG = False
85
85
86 if argv is None:
86 if argv is None:
87 argv = sys.argv
87 argv = sys.argv
88
88
89 # __IP is the main global that lives throughout and represents the whole
89 # __IP is the main global that lives throughout and represents the whole
90 # application. If the user redefines it, all bets are off as to what
90 # application. If the user redefines it, all bets are off as to what
91 # happens.
91 # happens.
92
92
93 # __IP is the name of he global which the caller will have accessible as
93 # __IP is the name of he global which the caller will have accessible as
94 # __IP.name. We set its name via the first parameter passed to
94 # __IP.name. We set its name via the first parameter passed to
95 # InteractiveShell:
95 # InteractiveShell:
96
96
97 IP = shell_class('__IP',user_ns=user_ns,user_global_ns=user_global_ns,
97 IP = shell_class('__IP',user_ns=user_ns,user_global_ns=user_global_ns,
98 embedded=embedded,**kw)
98 embedded=embedded,**kw)
99
99
100 # Put 'help' in the user namespace
100 # Put 'help' in the user namespace
101 try:
101 try:
102 from site import _Helper
102 from site import _Helper
103 IP.user_ns['help'] = _Helper()
103 IP.user_ns['help'] = _Helper()
104 except ImportError:
104 except ImportError:
105 warn('help() not available - check site.py')
105 warn('help() not available - check site.py')
106
106
107 if DEVDEBUG:
107 if DEVDEBUG:
108 # For developer debugging only (global flag)
108 # For developer debugging only (global flag)
109 from IPython import ultraTB
109 from IPython import ultraTB
110 sys.excepthook = ultraTB.VerboseTB(call_pdb=1)
110 sys.excepthook = ultraTB.VerboseTB(call_pdb=1)
111
111
112 IP.BANNER_PARTS = ['Python %s\n'
112 IP.BANNER_PARTS = ['Python %s\n'
113 'Type "copyright", "credits" or "license" '
113 'Type "copyright", "credits" or "license" '
114 'for more information.\n'
114 'for more information.\n'
115 % (sys.version.split('\n')[0],),
115 % (sys.version.split('\n')[0],),
116 "IPython %s -- An enhanced Interactive Python."
116 "IPython %s -- An enhanced Interactive Python."
117 % (Release.version,),
117 % (release.version,),
118 """\
118 """\
119 ? -> Introduction and overview of IPython's features.
119 ? -> Introduction and overview of IPython's features.
120 %quickref -> Quick reference.
120 %quickref -> Quick reference.
121 help -> Python's own help system.
121 help -> Python's own help system.
122 object? -> Details about 'object'. ?object also works, ?? prints more.
122 object? -> Details about 'object'. ?object also works, ?? prints more.
123 """ ]
123 """ ]
124
124
125 IP.usage = interactive_usage
125 IP.usage = interactive_usage
126
126
127 # Platform-dependent suffix.
127 # Platform-dependent suffix.
128 if os.name == 'posix':
128 if os.name == 'posix':
129 rc_suffix = ''
129 rc_suffix = ''
130 else:
130 else:
131 rc_suffix = '.ini'
131 rc_suffix = '.ini'
132
132
133 # default directory for configuration
133 # default directory for configuration
134 ipythondir_def = get_ipython_dir()
134 ipythondir_def = get_ipython_dir()
135
135
136 sys.path.insert(0, '') # add . to sys.path. Fix from Prabhu Ramachandran
136 sys.path.insert(0, '') # add . to sys.path. Fix from Prabhu Ramachandran
137
137
138 # we need the directory where IPython itself is installed
138 # we need the directory where IPython itself is installed
139 import IPython
139 import IPython
140 IPython_dir = os.path.dirname(IPython.__file__)
140 IPython_dir = os.path.dirname(IPython.__file__)
141 del IPython
141 del IPython
142
142
143 #-------------------------------------------------------------------------
143 #-------------------------------------------------------------------------
144 # Command line handling
144 # Command line handling
145
145
146 # Valid command line options (uses DPyGetOpt syntax, like Perl's
146 # Valid command line options (uses DPyGetOpt syntax, like Perl's
147 # GetOpt::Long)
147 # GetOpt::Long)
148
148
149 # Any key not listed here gets deleted even if in the file (like session
149 # Any key not listed here gets deleted even if in the file (like session
150 # or profile). That's deliberate, to maintain the rc namespace clean.
150 # or profile). That's deliberate, to maintain the rc namespace clean.
151
151
152 # Each set of options appears twice: under _conv only the names are
152 # Each set of options appears twice: under _conv only the names are
153 # listed, indicating which type they must be converted to when reading the
153 # listed, indicating which type they must be converted to when reading the
154 # ipythonrc file. And under DPyGetOpt they are listed with the regular
154 # ipythonrc file. And under DPyGetOpt they are listed with the regular
155 # DPyGetOpt syntax (=s,=i,:f,etc).
155 # DPyGetOpt syntax (=s,=i,:f,etc).
156
156
157 # Make sure there's a space before each end of line (they get auto-joined!)
157 # Make sure there's a space before each end of line (they get auto-joined!)
158 cmdline_opts = ('autocall=i autoindent! automagic! banner! cache_size|cs=i '
158 cmdline_opts = ('autocall=i autoindent! automagic! banner! cache_size|cs=i '
159 'c=s classic|cl color_info! colors=s confirm_exit! '
159 'c=s classic|cl color_info! colors=s confirm_exit! '
160 'debug! deep_reload! editor=s log|l messages! nosep '
160 'debug! deep_reload! editor=s log|l messages! nosep '
161 'object_info_string_level=i pdb! '
161 'object_info_string_level=i pdb! '
162 'pprint! prompt_in1|pi1=s prompt_in2|pi2=s prompt_out|po=s '
162 'pprint! prompt_in1|pi1=s prompt_in2|pi2=s prompt_out|po=s '
163 'pydb! '
163 'pydb! '
164 'pylab_import_all! '
164 'pylab_import_all! '
165 'quick screen_length|sl=i prompts_pad_left=i '
165 'quick screen_length|sl=i prompts_pad_left=i '
166 'logfile|lf=s logplay|lp=s profile|p=s '
166 'logfile|lf=s logplay|lp=s profile|p=s '
167 'readline! readline_merge_completions! '
167 'readline! readline_merge_completions! '
168 'readline_omit__names! '
168 'readline_omit__names! '
169 'rcfile=s separate_in|si=s separate_out|so=s '
169 'rcfile=s separate_in|si=s separate_out|so=s '
170 'separate_out2|so2=s xmode=s wildcards_case_sensitive! '
170 'separate_out2|so2=s xmode=s wildcards_case_sensitive! '
171 'magic_docstrings system_verbose! '
171 'magic_docstrings system_verbose! '
172 'multi_line_specials! '
172 'multi_line_specials! '
173 'term_title! wxversion=s '
173 'term_title! wxversion=s '
174 'autoedit_syntax!')
174 'autoedit_syntax!')
175
175
176 # Options that can *only* appear at the cmd line (not in rcfiles).
176 # Options that can *only* appear at the cmd line (not in rcfiles).
177
177
178 cmdline_only = ('help interact|i ipythondir=s Version upgrade '
178 cmdline_only = ('help interact|i ipythondir=s Version upgrade '
179 'gthread! qthread! q4thread! wthread! tkthread! pylab! tk! '
179 'gthread! qthread! q4thread! wthread! tkthread! pylab! tk! '
180 # 'twisted!' # disabled for now.
180 # 'twisted!' # disabled for now.
181 )
181 )
182
182
183 # Build the actual name list to be used by DPyGetOpt
183 # Build the actual name list to be used by DPyGetOpt
184 opts_names = qw(cmdline_opts) + qw(cmdline_only)
184 opts_names = qw(cmdline_opts) + qw(cmdline_only)
185
185
186 # Set sensible command line defaults.
186 # Set sensible command line defaults.
187 # This should have everything from cmdline_opts and cmdline_only
187 # This should have everything from cmdline_opts and cmdline_only
188 opts_def = Struct(autocall = 1,
188 opts_def = Struct(autocall = 1,
189 autoedit_syntax = 0,
189 autoedit_syntax = 0,
190 autoindent = 0,
190 autoindent = 0,
191 automagic = 1,
191 automagic = 1,
192 autoexec = [],
192 autoexec = [],
193 banner = 1,
193 banner = 1,
194 c = '',
194 c = '',
195 cache_size = 1000,
195 cache_size = 1000,
196 classic = 0,
196 classic = 0,
197 color_info = 0,
197 color_info = 0,
198 colors = 'NoColor',
198 colors = 'NoColor',
199 confirm_exit = 1,
199 confirm_exit = 1,
200 debug = 0,
200 debug = 0,
201 deep_reload = 0,
201 deep_reload = 0,
202 editor = '0',
202 editor = '0',
203 gthread = 0,
203 gthread = 0,
204 help = 0,
204 help = 0,
205 interact = 0,
205 interact = 0,
206 ipythondir = ipythondir_def,
206 ipythondir = ipythondir_def,
207 log = 0,
207 log = 0,
208 logfile = '',
208 logfile = '',
209 logplay = '',
209 logplay = '',
210 messages = 1,
210 messages = 1,
211 multi_line_specials = 1,
211 multi_line_specials = 1,
212 nosep = 0,
212 nosep = 0,
213 object_info_string_level = 0,
213 object_info_string_level = 0,
214 pdb = 0,
214 pdb = 0,
215 pprint = 0,
215 pprint = 0,
216 profile = '',
216 profile = '',
217 prompt_in1 = 'In [\\#]: ',
217 prompt_in1 = 'In [\\#]: ',
218 prompt_in2 = ' .\\D.: ',
218 prompt_in2 = ' .\\D.: ',
219 prompt_out = 'Out[\\#]: ',
219 prompt_out = 'Out[\\#]: ',
220 prompts_pad_left = 1,
220 prompts_pad_left = 1,
221 pydb = 0,
221 pydb = 0,
222 pylab = 0,
222 pylab = 0,
223 pylab_import_all = 1,
223 pylab_import_all = 1,
224 q4thread = 0,
224 q4thread = 0,
225 qthread = 0,
225 qthread = 0,
226 quick = 0,
226 quick = 0,
227 quiet = 0,
227 quiet = 0,
228 rcfile = 'ipythonrc' + rc_suffix,
228 rcfile = 'ipythonrc' + rc_suffix,
229 readline = 1,
229 readline = 1,
230 readline_merge_completions = 1,
230 readline_merge_completions = 1,
231 readline_omit__names = 0,
231 readline_omit__names = 0,
232 screen_length = 0,
232 screen_length = 0,
233 separate_in = '\n',
233 separate_in = '\n',
234 separate_out = '\n',
234 separate_out = '\n',
235 separate_out2 = '',
235 separate_out2 = '',
236 system_header = 'IPython system call: ',
236 system_header = 'IPython system call: ',
237 system_verbose = 0,
237 system_verbose = 0,
238 term_title = 1,
238 term_title = 1,
239 tk = 0,
239 tk = 0,
240 #twisted= 0, # disabled for now
240 #twisted= 0, # disabled for now
241 upgrade = 0,
241 upgrade = 0,
242 Version = 0,
242 Version = 0,
243 wildcards_case_sensitive = 1,
243 wildcards_case_sensitive = 1,
244 wthread = 0,
244 wthread = 0,
245 wxversion = '0',
245 wxversion = '0',
246 xmode = 'Context',
246 xmode = 'Context',
247 magic_docstrings = 0, # undocumented, for doc generation
247 magic_docstrings = 0, # undocumented, for doc generation
248 )
248 )
249
249
250 # Things that will *only* appear in rcfiles (not at the command line).
250 # Things that will *only* appear in rcfiles (not at the command line).
251 # Make sure there's a space before each end of line (they get auto-joined!)
251 # Make sure there's a space before each end of line (they get auto-joined!)
252 rcfile_opts = { qwflat: 'include import_mod import_all execfile ',
252 rcfile_opts = { qwflat: 'include import_mod import_all execfile ',
253 qw_lol: 'import_some ',
253 qw_lol: 'import_some ',
254 # for things with embedded whitespace:
254 # for things with embedded whitespace:
255 list_strings:'execute alias readline_parse_and_bind ',
255 list_strings:'execute alias readline_parse_and_bind ',
256 # Regular strings need no conversion:
256 # Regular strings need no conversion:
257 None:'readline_remove_delims ',
257 None:'readline_remove_delims ',
258 }
258 }
259 # Default values for these
259 # Default values for these
260 rc_def = Struct(include = [],
260 rc_def = Struct(include = [],
261 import_mod = [],
261 import_mod = [],
262 import_all = [],
262 import_all = [],
263 import_some = [[]],
263 import_some = [[]],
264 execute = [],
264 execute = [],
265 execfile = [],
265 execfile = [],
266 alias = [],
266 alias = [],
267 readline_parse_and_bind = [],
267 readline_parse_and_bind = [],
268 readline_remove_delims = '',
268 readline_remove_delims = '',
269 )
269 )
270
270
271 # Build the type conversion dictionary from the above tables:
271 # Build the type conversion dictionary from the above tables:
272 typeconv = rcfile_opts.copy()
272 typeconv = rcfile_opts.copy()
273 typeconv.update(optstr2types(cmdline_opts))
273 typeconv.update(optstr2types(cmdline_opts))
274
274
275 # FIXME: the None key appears in both, put that back together by hand. Ugly!
275 # FIXME: the None key appears in both, put that back together by hand. Ugly!
276 typeconv[None] += ' ' + rcfile_opts[None]
276 typeconv[None] += ' ' + rcfile_opts[None]
277
277
278 # Remove quotes at ends of all strings (used to protect spaces)
278 # Remove quotes at ends of all strings (used to protect spaces)
279 typeconv[unquote_ends] = typeconv[None]
279 typeconv[unquote_ends] = typeconv[None]
280 del typeconv[None]
280 del typeconv[None]
281
281
282 # Build the list we'll use to make all config decisions with defaults:
282 # Build the list we'll use to make all config decisions with defaults:
283 opts_all = opts_def.copy()
283 opts_all = opts_def.copy()
284 opts_all.update(rc_def)
284 opts_all.update(rc_def)
285
285
286 # Build conflict resolver for recursive loading of config files:
286 # Build conflict resolver for recursive loading of config files:
287 # - preserve means the outermost file maintains the value, it is not
287 # - preserve means the outermost file maintains the value, it is not
288 # overwritten if an included file has the same key.
288 # overwritten if an included file has the same key.
289 # - add_flip applies + to the two values, so it better make sense to add
289 # - add_flip applies + to the two values, so it better make sense to add
290 # those types of keys. But it flips them first so that things loaded
290 # those types of keys. But it flips them first so that things loaded
291 # deeper in the inclusion chain have lower precedence.
291 # deeper in the inclusion chain have lower precedence.
292 conflict = {'preserve': ' '.join([ typeconv[int],
292 conflict = {'preserve': ' '.join([ typeconv[int],
293 typeconv[unquote_ends] ]),
293 typeconv[unquote_ends] ]),
294 'add_flip': ' '.join([ typeconv[qwflat],
294 'add_flip': ' '.join([ typeconv[qwflat],
295 typeconv[qw_lol],
295 typeconv[qw_lol],
296 typeconv[list_strings] ])
296 typeconv[list_strings] ])
297 }
297 }
298
298
299 # Now actually process the command line
299 # Now actually process the command line
300 getopt = DPyGetOpt.DPyGetOpt()
300 getopt = DPyGetOpt.DPyGetOpt()
301 getopt.setIgnoreCase(0)
301 getopt.setIgnoreCase(0)
302
302
303 getopt.parseConfiguration(opts_names)
303 getopt.parseConfiguration(opts_names)
304
304
305 try:
305 try:
306 getopt.processArguments(argv)
306 getopt.processArguments(argv)
307 except DPyGetOpt.ArgumentError, exc:
307 except DPyGetOpt.ArgumentError, exc:
308 print cmd_line_usage
308 print cmd_line_usage
309 warn('\nError in Arguments: "%s"' % exc)
309 warn('\nError in Arguments: "%s"' % exc)
310 sys.exit(1)
310 sys.exit(1)
311
311
312 # convert the options dict to a struct for much lighter syntax later
312 # convert the options dict to a struct for much lighter syntax later
313 opts = Struct(getopt.optionValues)
313 opts = Struct(getopt.optionValues)
314 args = getopt.freeValues
314 args = getopt.freeValues
315
315
316 # this is the struct (which has default values at this point) with which
316 # this is the struct (which has default values at this point) with which
317 # we make all decisions:
317 # we make all decisions:
318 opts_all.update(opts)
318 opts_all.update(opts)
319
319
320 # Options that force an immediate exit
320 # Options that force an immediate exit
321 if opts_all.help:
321 if opts_all.help:
322 page(cmd_line_usage)
322 page(cmd_line_usage)
323 sys.exit()
323 sys.exit()
324
324
325 if opts_all.Version:
325 if opts_all.Version:
326 print Release.version
326 print release.version
327 sys.exit()
327 sys.exit()
328
328
329 if opts_all.magic_docstrings:
329 if opts_all.magic_docstrings:
330 IP.magic_magic('-latex')
330 IP.magic_magic('-latex')
331 sys.exit()
331 sys.exit()
332
332
333 # add personal ipythondir to sys.path so that users can put things in
333 # add personal ipythondir to sys.path so that users can put things in
334 # there for customization
334 # there for customization
335 sys.path.append(os.path.abspath(opts_all.ipythondir))
335 sys.path.append(os.path.abspath(opts_all.ipythondir))
336
336
337 # Create user config directory if it doesn't exist. This must be done
337 # Create user config directory if it doesn't exist. This must be done
338 # *after* getting the cmd line options.
338 # *after* getting the cmd line options.
339 if not os.path.isdir(opts_all.ipythondir):
339 if not os.path.isdir(opts_all.ipythondir):
340 IP.user_setup(opts_all.ipythondir,rc_suffix,'install')
340 IP.user_setup(opts_all.ipythondir,rc_suffix,'install')
341
341
342 # upgrade user config files while preserving a copy of the originals
342 # upgrade user config files while preserving a copy of the originals
343 if opts_all.upgrade:
343 if opts_all.upgrade:
344 IP.user_setup(opts_all.ipythondir,rc_suffix,'upgrade')
344 IP.user_setup(opts_all.ipythondir,rc_suffix,'upgrade')
345
345
346 # check mutually exclusive options in the *original* command line
346 # check mutually exclusive options in the *original* command line
347 mutex_opts(opts,[qw('log logfile'),qw('rcfile profile'),
347 mutex_opts(opts,[qw('log logfile'),qw('rcfile profile'),
348 qw('classic profile'),qw('classic rcfile')])
348 qw('classic profile'),qw('classic rcfile')])
349
349
350 #---------------------------------------------------------------------------
350 #---------------------------------------------------------------------------
351 # Log replay
351 # Log replay
352
352
353 # if -logplay, we need to 'become' the other session. That basically means
353 # if -logplay, we need to 'become' the other session. That basically means
354 # replacing the current command line environment with that of the old
354 # replacing the current command line environment with that of the old
355 # session and moving on.
355 # session and moving on.
356
356
357 # this is needed so that later we know we're in session reload mode, as
357 # this is needed so that later we know we're in session reload mode, as
358 # opts_all will get overwritten:
358 # opts_all will get overwritten:
359 load_logplay = 0
359 load_logplay = 0
360
360
361 if opts_all.logplay:
361 if opts_all.logplay:
362 load_logplay = opts_all.logplay
362 load_logplay = opts_all.logplay
363 opts_debug_save = opts_all.debug
363 opts_debug_save = opts_all.debug
364 try:
364 try:
365 logplay = open(opts_all.logplay)
365 logplay = open(opts_all.logplay)
366 except IOError:
366 except IOError:
367 if opts_all.debug: IP.InteractiveTB()
367 if opts_all.debug: IP.InteractiveTB()
368 warn('Could not open logplay file '+`opts_all.logplay`)
368 warn('Could not open logplay file '+`opts_all.logplay`)
369 # restore state as if nothing had happened and move on, but make
369 # restore state as if nothing had happened and move on, but make
370 # sure that later we don't try to actually load the session file
370 # sure that later we don't try to actually load the session file
371 logplay = None
371 logplay = None
372 load_logplay = 0
372 load_logplay = 0
373 del opts_all.logplay
373 del opts_all.logplay
374 else:
374 else:
375 try:
375 try:
376 logplay.readline()
376 logplay.readline()
377 logplay.readline();
377 logplay.readline();
378 # this reloads that session's command line
378 # this reloads that session's command line
379 cmd = logplay.readline()[6:]
379 cmd = logplay.readline()[6:]
380 exec cmd
380 exec cmd
381 # restore the true debug flag given so that the process of
381 # restore the true debug flag given so that the process of
382 # session loading itself can be monitored.
382 # session loading itself can be monitored.
383 opts.debug = opts_debug_save
383 opts.debug = opts_debug_save
384 # save the logplay flag so later we don't overwrite the log
384 # save the logplay flag so later we don't overwrite the log
385 opts.logplay = load_logplay
385 opts.logplay = load_logplay
386 # now we must update our own structure with defaults
386 # now we must update our own structure with defaults
387 opts_all.update(opts)
387 opts_all.update(opts)
388 # now load args
388 # now load args
389 cmd = logplay.readline()[6:]
389 cmd = logplay.readline()[6:]
390 exec cmd
390 exec cmd
391 logplay.close()
391 logplay.close()
392 except:
392 except:
393 logplay.close()
393 logplay.close()
394 if opts_all.debug: IP.InteractiveTB()
394 if opts_all.debug: IP.InteractiveTB()
395 warn("Logplay file lacking full configuration information.\n"
395 warn("Logplay file lacking full configuration information.\n"
396 "I'll try to read it, but some things may not work.")
396 "I'll try to read it, but some things may not work.")
397
397
398 #-------------------------------------------------------------------------
398 #-------------------------------------------------------------------------
399 # set up output traps: catch all output from files, being run, modules
399 # set up output traps: catch all output from files, being run, modules
400 # loaded, etc. Then give it to the user in a clean form at the end.
400 # loaded, etc. Then give it to the user in a clean form at the end.
401
401
402 msg_out = 'Output messages. '
402 msg_out = 'Output messages. '
403 msg_err = 'Error messages. '
403 msg_err = 'Error messages. '
404 msg_sep = '\n'
404 msg_sep = '\n'
405 msg = Struct(config = OutputTrap('Configuration Loader',msg_out,
405 msg = Struct(config = OutputTrap('Configuration Loader',msg_out,
406 msg_err,msg_sep,debug,
406 msg_err,msg_sep,debug,
407 quiet_out=1),
407 quiet_out=1),
408 user_exec = OutputTrap('User File Execution',msg_out,
408 user_exec = OutputTrap('User File Execution',msg_out,
409 msg_err,msg_sep,debug),
409 msg_err,msg_sep,debug),
410 logplay = OutputTrap('Log Loader',msg_out,
410 logplay = OutputTrap('Log Loader',msg_out,
411 msg_err,msg_sep,debug),
411 msg_err,msg_sep,debug),
412 summary = ''
412 summary = ''
413 )
413 )
414
414
415 #-------------------------------------------------------------------------
415 #-------------------------------------------------------------------------
416 # Process user ipythonrc-type configuration files
416 # Process user ipythonrc-type configuration files
417
417
418 # turn on output trapping and log to msg.config
418 # turn on output trapping and log to msg.config
419 # remember that with debug on, trapping is actually disabled
419 # remember that with debug on, trapping is actually disabled
420 msg.config.trap_all()
420 msg.config.trap_all()
421
421
422 # look for rcfile in current or default directory
422 # look for rcfile in current or default directory
423 try:
423 try:
424 opts_all.rcfile = filefind(opts_all.rcfile,opts_all.ipythondir)
424 opts_all.rcfile = filefind(opts_all.rcfile,opts_all.ipythondir)
425 except IOError:
425 except IOError:
426 if opts_all.debug: IP.InteractiveTB()
426 if opts_all.debug: IP.InteractiveTB()
427 warn('Configuration file %s not found. Ignoring request.'
427 warn('Configuration file %s not found. Ignoring request.'
428 % (opts_all.rcfile) )
428 % (opts_all.rcfile) )
429
429
430 # 'profiles' are a shorthand notation for config filenames
430 # 'profiles' are a shorthand notation for config filenames
431 profile_handled_by_legacy = False
431 profile_handled_by_legacy = False
432 if opts_all.profile:
432 if opts_all.profile:
433
433
434 try:
434 try:
435 opts_all.rcfile = filefind('ipythonrc-' + opts_all.profile
435 opts_all.rcfile = filefind('ipythonrc-' + opts_all.profile
436 + rc_suffix,
436 + rc_suffix,
437 opts_all.ipythondir)
437 opts_all.ipythondir)
438 profile_handled_by_legacy = True
438 profile_handled_by_legacy = True
439 except IOError:
439 except IOError:
440 if opts_all.debug: IP.InteractiveTB()
440 if opts_all.debug: IP.InteractiveTB()
441 opts.profile = '' # remove profile from options if invalid
441 opts.profile = '' # remove profile from options if invalid
442 # We won't warn anymore, primary method is ipy_profile_PROFNAME
442 # We won't warn anymore, primary method is ipy_profile_PROFNAME
443 # which does trigger a warning.
443 # which does trigger a warning.
444
444
445 # load the config file
445 # load the config file
446 rcfiledata = None
446 rcfiledata = None
447 if opts_all.quick:
447 if opts_all.quick:
448 print 'Launching IPython in quick mode. No config file read.'
448 print 'Launching IPython in quick mode. No config file read.'
449 elif opts_all.rcfile:
449 elif opts_all.rcfile:
450 try:
450 try:
451 cfg_loader = ConfigLoader(conflict)
451 cfg_loader = ConfigLoader(conflict)
452 rcfiledata = cfg_loader.load(opts_all.rcfile,typeconv,
452 rcfiledata = cfg_loader.load(opts_all.rcfile,typeconv,
453 'include',opts_all.ipythondir,
453 'include',opts_all.ipythondir,
454 purge = 1,
454 purge = 1,
455 unique = conflict['preserve'])
455 unique = conflict['preserve'])
456 except:
456 except:
457 IP.InteractiveTB()
457 IP.InteractiveTB()
458 warn('Problems loading configuration file '+
458 warn('Problems loading configuration file '+
459 `opts_all.rcfile`+
459 `opts_all.rcfile`+
460 '\nStarting with default -bare bones- configuration.')
460 '\nStarting with default -bare bones- configuration.')
461 else:
461 else:
462 warn('No valid configuration file found in either currrent directory\n'+
462 warn('No valid configuration file found in either currrent directory\n'+
463 'or in the IPython config. directory: '+`opts_all.ipythondir`+
463 'or in the IPython config. directory: '+`opts_all.ipythondir`+
464 '\nProceeding with internal defaults.')
464 '\nProceeding with internal defaults.')
465
465
466 #------------------------------------------------------------------------
466 #------------------------------------------------------------------------
467 # Set exception handlers in mode requested by user.
467 # Set exception handlers in mode requested by user.
468 otrap = OutputTrap(trap_out=1) # trap messages from magic_xmode
468 otrap = OutputTrap(trap_out=1) # trap messages from magic_xmode
469 IP.magic_xmode(opts_all.xmode)
469 IP.magic_xmode(opts_all.xmode)
470 otrap.release_out()
470 otrap.release_out()
471
471
472 #------------------------------------------------------------------------
472 #------------------------------------------------------------------------
473 # Execute user config
473 # Execute user config
474
474
475 # Create a valid config structure with the right precedence order:
475 # Create a valid config structure with the right precedence order:
476 # defaults < rcfile < command line. This needs to be in the instance, so
476 # defaults < rcfile < command line. This needs to be in the instance, so
477 # that method calls below that rely on it find it.
477 # that method calls below that rely on it find it.
478 IP.rc = rc_def.copy()
478 IP.rc = rc_def.copy()
479
479
480 # Work with a local alias inside this routine to avoid unnecessary
480 # Work with a local alias inside this routine to avoid unnecessary
481 # attribute lookups.
481 # attribute lookups.
482 IP_rc = IP.rc
482 IP_rc = IP.rc
483
483
484 IP_rc.update(opts_def)
484 IP_rc.update(opts_def)
485 if rcfiledata:
485 if rcfiledata:
486 # now we can update
486 # now we can update
487 IP_rc.update(rcfiledata)
487 IP_rc.update(rcfiledata)
488 IP_rc.update(opts)
488 IP_rc.update(opts)
489 IP_rc.update(rc_override)
489 IP_rc.update(rc_override)
490
490
491 # Store the original cmd line for reference:
491 # Store the original cmd line for reference:
492 IP_rc.opts = opts
492 IP_rc.opts = opts
493 IP_rc.args = args
493 IP_rc.args = args
494
494
495 # create a *runtime* Struct like rc for holding parameters which may be
495 # create a *runtime* Struct like rc for holding parameters which may be
496 # created and/or modified by runtime user extensions.
496 # created and/or modified by runtime user extensions.
497 IP.runtime_rc = Struct()
497 IP.runtime_rc = Struct()
498
498
499 # from this point on, all config should be handled through IP_rc,
499 # from this point on, all config should be handled through IP_rc,
500 # opts* shouldn't be used anymore.
500 # opts* shouldn't be used anymore.
501
501
502
502
503 # update IP_rc with some special things that need manual
503 # update IP_rc with some special things that need manual
504 # tweaks. Basically options which affect other options. I guess this
504 # tweaks. Basically options which affect other options. I guess this
505 # should just be written so that options are fully orthogonal and we
505 # should just be written so that options are fully orthogonal and we
506 # wouldn't worry about this stuff!
506 # wouldn't worry about this stuff!
507
507
508 if IP_rc.classic:
508 if IP_rc.classic:
509 IP_rc.quick = 1
509 IP_rc.quick = 1
510 IP_rc.cache_size = 0
510 IP_rc.cache_size = 0
511 IP_rc.pprint = 0
511 IP_rc.pprint = 0
512 IP_rc.prompt_in1 = '>>> '
512 IP_rc.prompt_in1 = '>>> '
513 IP_rc.prompt_in2 = '... '
513 IP_rc.prompt_in2 = '... '
514 IP_rc.prompt_out = ''
514 IP_rc.prompt_out = ''
515 IP_rc.separate_in = IP_rc.separate_out = IP_rc.separate_out2 = '0'
515 IP_rc.separate_in = IP_rc.separate_out = IP_rc.separate_out2 = '0'
516 IP_rc.colors = 'NoColor'
516 IP_rc.colors = 'NoColor'
517 IP_rc.xmode = 'Plain'
517 IP_rc.xmode = 'Plain'
518
518
519 IP.pre_config_initialization()
519 IP.pre_config_initialization()
520 # configure readline
520 # configure readline
521
521
522 # update exception handlers with rc file status
522 # update exception handlers with rc file status
523 otrap.trap_out() # I don't want these messages ever.
523 otrap.trap_out() # I don't want these messages ever.
524 IP.magic_xmode(IP_rc.xmode)
524 IP.magic_xmode(IP_rc.xmode)
525 otrap.release_out()
525 otrap.release_out()
526
526
527 # activate logging if requested and not reloading a log
527 # activate logging if requested and not reloading a log
528 if IP_rc.logplay:
528 if IP_rc.logplay:
529 IP.magic_logstart(IP_rc.logplay + ' append')
529 IP.magic_logstart(IP_rc.logplay + ' append')
530 elif IP_rc.logfile:
530 elif IP_rc.logfile:
531 IP.magic_logstart(IP_rc.logfile)
531 IP.magic_logstart(IP_rc.logfile)
532 elif IP_rc.log:
532 elif IP_rc.log:
533 IP.magic_logstart()
533 IP.magic_logstart()
534
534
535 # find user editor so that it we don't have to look it up constantly
535 # find user editor so that it we don't have to look it up constantly
536 if IP_rc.editor.strip()=='0':
536 if IP_rc.editor.strip()=='0':
537 try:
537 try:
538 ed = os.environ['EDITOR']
538 ed = os.environ['EDITOR']
539 except KeyError:
539 except KeyError:
540 if os.name == 'posix':
540 if os.name == 'posix':
541 ed = 'vi' # the only one guaranteed to be there!
541 ed = 'vi' # the only one guaranteed to be there!
542 else:
542 else:
543 ed = 'notepad' # same in Windows!
543 ed = 'notepad' # same in Windows!
544 IP_rc.editor = ed
544 IP_rc.editor = ed
545
545
546 # Keep track of whether this is an embedded instance or not (useful for
546 # Keep track of whether this is an embedded instance or not (useful for
547 # post-mortems).
547 # post-mortems).
548 IP_rc.embedded = IP.embedded
548 IP_rc.embedded = IP.embedded
549
549
550 # Recursive reload
550 # Recursive reload
551 try:
551 try:
552 from IPython.lib import deepreload
552 from IPython.lib import deepreload
553 if IP_rc.deep_reload:
553 if IP_rc.deep_reload:
554 __builtin__.reload = deepreload.reload
554 __builtin__.reload = deepreload.reload
555 else:
555 else:
556 __builtin__.dreload = deepreload.reload
556 __builtin__.dreload = deepreload.reload
557 del deepreload
557 del deepreload
558 except ImportError:
558 except ImportError:
559 pass
559 pass
560
560
561 # Save the current state of our namespace so that the interactive shell
561 # Save the current state of our namespace so that the interactive shell
562 # can later know which variables have been created by us from config files
562 # can later know which variables have been created by us from config files
563 # and loading. This way, loading a file (in any way) is treated just like
563 # and loading. This way, loading a file (in any way) is treated just like
564 # defining things on the command line, and %who works as expected.
564 # defining things on the command line, and %who works as expected.
565
565
566 # DON'T do anything that affects the namespace beyond this point!
566 # DON'T do anything that affects the namespace beyond this point!
567 IP.internal_ns.update(__main__.__dict__)
567 IP.internal_ns.update(__main__.__dict__)
568
568
569 #IP.internal_ns.update(locals()) # so our stuff doesn't show up in %who
569 #IP.internal_ns.update(locals()) # so our stuff doesn't show up in %who
570
570
571 # Now run through the different sections of the users's config
571 # Now run through the different sections of the users's config
572 if IP_rc.debug:
572 if IP_rc.debug:
573 print 'Trying to execute the following configuration structure:'
573 print 'Trying to execute the following configuration structure:'
574 print '(Things listed first are deeper in the inclusion tree and get'
574 print '(Things listed first are deeper in the inclusion tree and get'
575 print 'loaded first).\n'
575 print 'loaded first).\n'
576 pprint(IP_rc.__dict__)
576 pprint(IP_rc.__dict__)
577
577
578 for mod in IP_rc.import_mod:
578 for mod in IP_rc.import_mod:
579 try:
579 try:
580 exec 'import '+mod in IP.user_ns
580 exec 'import '+mod in IP.user_ns
581 except :
581 except :
582 IP.InteractiveTB()
582 IP.InteractiveTB()
583 import_fail_info(mod)
583 import_fail_info(mod)
584
584
585 for mod_fn in IP_rc.import_some:
585 for mod_fn in IP_rc.import_some:
586 if not mod_fn == []:
586 if not mod_fn == []:
587 mod,fn = mod_fn[0],','.join(mod_fn[1:])
587 mod,fn = mod_fn[0],','.join(mod_fn[1:])
588 try:
588 try:
589 exec 'from '+mod+' import '+fn in IP.user_ns
589 exec 'from '+mod+' import '+fn in IP.user_ns
590 except :
590 except :
591 IP.InteractiveTB()
591 IP.InteractiveTB()
592 import_fail_info(mod,fn)
592 import_fail_info(mod,fn)
593
593
594 for mod in IP_rc.import_all:
594 for mod in IP_rc.import_all:
595 try:
595 try:
596 exec 'from '+mod+' import *' in IP.user_ns
596 exec 'from '+mod+' import *' in IP.user_ns
597 except :
597 except :
598 IP.InteractiveTB()
598 IP.InteractiveTB()
599 import_fail_info(mod)
599 import_fail_info(mod)
600
600
601 for code in IP_rc.execute:
601 for code in IP_rc.execute:
602 try:
602 try:
603 exec code in IP.user_ns
603 exec code in IP.user_ns
604 except:
604 except:
605 IP.InteractiveTB()
605 IP.InteractiveTB()
606 warn('Failure executing code: ' + `code`)
606 warn('Failure executing code: ' + `code`)
607
607
608 # Execute the files the user wants in ipythonrc
608 # Execute the files the user wants in ipythonrc
609 for file in IP_rc.execfile:
609 for file in IP_rc.execfile:
610 try:
610 try:
611 file = filefind(file,sys.path+[IPython_dir])
611 file = filefind(file,sys.path+[IPython_dir])
612 except IOError:
612 except IOError:
613 warn(itpl('File $file not found. Skipping it.'))
613 warn(itpl('File $file not found. Skipping it.'))
614 else:
614 else:
615 IP.safe_execfile(os.path.expanduser(file),IP.user_ns)
615 IP.safe_execfile(os.path.expanduser(file),IP.user_ns)
616
616
617 # finally, try importing ipy_*_conf for final configuration
617 # finally, try importing ipy_*_conf for final configuration
618 try:
618 try:
619 import ipy_system_conf
619 import ipy_system_conf
620 except ImportError:
620 except ImportError:
621 if opts_all.debug: IP.InteractiveTB()
621 if opts_all.debug: IP.InteractiveTB()
622 warn("Could not import 'ipy_system_conf'")
622 warn("Could not import 'ipy_system_conf'")
623 except:
623 except:
624 IP.InteractiveTB()
624 IP.InteractiveTB()
625 import_fail_info('ipy_system_conf')
625 import_fail_info('ipy_system_conf')
626
626
627 # only import prof module if ipythonrc-PROF was not found
627 # only import prof module if ipythonrc-PROF was not found
628 if opts_all.profile and not profile_handled_by_legacy:
628 if opts_all.profile and not profile_handled_by_legacy:
629 profmodname = 'ipy_profile_' + opts_all.profile
629 profmodname = 'ipy_profile_' + opts_all.profile
630 try:
630 try:
631 force_import(profmodname)
631 force_import(profmodname)
632 except:
632 except:
633 IP.InteractiveTB()
633 IP.InteractiveTB()
634 print "Error importing",profmodname,\
634 print "Error importing",profmodname,\
635 "- perhaps you should run %upgrade?"
635 "- perhaps you should run %upgrade?"
636 import_fail_info(profmodname)
636 import_fail_info(profmodname)
637 else:
637 else:
638 opts.profile = opts_all.profile
638 opts.profile = opts_all.profile
639 else:
639 else:
640 force_import('ipy_profile_none')
640 force_import('ipy_profile_none')
641 # XXX - this is wrong: ipy_user_conf should not be loaded unconditionally,
641 # XXX - this is wrong: ipy_user_conf should not be loaded unconditionally,
642 # since the user could have specified a config file path by hand.
642 # since the user could have specified a config file path by hand.
643 try:
643 try:
644 force_import('ipy_user_conf')
644 force_import('ipy_user_conf')
645 except:
645 except:
646 conf = opts_all.ipythondir + "/ipy_user_conf.py"
646 conf = opts_all.ipythondir + "/ipy_user_conf.py"
647 IP.InteractiveTB()
647 IP.InteractiveTB()
648 if not os.path.isfile(conf):
648 if not os.path.isfile(conf):
649 warn(conf + ' does not exist, please run %upgrade!')
649 warn(conf + ' does not exist, please run %upgrade!')
650
650
651 import_fail_info("ipy_user_conf")
651 import_fail_info("ipy_user_conf")
652
652
653 # Define the history file for saving commands in between sessions
653 # Define the history file for saving commands in between sessions
654 try:
654 try:
655 histfname = 'history-%s' % opts.profile
655 histfname = 'history-%s' % opts.profile
656 except AttributeError:
656 except AttributeError:
657 histfname = 'history'
657 histfname = 'history'
658 IP.histfile = os.path.join(opts_all.ipythondir,histfname)
658 IP.histfile = os.path.join(opts_all.ipythondir,histfname)
659
659
660 # finally, push the argv to options again to ensure highest priority
660 # finally, push the argv to options again to ensure highest priority
661 IP_rc.update(opts)
661 IP_rc.update(opts)
662
662
663 # release stdout and stderr and save config log into a global summary
663 # release stdout and stderr and save config log into a global summary
664 msg.config.release_all()
664 msg.config.release_all()
665 if IP_rc.messages:
665 if IP_rc.messages:
666 msg.summary += msg.config.summary_all()
666 msg.summary += msg.config.summary_all()
667
667
668 #------------------------------------------------------------------------
668 #------------------------------------------------------------------------
669 # Setup interactive session
669 # Setup interactive session
670
670
671 # Now we should be fully configured. We can then execute files or load
671 # Now we should be fully configured. We can then execute files or load
672 # things only needed for interactive use. Then we'll open the shell.
672 # things only needed for interactive use. Then we'll open the shell.
673
673
674 # Take a snapshot of the user namespace before opening the shell. That way
674 # Take a snapshot of the user namespace before opening the shell. That way
675 # we'll be able to identify which things were interactively defined and
675 # we'll be able to identify which things were interactively defined and
676 # which were defined through config files.
676 # which were defined through config files.
677 IP.user_config_ns.update(IP.user_ns)
677 IP.user_config_ns.update(IP.user_ns)
678
678
679 # Force reading a file as if it were a session log. Slower but safer.
679 # Force reading a file as if it were a session log. Slower but safer.
680 if load_logplay:
680 if load_logplay:
681 print 'Replaying log...'
681 print 'Replaying log...'
682 try:
682 try:
683 if IP_rc.debug:
683 if IP_rc.debug:
684 logplay_quiet = 0
684 logplay_quiet = 0
685 else:
685 else:
686 logplay_quiet = 1
686 logplay_quiet = 1
687
687
688 msg.logplay.trap_all()
688 msg.logplay.trap_all()
689 IP.safe_execfile(load_logplay,IP.user_ns,
689 IP.safe_execfile(load_logplay,IP.user_ns,
690 islog = 1, quiet = logplay_quiet)
690 islog = 1, quiet = logplay_quiet)
691 msg.logplay.release_all()
691 msg.logplay.release_all()
692 if IP_rc.messages:
692 if IP_rc.messages:
693 msg.summary += msg.logplay.summary_all()
693 msg.summary += msg.logplay.summary_all()
694 except:
694 except:
695 warn('Problems replaying logfile %s.' % load_logplay)
695 warn('Problems replaying logfile %s.' % load_logplay)
696 IP.InteractiveTB()
696 IP.InteractiveTB()
697
697
698 # Load remaining files in command line
698 # Load remaining files in command line
699 msg.user_exec.trap_all()
699 msg.user_exec.trap_all()
700
700
701 # Do NOT execute files named in the command line as scripts to be loaded
701 # Do NOT execute files named in the command line as scripts to be loaded
702 # by embedded instances. Doing so has the potential for an infinite
702 # by embedded instances. Doing so has the potential for an infinite
703 # recursion if there are exceptions thrown in the process.
703 # recursion if there are exceptions thrown in the process.
704
704
705 # XXX FIXME: the execution of user files should be moved out to after
705 # XXX FIXME: the execution of user files should be moved out to after
706 # ipython is fully initialized, just as if they were run via %run at the
706 # ipython is fully initialized, just as if they were run via %run at the
707 # ipython prompt. This would also give them the benefit of ipython's
707 # ipython prompt. This would also give them the benefit of ipython's
708 # nice tracebacks.
708 # nice tracebacks.
709
709
710 if (not embedded and IP_rc.args and
710 if (not embedded and IP_rc.args and
711 not IP_rc.args[0].lower().endswith('.ipy')):
711 not IP_rc.args[0].lower().endswith('.ipy')):
712 name_save = IP.user_ns['__name__']
712 name_save = IP.user_ns['__name__']
713 IP.user_ns['__name__'] = '__main__'
713 IP.user_ns['__name__'] = '__main__'
714 # Set our own excepthook in case the user code tries to call it
714 # Set our own excepthook in case the user code tries to call it
715 # directly. This prevents triggering the IPython crash handler.
715 # directly. This prevents triggering the IPython crash handler.
716 old_excepthook,sys.excepthook = sys.excepthook, IP.excepthook
716 old_excepthook,sys.excepthook = sys.excepthook, IP.excepthook
717
717
718 save_argv = sys.argv[1:] # save it for later restoring
718 save_argv = sys.argv[1:] # save it for later restoring
719
719
720 sys.argv = args
720 sys.argv = args
721
721
722 try:
722 try:
723 IP.safe_execfile(args[0], IP.user_ns)
723 IP.safe_execfile(args[0], IP.user_ns)
724 finally:
724 finally:
725 # Reset our crash handler in place
725 # Reset our crash handler in place
726 sys.excepthook = old_excepthook
726 sys.excepthook = old_excepthook
727 sys.argv[:] = save_argv
727 sys.argv[:] = save_argv
728 IP.user_ns['__name__'] = name_save
728 IP.user_ns['__name__'] = name_save
729
729
730 msg.user_exec.release_all()
730 msg.user_exec.release_all()
731
731
732 if IP_rc.messages:
732 if IP_rc.messages:
733 msg.summary += msg.user_exec.summary_all()
733 msg.summary += msg.user_exec.summary_all()
734
734
735 # since we can't specify a null string on the cmd line, 0 is the equivalent:
735 # since we can't specify a null string on the cmd line, 0 is the equivalent:
736 if IP_rc.nosep:
736 if IP_rc.nosep:
737 IP_rc.separate_in = IP_rc.separate_out = IP_rc.separate_out2 = '0'
737 IP_rc.separate_in = IP_rc.separate_out = IP_rc.separate_out2 = '0'
738 if IP_rc.separate_in == '0': IP_rc.separate_in = ''
738 if IP_rc.separate_in == '0': IP_rc.separate_in = ''
739 if IP_rc.separate_out == '0': IP_rc.separate_out = ''
739 if IP_rc.separate_out == '0': IP_rc.separate_out = ''
740 if IP_rc.separate_out2 == '0': IP_rc.separate_out2 = ''
740 if IP_rc.separate_out2 == '0': IP_rc.separate_out2 = ''
741 IP_rc.separate_in = IP_rc.separate_in.replace('\\n','\n')
741 IP_rc.separate_in = IP_rc.separate_in.replace('\\n','\n')
742 IP_rc.separate_out = IP_rc.separate_out.replace('\\n','\n')
742 IP_rc.separate_out = IP_rc.separate_out.replace('\\n','\n')
743 IP_rc.separate_out2 = IP_rc.separate_out2.replace('\\n','\n')
743 IP_rc.separate_out2 = IP_rc.separate_out2.replace('\\n','\n')
744
744
745 # Determine how many lines at the bottom of the screen are needed for
745 # Determine how many lines at the bottom of the screen are needed for
746 # showing prompts, so we can know wheter long strings are to be printed or
746 # showing prompts, so we can know wheter long strings are to be printed or
747 # paged:
747 # paged:
748 num_lines_bot = IP_rc.separate_in.count('\n')+1
748 num_lines_bot = IP_rc.separate_in.count('\n')+1
749 IP_rc.screen_length = IP_rc.screen_length - num_lines_bot
749 IP_rc.screen_length = IP_rc.screen_length - num_lines_bot
750
750
751 # configure startup banner
751 # configure startup banner
752 if IP_rc.c: # regular python doesn't print the banner with -c
752 if IP_rc.c: # regular python doesn't print the banner with -c
753 IP_rc.banner = 0
753 IP_rc.banner = 0
754 if IP_rc.banner:
754 if IP_rc.banner:
755 BANN_P = IP.BANNER_PARTS
755 BANN_P = IP.BANNER_PARTS
756 else:
756 else:
757 BANN_P = []
757 BANN_P = []
758
758
759 if IP_rc.profile: BANN_P.append('IPython profile: %s\n' % IP_rc.profile)
759 if IP_rc.profile: BANN_P.append('IPython profile: %s\n' % IP_rc.profile)
760
760
761 # add message log (possibly empty)
761 # add message log (possibly empty)
762 if msg.summary: BANN_P.append(msg.summary)
762 if msg.summary: BANN_P.append(msg.summary)
763 # Final banner is a string
763 # Final banner is a string
764 IP.BANNER = '\n'.join(BANN_P)
764 IP.BANNER = '\n'.join(BANN_P)
765
765
766 # Finalize the IPython instance. This assumes the rc structure is fully
766 # Finalize the IPython instance. This assumes the rc structure is fully
767 # in place.
767 # in place.
768 IP.post_config_initialization()
768 IP.post_config_initialization()
769
769
770 return IP
770 return IP
771 #************************ end of file <ipmaker.py> **************************
771 #************************ end of file <ipmaker.py> **************************
@@ -1,627 +1,627
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.utils import coloransi
23 from IPython.utils import coloransi
24 from IPython import Release
24 from IPython.core import release
25 from IPython.external.Itpl import ItplNS
25 from IPython.external.Itpl import ItplNS
26 from IPython.core.ipapi import TryNext
26 from IPython.core.ipapi import TryNext
27 from IPython.utils.ipstruct import Struct
27 from IPython.utils.ipstruct import Struct
28 from IPython.core.macro import Macro
28 from IPython.core.macro import Macro
29 import IPython.utils.generics
29 import IPython.utils.generics
30
30
31 from IPython.utils.genutils import *
31 from IPython.utils.genutils import *
32
32
33 #****************************************************************************
33 #****************************************************************************
34 #Color schemes for Prompts.
34 #Color schemes for Prompts.
35
35
36 PromptColors = coloransi.ColorSchemeTable()
36 PromptColors = coloransi.ColorSchemeTable()
37 InputColors = coloransi.InputTermColors # just a shorthand
37 InputColors = coloransi.InputTermColors # just a shorthand
38 Colors = coloransi.TermColors # just a shorthand
38 Colors = coloransi.TermColors # just a shorthand
39
39
40 PromptColors.add_scheme(coloransi.ColorScheme(
40 PromptColors.add_scheme(coloransi.ColorScheme(
41 'NoColor',
41 'NoColor',
42 in_prompt = InputColors.NoColor, # Input prompt
42 in_prompt = InputColors.NoColor, # Input prompt
43 in_number = InputColors.NoColor, # Input prompt number
43 in_number = InputColors.NoColor, # Input prompt number
44 in_prompt2 = InputColors.NoColor, # Continuation prompt
44 in_prompt2 = InputColors.NoColor, # Continuation prompt
45 in_normal = InputColors.NoColor, # color off (usu. Colors.Normal)
45 in_normal = InputColors.NoColor, # color off (usu. Colors.Normal)
46
46
47 out_prompt = Colors.NoColor, # Output prompt
47 out_prompt = Colors.NoColor, # Output prompt
48 out_number = Colors.NoColor, # Output prompt number
48 out_number = Colors.NoColor, # Output prompt number
49
49
50 normal = Colors.NoColor # color off (usu. Colors.Normal)
50 normal = Colors.NoColor # color off (usu. Colors.Normal)
51 ))
51 ))
52
52
53 # make some schemes as instances so we can copy them for modification easily:
53 # make some schemes as instances so we can copy them for modification easily:
54 __PColLinux = coloransi.ColorScheme(
54 __PColLinux = coloransi.ColorScheme(
55 'Linux',
55 'Linux',
56 in_prompt = InputColors.Green,
56 in_prompt = InputColors.Green,
57 in_number = InputColors.LightGreen,
57 in_number = InputColors.LightGreen,
58 in_prompt2 = InputColors.Green,
58 in_prompt2 = InputColors.Green,
59 in_normal = InputColors.Normal, # color off (usu. Colors.Normal)
59 in_normal = InputColors.Normal, # color off (usu. Colors.Normal)
60
60
61 out_prompt = Colors.Red,
61 out_prompt = Colors.Red,
62 out_number = Colors.LightRed,
62 out_number = Colors.LightRed,
63
63
64 normal = Colors.Normal
64 normal = Colors.Normal
65 )
65 )
66 # Don't forget to enter it into the table!
66 # Don't forget to enter it into the table!
67 PromptColors.add_scheme(__PColLinux)
67 PromptColors.add_scheme(__PColLinux)
68
68
69 # Slightly modified Linux for light backgrounds
69 # Slightly modified Linux for light backgrounds
70 __PColLightBG = __PColLinux.copy('LightBG')
70 __PColLightBG = __PColLinux.copy('LightBG')
71
71
72 __PColLightBG.colors.update(
72 __PColLightBG.colors.update(
73 in_prompt = InputColors.Blue,
73 in_prompt = InputColors.Blue,
74 in_number = InputColors.LightBlue,
74 in_number = InputColors.LightBlue,
75 in_prompt2 = InputColors.Blue
75 in_prompt2 = InputColors.Blue
76 )
76 )
77 PromptColors.add_scheme(__PColLightBG)
77 PromptColors.add_scheme(__PColLightBG)
78
78
79 del Colors,InputColors
79 del Colors,InputColors
80
80
81 #-----------------------------------------------------------------------------
81 #-----------------------------------------------------------------------------
82 def multiple_replace(dict, text):
82 def multiple_replace(dict, text):
83 """ Replace in 'text' all occurences of any key in the given
83 """ Replace in 'text' all occurences of any key in the given
84 dictionary by its corresponding value. Returns the new string."""
84 dictionary by its corresponding value. Returns the new string."""
85
85
86 # Function by Xavier Defrang, originally found at:
86 # Function by Xavier Defrang, originally found at:
87 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
87 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
88
88
89 # Create a regular expression from the dictionary keys
89 # Create a regular expression from the dictionary keys
90 regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
90 regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
91 # For each match, look-up corresponding value in dictionary
91 # For each match, look-up corresponding value in dictionary
92 return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
92 return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
93
93
94 #-----------------------------------------------------------------------------
94 #-----------------------------------------------------------------------------
95 # Special characters that can be used in prompt templates, mainly bash-like
95 # Special characters that can be used in prompt templates, mainly bash-like
96
96
97 # If $HOME isn't defined (Windows), make it an absurd string so that it can
97 # If $HOME isn't defined (Windows), make it an absurd string so that it can
98 # never be expanded out into '~'. Basically anything which can never be a
98 # never be expanded out into '~'. Basically anything which can never be a
99 # reasonable directory name will do, we just want the $HOME -> '~' operation
99 # reasonable directory name will do, we just want the $HOME -> '~' operation
100 # to become a no-op. We pre-compute $HOME here so it's not done on every
100 # to become a no-op. We pre-compute $HOME here so it's not done on every
101 # prompt call.
101 # prompt call.
102
102
103 # FIXME:
103 # FIXME:
104
104
105 # - This should be turned into a class which does proper namespace management,
105 # - This should be turned into a class which does proper namespace management,
106 # since the prompt specials need to be evaluated in a certain namespace.
106 # since the prompt specials need to be evaluated in a certain namespace.
107 # Currently it's just globals, which need to be managed manually by code
107 # Currently it's just globals, which need to be managed manually by code
108 # below.
108 # below.
109
109
110 # - I also need to split up the color schemes from the prompt specials
110 # - I also need to split up the color schemes from the prompt specials
111 # somehow. I don't have a clean design for that quite yet.
111 # somehow. I don't have a clean design for that quite yet.
112
112
113 HOME = os.environ.get("HOME","//////:::::ZZZZZ,,,~~~")
113 HOME = os.environ.get("HOME","//////:::::ZZZZZ,,,~~~")
114
114
115 # We precompute a few more strings here for the prompt_specials, which are
115 # We precompute a few more strings here for the prompt_specials, which are
116 # fixed once ipython starts. This reduces the runtime overhead of computing
116 # fixed once ipython starts. This reduces the runtime overhead of computing
117 # prompt strings.
117 # prompt strings.
118 USER = os.environ.get("USER")
118 USER = os.environ.get("USER")
119 HOSTNAME = socket.gethostname()
119 HOSTNAME = socket.gethostname()
120 HOSTNAME_SHORT = HOSTNAME.split(".")[0]
120 HOSTNAME_SHORT = HOSTNAME.split(".")[0]
121 ROOT_SYMBOL = "$#"[os.name=='nt' or os.getuid()==0]
121 ROOT_SYMBOL = "$#"[os.name=='nt' or os.getuid()==0]
122
122
123 prompt_specials_color = {
123 prompt_specials_color = {
124 # Prompt/history count
124 # Prompt/history count
125 '%n' : '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
125 '%n' : '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
126 r'\#': '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
126 r'\#': '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
127 # Just the prompt counter number, WITHOUT any coloring wrappers, so users
127 # Just the prompt counter number, WITHOUT any coloring wrappers, so users
128 # can get numbers displayed in whatever color they want.
128 # can get numbers displayed in whatever color they want.
129 r'\N': '${self.cache.prompt_count}',
129 r'\N': '${self.cache.prompt_count}',
130
130
131 # Prompt/history count, with the actual digits replaced by dots. Used
131 # Prompt/history count, with the actual digits replaced by dots. Used
132 # mainly in continuation prompts (prompt_in2)
132 # mainly in continuation prompts (prompt_in2)
133 #r'\D': '${"."*len(str(self.cache.prompt_count))}',
133 #r'\D': '${"."*len(str(self.cache.prompt_count))}',
134 # More robust form of the above expression, that uses __builtins__
134 # More robust form of the above expression, that uses __builtins__
135 r'\D': '${"."*__builtins__.len(__builtins__.str(self.cache.prompt_count))}',
135 r'\D': '${"."*__builtins__.len(__builtins__.str(self.cache.prompt_count))}',
136
136
137 # Current working directory
137 # Current working directory
138 r'\w': '${os.getcwd()}',
138 r'\w': '${os.getcwd()}',
139 # Current time
139 # Current time
140 r'\t' : '${time.strftime("%H:%M:%S")}',
140 r'\t' : '${time.strftime("%H:%M:%S")}',
141 # Basename of current working directory.
141 # Basename of current working directory.
142 # (use os.sep to make this portable across OSes)
142 # (use os.sep to make this portable across OSes)
143 r'\W' : '${os.getcwd().split("%s")[-1]}' % os.sep,
143 r'\W' : '${os.getcwd().split("%s")[-1]}' % os.sep,
144 # These X<N> are an extension to the normal bash prompts. They return
144 # These X<N> are an extension to the normal bash prompts. They return
145 # N terms of the path, after replacing $HOME with '~'
145 # N terms of the path, after replacing $HOME with '~'
146 r'\X0': '${os.getcwd().replace("%s","~")}' % HOME,
146 r'\X0': '${os.getcwd().replace("%s","~")}' % HOME,
147 r'\X1': '${self.cwd_filt(1)}',
147 r'\X1': '${self.cwd_filt(1)}',
148 r'\X2': '${self.cwd_filt(2)}',
148 r'\X2': '${self.cwd_filt(2)}',
149 r'\X3': '${self.cwd_filt(3)}',
149 r'\X3': '${self.cwd_filt(3)}',
150 r'\X4': '${self.cwd_filt(4)}',
150 r'\X4': '${self.cwd_filt(4)}',
151 r'\X5': '${self.cwd_filt(5)}',
151 r'\X5': '${self.cwd_filt(5)}',
152 # Y<N> are similar to X<N>, but they show '~' if it's the directory
152 # Y<N> are similar to X<N>, but they show '~' if it's the directory
153 # N+1 in the list. Somewhat like %cN in tcsh.
153 # N+1 in the list. Somewhat like %cN in tcsh.
154 r'\Y0': '${self.cwd_filt2(0)}',
154 r'\Y0': '${self.cwd_filt2(0)}',
155 r'\Y1': '${self.cwd_filt2(1)}',
155 r'\Y1': '${self.cwd_filt2(1)}',
156 r'\Y2': '${self.cwd_filt2(2)}',
156 r'\Y2': '${self.cwd_filt2(2)}',
157 r'\Y3': '${self.cwd_filt2(3)}',
157 r'\Y3': '${self.cwd_filt2(3)}',
158 r'\Y4': '${self.cwd_filt2(4)}',
158 r'\Y4': '${self.cwd_filt2(4)}',
159 r'\Y5': '${self.cwd_filt2(5)}',
159 r'\Y5': '${self.cwd_filt2(5)}',
160 # Hostname up to first .
160 # Hostname up to first .
161 r'\h': HOSTNAME_SHORT,
161 r'\h': HOSTNAME_SHORT,
162 # Full hostname
162 # Full hostname
163 r'\H': HOSTNAME,
163 r'\H': HOSTNAME,
164 # Username of current user
164 # Username of current user
165 r'\u': USER,
165 r'\u': USER,
166 # Escaped '\'
166 # Escaped '\'
167 '\\\\': '\\',
167 '\\\\': '\\',
168 # Newline
168 # Newline
169 r'\n': '\n',
169 r'\n': '\n',
170 # Carriage return
170 # Carriage return
171 r'\r': '\r',
171 r'\r': '\r',
172 # Release version
172 # Release version
173 r'\v': Release.version,
173 r'\v': release.version,
174 # Root symbol ($ or #)
174 # Root symbol ($ or #)
175 r'\$': ROOT_SYMBOL,
175 r'\$': ROOT_SYMBOL,
176 }
176 }
177
177
178 # A copy of the prompt_specials dictionary but with all color escapes removed,
178 # A copy of the prompt_specials dictionary but with all color escapes removed,
179 # so we can correctly compute the prompt length for the auto_rewrite method.
179 # so we can correctly compute the prompt length for the auto_rewrite method.
180 prompt_specials_nocolor = prompt_specials_color.copy()
180 prompt_specials_nocolor = prompt_specials_color.copy()
181 prompt_specials_nocolor['%n'] = '${self.cache.prompt_count}'
181 prompt_specials_nocolor['%n'] = '${self.cache.prompt_count}'
182 prompt_specials_nocolor[r'\#'] = '${self.cache.prompt_count}'
182 prompt_specials_nocolor[r'\#'] = '${self.cache.prompt_count}'
183
183
184 # Add in all the InputTermColors color escapes as valid prompt characters.
184 # Add in all the InputTermColors color escapes as valid prompt characters.
185 # They all get added as \\C_COLORNAME, so that we don't have any conflicts
185 # They all get added as \\C_COLORNAME, so that we don't have any conflicts
186 # with a color name which may begin with a letter used by any other of the
186 # with a color name which may begin with a letter used by any other of the
187 # allowed specials. This of course means that \\C will never be allowed for
187 # allowed specials. This of course means that \\C will never be allowed for
188 # anything else.
188 # anything else.
189 input_colors = coloransi.InputTermColors
189 input_colors = coloransi.InputTermColors
190 for _color in dir(input_colors):
190 for _color in dir(input_colors):
191 if _color[0] != '_':
191 if _color[0] != '_':
192 c_name = r'\C_'+_color
192 c_name = r'\C_'+_color
193 prompt_specials_color[c_name] = getattr(input_colors,_color)
193 prompt_specials_color[c_name] = getattr(input_colors,_color)
194 prompt_specials_nocolor[c_name] = ''
194 prompt_specials_nocolor[c_name] = ''
195
195
196 # we default to no color for safety. Note that prompt_specials is a global
196 # we default to no color for safety. Note that prompt_specials is a global
197 # variable used by all prompt objects.
197 # variable used by all prompt objects.
198 prompt_specials = prompt_specials_nocolor
198 prompt_specials = prompt_specials_nocolor
199
199
200 #-----------------------------------------------------------------------------
200 #-----------------------------------------------------------------------------
201 def str_safe(arg):
201 def str_safe(arg):
202 """Convert to a string, without ever raising an exception.
202 """Convert to a string, without ever raising an exception.
203
203
204 If str(arg) fails, <ERROR: ... > is returned, where ... is the exception
204 If str(arg) fails, <ERROR: ... > is returned, where ... is the exception
205 error message."""
205 error message."""
206
206
207 try:
207 try:
208 out = str(arg)
208 out = str(arg)
209 except UnicodeError:
209 except UnicodeError:
210 try:
210 try:
211 out = arg.encode('utf_8','replace')
211 out = arg.encode('utf_8','replace')
212 except Exception,msg:
212 except Exception,msg:
213 # let's keep this little duplication here, so that the most common
213 # let's keep this little duplication here, so that the most common
214 # case doesn't suffer from a double try wrapping.
214 # case doesn't suffer from a double try wrapping.
215 out = '<ERROR: %s>' % msg
215 out = '<ERROR: %s>' % msg
216 except Exception,msg:
216 except Exception,msg:
217 out = '<ERROR: %s>' % msg
217 out = '<ERROR: %s>' % msg
218 return out
218 return out
219
219
220 class BasePrompt(object):
220 class BasePrompt(object):
221 """Interactive prompt similar to Mathematica's."""
221 """Interactive prompt similar to Mathematica's."""
222
222
223 def _get_p_template(self):
223 def _get_p_template(self):
224 return self._p_template
224 return self._p_template
225
225
226 def _set_p_template(self,val):
226 def _set_p_template(self,val):
227 self._p_template = val
227 self._p_template = val
228 self.set_p_str()
228 self.set_p_str()
229
229
230 p_template = property(_get_p_template,_set_p_template,
230 p_template = property(_get_p_template,_set_p_template,
231 doc='Template for prompt string creation')
231 doc='Template for prompt string creation')
232
232
233 def __init__(self,cache,sep,prompt,pad_left=False):
233 def __init__(self,cache,sep,prompt,pad_left=False):
234
234
235 # Hack: we access information about the primary prompt through the
235 # Hack: we access information about the primary prompt through the
236 # cache argument. We need this, because we want the secondary prompt
236 # cache argument. We need this, because we want the secondary prompt
237 # to be aligned with the primary one. Color table info is also shared
237 # to be aligned with the primary one. Color table info is also shared
238 # by all prompt classes through the cache. Nice OO spaghetti code!
238 # by all prompt classes through the cache. Nice OO spaghetti code!
239 self.cache = cache
239 self.cache = cache
240 self.sep = sep
240 self.sep = sep
241
241
242 # regexp to count the number of spaces at the end of a prompt
242 # regexp to count the number of spaces at the end of a prompt
243 # expression, useful for prompt auto-rewriting
243 # expression, useful for prompt auto-rewriting
244 self.rspace = re.compile(r'(\s*)$')
244 self.rspace = re.compile(r'(\s*)$')
245 # Flag to left-pad prompt strings to match the length of the primary
245 # Flag to left-pad prompt strings to match the length of the primary
246 # prompt
246 # prompt
247 self.pad_left = pad_left
247 self.pad_left = pad_left
248
248
249 # Set template to create each actual prompt (where numbers change).
249 # Set template to create each actual prompt (where numbers change).
250 # Use a property
250 # Use a property
251 self.p_template = prompt
251 self.p_template = prompt
252 self.set_p_str()
252 self.set_p_str()
253
253
254 def set_p_str(self):
254 def set_p_str(self):
255 """ Set the interpolating prompt strings.
255 """ Set the interpolating prompt strings.
256
256
257 This must be called every time the color settings change, because the
257 This must be called every time the color settings change, because the
258 prompt_specials global may have changed."""
258 prompt_specials global may have changed."""
259
259
260 import os,time # needed in locals for prompt string handling
260 import os,time # needed in locals for prompt string handling
261 loc = locals()
261 loc = locals()
262 try:
262 try:
263 self.p_str = ItplNS('%s%s%s' %
263 self.p_str = ItplNS('%s%s%s' %
264 ('${self.sep}${self.col_p}',
264 ('${self.sep}${self.col_p}',
265 multiple_replace(prompt_specials, self.p_template),
265 multiple_replace(prompt_specials, self.p_template),
266 '${self.col_norm}'),self.cache.user_ns,loc)
266 '${self.col_norm}'),self.cache.user_ns,loc)
267
267
268 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
268 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
269 self.p_template),
269 self.p_template),
270 self.cache.user_ns,loc)
270 self.cache.user_ns,loc)
271 except:
271 except:
272 print "Illegal prompt template (check $ usage!):",self.p_template
272 print "Illegal prompt template (check $ usage!):",self.p_template
273 self.p_str = self.p_template
273 self.p_str = self.p_template
274 self.p_str_nocolor = self.p_template
274 self.p_str_nocolor = self.p_template
275
275
276 def write(self,msg): # dbg
276 def write(self,msg): # dbg
277 sys.stdout.write(msg)
277 sys.stdout.write(msg)
278 return ''
278 return ''
279
279
280 def __str__(self):
280 def __str__(self):
281 """Return a string form of the prompt.
281 """Return a string form of the prompt.
282
282
283 This for is useful for continuation and output prompts, since it is
283 This for is useful for continuation and output prompts, since it is
284 left-padded to match lengths with the primary one (if the
284 left-padded to match lengths with the primary one (if the
285 self.pad_left attribute is set)."""
285 self.pad_left attribute is set)."""
286
286
287 out_str = str_safe(self.p_str)
287 out_str = str_safe(self.p_str)
288 if self.pad_left:
288 if self.pad_left:
289 # We must find the amount of padding required to match lengths,
289 # We must find the amount of padding required to match lengths,
290 # taking the color escapes (which are invisible on-screen) into
290 # taking the color escapes (which are invisible on-screen) into
291 # account.
291 # account.
292 esc_pad = len(out_str) - len(str_safe(self.p_str_nocolor))
292 esc_pad = len(out_str) - len(str_safe(self.p_str_nocolor))
293 format = '%%%ss' % (len(str(self.cache.last_prompt))+esc_pad)
293 format = '%%%ss' % (len(str(self.cache.last_prompt))+esc_pad)
294 return format % out_str
294 return format % out_str
295 else:
295 else:
296 return out_str
296 return out_str
297
297
298 # these path filters are put in as methods so that we can control the
298 # these path filters are put in as methods so that we can control the
299 # namespace where the prompt strings get evaluated
299 # namespace where the prompt strings get evaluated
300 def cwd_filt(self,depth):
300 def cwd_filt(self,depth):
301 """Return the last depth elements of the current working directory.
301 """Return the last depth elements of the current working directory.
302
302
303 $HOME is always replaced with '~'.
303 $HOME is always replaced with '~'.
304 If depth==0, the full path is returned."""
304 If depth==0, the full path is returned."""
305
305
306 cwd = os.getcwd().replace(HOME,"~")
306 cwd = os.getcwd().replace(HOME,"~")
307 out = os.sep.join(cwd.split(os.sep)[-depth:])
307 out = os.sep.join(cwd.split(os.sep)[-depth:])
308 if out:
308 if out:
309 return out
309 return out
310 else:
310 else:
311 return os.sep
311 return os.sep
312
312
313 def cwd_filt2(self,depth):
313 def cwd_filt2(self,depth):
314 """Return the last depth elements of the current working directory.
314 """Return the last depth elements of the current working directory.
315
315
316 $HOME is always replaced with '~'.
316 $HOME is always replaced with '~'.
317 If depth==0, the full path is returned."""
317 If depth==0, the full path is returned."""
318
318
319 full_cwd = os.getcwd()
319 full_cwd = os.getcwd()
320 cwd = full_cwd.replace(HOME,"~").split(os.sep)
320 cwd = full_cwd.replace(HOME,"~").split(os.sep)
321 if '~' in cwd and len(cwd) == depth+1:
321 if '~' in cwd and len(cwd) == depth+1:
322 depth += 1
322 depth += 1
323 drivepart = ''
323 drivepart = ''
324 if sys.platform == 'win32' and len(cwd) > depth:
324 if sys.platform == 'win32' and len(cwd) > depth:
325 drivepart = os.path.splitdrive(full_cwd)[0]
325 drivepart = os.path.splitdrive(full_cwd)[0]
326 out = drivepart + '/'.join(cwd[-depth:])
326 out = drivepart + '/'.join(cwd[-depth:])
327
327
328 if out:
328 if out:
329 return out
329 return out
330 else:
330 else:
331 return os.sep
331 return os.sep
332
332
333 def __nonzero__(self):
333 def __nonzero__(self):
334 """Implement boolean behavior.
334 """Implement boolean behavior.
335
335
336 Checks whether the p_str attribute is non-empty"""
336 Checks whether the p_str attribute is non-empty"""
337
337
338 return bool(self.p_template)
338 return bool(self.p_template)
339
339
340 class Prompt1(BasePrompt):
340 class Prompt1(BasePrompt):
341 """Input interactive prompt similar to Mathematica's."""
341 """Input interactive prompt similar to Mathematica's."""
342
342
343 def __init__(self,cache,sep='\n',prompt='In [\\#]: ',pad_left=True):
343 def __init__(self,cache,sep='\n',prompt='In [\\#]: ',pad_left=True):
344 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
344 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
345
345
346 def set_colors(self):
346 def set_colors(self):
347 self.set_p_str()
347 self.set_p_str()
348 Colors = self.cache.color_table.active_colors # shorthand
348 Colors = self.cache.color_table.active_colors # shorthand
349 self.col_p = Colors.in_prompt
349 self.col_p = Colors.in_prompt
350 self.col_num = Colors.in_number
350 self.col_num = Colors.in_number
351 self.col_norm = Colors.in_normal
351 self.col_norm = Colors.in_normal
352 # We need a non-input version of these escapes for the '--->'
352 # We need a non-input version of these escapes for the '--->'
353 # auto-call prompts used in the auto_rewrite() method.
353 # auto-call prompts used in the auto_rewrite() method.
354 self.col_p_ni = self.col_p.replace('\001','').replace('\002','')
354 self.col_p_ni = self.col_p.replace('\001','').replace('\002','')
355 self.col_norm_ni = Colors.normal
355 self.col_norm_ni = Colors.normal
356
356
357 def __str__(self):
357 def __str__(self):
358 self.cache.prompt_count += 1
358 self.cache.prompt_count += 1
359 self.cache.last_prompt = str_safe(self.p_str_nocolor).split('\n')[-1]
359 self.cache.last_prompt = str_safe(self.p_str_nocolor).split('\n')[-1]
360 return str_safe(self.p_str)
360 return str_safe(self.p_str)
361
361
362 def auto_rewrite(self):
362 def auto_rewrite(self):
363 """Print a string of the form '--->' which lines up with the previous
363 """Print a string of the form '--->' which lines up with the previous
364 input string. Useful for systems which re-write the user input when
364 input string. Useful for systems which re-write the user input when
365 handling automatically special syntaxes."""
365 handling automatically special syntaxes."""
366
366
367 curr = str(self.cache.last_prompt)
367 curr = str(self.cache.last_prompt)
368 nrspaces = len(self.rspace.search(curr).group())
368 nrspaces = len(self.rspace.search(curr).group())
369 return '%s%s>%s%s' % (self.col_p_ni,'-'*(len(curr)-nrspaces-1),
369 return '%s%s>%s%s' % (self.col_p_ni,'-'*(len(curr)-nrspaces-1),
370 ' '*nrspaces,self.col_norm_ni)
370 ' '*nrspaces,self.col_norm_ni)
371
371
372 class PromptOut(BasePrompt):
372 class PromptOut(BasePrompt):
373 """Output interactive prompt similar to Mathematica's."""
373 """Output interactive prompt similar to Mathematica's."""
374
374
375 def __init__(self,cache,sep='',prompt='Out[\\#]: ',pad_left=True):
375 def __init__(self,cache,sep='',prompt='Out[\\#]: ',pad_left=True):
376 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
376 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
377 if not self.p_template:
377 if not self.p_template:
378 self.__str__ = lambda: ''
378 self.__str__ = lambda: ''
379
379
380 def set_colors(self):
380 def set_colors(self):
381 self.set_p_str()
381 self.set_p_str()
382 Colors = self.cache.color_table.active_colors # shorthand
382 Colors = self.cache.color_table.active_colors # shorthand
383 self.col_p = Colors.out_prompt
383 self.col_p = Colors.out_prompt
384 self.col_num = Colors.out_number
384 self.col_num = Colors.out_number
385 self.col_norm = Colors.normal
385 self.col_norm = Colors.normal
386
386
387 class Prompt2(BasePrompt):
387 class Prompt2(BasePrompt):
388 """Interactive continuation prompt."""
388 """Interactive continuation prompt."""
389
389
390 def __init__(self,cache,prompt=' .\\D.: ',pad_left=True):
390 def __init__(self,cache,prompt=' .\\D.: ',pad_left=True):
391 self.cache = cache
391 self.cache = cache
392 self.p_template = prompt
392 self.p_template = prompt
393 self.pad_left = pad_left
393 self.pad_left = pad_left
394 self.set_p_str()
394 self.set_p_str()
395
395
396 def set_p_str(self):
396 def set_p_str(self):
397 import os,time # needed in locals for prompt string handling
397 import os,time # needed in locals for prompt string handling
398 loc = locals()
398 loc = locals()
399 self.p_str = ItplNS('%s%s%s' %
399 self.p_str = ItplNS('%s%s%s' %
400 ('${self.col_p2}',
400 ('${self.col_p2}',
401 multiple_replace(prompt_specials, self.p_template),
401 multiple_replace(prompt_specials, self.p_template),
402 '$self.col_norm'),
402 '$self.col_norm'),
403 self.cache.user_ns,loc)
403 self.cache.user_ns,loc)
404 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
404 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
405 self.p_template),
405 self.p_template),
406 self.cache.user_ns,loc)
406 self.cache.user_ns,loc)
407
407
408 def set_colors(self):
408 def set_colors(self):
409 self.set_p_str()
409 self.set_p_str()
410 Colors = self.cache.color_table.active_colors
410 Colors = self.cache.color_table.active_colors
411 self.col_p2 = Colors.in_prompt2
411 self.col_p2 = Colors.in_prompt2
412 self.col_norm = Colors.in_normal
412 self.col_norm = Colors.in_normal
413 # FIXME (2004-06-16) HACK: prevent crashes for users who haven't
413 # FIXME (2004-06-16) HACK: prevent crashes for users who haven't
414 # updated their prompt_in2 definitions. Remove eventually.
414 # updated their prompt_in2 definitions. Remove eventually.
415 self.col_p = Colors.out_prompt
415 self.col_p = Colors.out_prompt
416 self.col_num = Colors.out_number
416 self.col_num = Colors.out_number
417
417
418
418
419 #-----------------------------------------------------------------------------
419 #-----------------------------------------------------------------------------
420 class CachedOutput:
420 class CachedOutput:
421 """Class for printing output from calculations while keeping a cache of
421 """Class for printing output from calculations while keeping a cache of
422 reults. It dynamically creates global variables prefixed with _ which
422 reults. It dynamically creates global variables prefixed with _ which
423 contain these results.
423 contain these results.
424
424
425 Meant to be used as a sys.displayhook replacement, providing numbered
425 Meant to be used as a sys.displayhook replacement, providing numbered
426 prompts and cache services.
426 prompts and cache services.
427
427
428 Initialize with initial and final values for cache counter (this defines
428 Initialize with initial and final values for cache counter (this defines
429 the maximum size of the cache."""
429 the maximum size of the cache."""
430
430
431 def __init__(self,shell,cache_size,Pprint,
431 def __init__(self,shell,cache_size,Pprint,
432 colors='NoColor',input_sep='\n',
432 colors='NoColor',input_sep='\n',
433 output_sep='\n',output_sep2='',
433 output_sep='\n',output_sep2='',
434 ps1 = None, ps2 = None,ps_out = None,pad_left=True):
434 ps1 = None, ps2 = None,ps_out = None,pad_left=True):
435
435
436 cache_size_min = 3
436 cache_size_min = 3
437 if cache_size <= 0:
437 if cache_size <= 0:
438 self.do_full_cache = 0
438 self.do_full_cache = 0
439 cache_size = 0
439 cache_size = 0
440 elif cache_size < cache_size_min:
440 elif cache_size < cache_size_min:
441 self.do_full_cache = 0
441 self.do_full_cache = 0
442 cache_size = 0
442 cache_size = 0
443 warn('caching was disabled (min value for cache size is %s).' %
443 warn('caching was disabled (min value for cache size is %s).' %
444 cache_size_min,level=3)
444 cache_size_min,level=3)
445 else:
445 else:
446 self.do_full_cache = 1
446 self.do_full_cache = 1
447
447
448 self.cache_size = cache_size
448 self.cache_size = cache_size
449 self.input_sep = input_sep
449 self.input_sep = input_sep
450
450
451 # we need a reference to the user-level namespace
451 # we need a reference to the user-level namespace
452 self.shell = shell
452 self.shell = shell
453 self.user_ns = shell.user_ns
453 self.user_ns = shell.user_ns
454 # and to the user's input
454 # and to the user's input
455 self.input_hist = shell.input_hist
455 self.input_hist = shell.input_hist
456 # and to the user's logger, for logging output
456 # and to the user's logger, for logging output
457 self.logger = shell.logger
457 self.logger = shell.logger
458
458
459 # Set input prompt strings and colors
459 # Set input prompt strings and colors
460 if cache_size == 0:
460 if cache_size == 0:
461 if ps1.find('%n') > -1 or ps1.find(r'\#') > -1 \
461 if ps1.find('%n') > -1 or ps1.find(r'\#') > -1 \
462 or ps1.find(r'\N') > -1:
462 or ps1.find(r'\N') > -1:
463 ps1 = '>>> '
463 ps1 = '>>> '
464 if ps2.find('%n') > -1 or ps2.find(r'\#') > -1 \
464 if ps2.find('%n') > -1 or ps2.find(r'\#') > -1 \
465 or ps2.find(r'\N') > -1:
465 or ps2.find(r'\N') > -1:
466 ps2 = '... '
466 ps2 = '... '
467 self.ps1_str = self._set_prompt_str(ps1,'In [\\#]: ','>>> ')
467 self.ps1_str = self._set_prompt_str(ps1,'In [\\#]: ','>>> ')
468 self.ps2_str = self._set_prompt_str(ps2,' .\\D.: ','... ')
468 self.ps2_str = self._set_prompt_str(ps2,' .\\D.: ','... ')
469 self.ps_out_str = self._set_prompt_str(ps_out,'Out[\\#]: ','')
469 self.ps_out_str = self._set_prompt_str(ps_out,'Out[\\#]: ','')
470
470
471 self.color_table = PromptColors
471 self.color_table = PromptColors
472 self.prompt1 = Prompt1(self,sep=input_sep,prompt=self.ps1_str,
472 self.prompt1 = Prompt1(self,sep=input_sep,prompt=self.ps1_str,
473 pad_left=pad_left)
473 pad_left=pad_left)
474 self.prompt2 = Prompt2(self,prompt=self.ps2_str,pad_left=pad_left)
474 self.prompt2 = Prompt2(self,prompt=self.ps2_str,pad_left=pad_left)
475 self.prompt_out = PromptOut(self,sep='',prompt=self.ps_out_str,
475 self.prompt_out = PromptOut(self,sep='',prompt=self.ps_out_str,
476 pad_left=pad_left)
476 pad_left=pad_left)
477 self.set_colors(colors)
477 self.set_colors(colors)
478
478
479 # other more normal stuff
479 # other more normal stuff
480 # b/c each call to the In[] prompt raises it by 1, even the first.
480 # b/c each call to the In[] prompt raises it by 1, even the first.
481 self.prompt_count = 0
481 self.prompt_count = 0
482 # Store the last prompt string each time, we need it for aligning
482 # Store the last prompt string each time, we need it for aligning
483 # continuation and auto-rewrite prompts
483 # continuation and auto-rewrite prompts
484 self.last_prompt = ''
484 self.last_prompt = ''
485 self.Pprint = Pprint
485 self.Pprint = Pprint
486 self.output_sep = output_sep
486 self.output_sep = output_sep
487 self.output_sep2 = output_sep2
487 self.output_sep2 = output_sep2
488 self._,self.__,self.___ = '','',''
488 self._,self.__,self.___ = '','',''
489 self.pprint_types = map(type,[(),[],{}])
489 self.pprint_types = map(type,[(),[],{}])
490
490
491 # these are deliberately global:
491 # these are deliberately global:
492 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
492 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
493 self.user_ns.update(to_user_ns)
493 self.user_ns.update(to_user_ns)
494
494
495 def _set_prompt_str(self,p_str,cache_def,no_cache_def):
495 def _set_prompt_str(self,p_str,cache_def,no_cache_def):
496 if p_str is None:
496 if p_str is None:
497 if self.do_full_cache:
497 if self.do_full_cache:
498 return cache_def
498 return cache_def
499 else:
499 else:
500 return no_cache_def
500 return no_cache_def
501 else:
501 else:
502 return p_str
502 return p_str
503
503
504 def set_colors(self,colors):
504 def set_colors(self,colors):
505 """Set the active color scheme and configure colors for the three
505 """Set the active color scheme and configure colors for the three
506 prompt subsystems."""
506 prompt subsystems."""
507
507
508 # FIXME: the prompt_specials global should be gobbled inside this
508 # FIXME: the prompt_specials global should be gobbled inside this
509 # class instead. Do it when cleaning up the whole 3-prompt system.
509 # class instead. Do it when cleaning up the whole 3-prompt system.
510 global prompt_specials
510 global prompt_specials
511 if colors.lower()=='nocolor':
511 if colors.lower()=='nocolor':
512 prompt_specials = prompt_specials_nocolor
512 prompt_specials = prompt_specials_nocolor
513 else:
513 else:
514 prompt_specials = prompt_specials_color
514 prompt_specials = prompt_specials_color
515
515
516 self.color_table.set_active_scheme(colors)
516 self.color_table.set_active_scheme(colors)
517 self.prompt1.set_colors()
517 self.prompt1.set_colors()
518 self.prompt2.set_colors()
518 self.prompt2.set_colors()
519 self.prompt_out.set_colors()
519 self.prompt_out.set_colors()
520
520
521 def __call__(self,arg=None):
521 def __call__(self,arg=None):
522 """Printing with history cache management.
522 """Printing with history cache management.
523
523
524 This is invoked everytime the interpreter needs to print, and is
524 This is invoked everytime the interpreter needs to print, and is
525 activated by setting the variable sys.displayhook to it."""
525 activated by setting the variable sys.displayhook to it."""
526
526
527 # If something injected a '_' variable in __builtin__, delete
527 # If something injected a '_' variable in __builtin__, delete
528 # ipython's automatic one so we don't clobber that. gettext() in
528 # ipython's automatic one so we don't clobber that. gettext() in
529 # particular uses _, so we need to stay away from it.
529 # particular uses _, so we need to stay away from it.
530 if '_' in __builtin__.__dict__:
530 if '_' in __builtin__.__dict__:
531 try:
531 try:
532 del self.user_ns['_']
532 del self.user_ns['_']
533 except KeyError:
533 except KeyError:
534 pass
534 pass
535 if arg is not None:
535 if arg is not None:
536 cout_write = Term.cout.write # fast lookup
536 cout_write = Term.cout.write # fast lookup
537 # first handle the cache and counters
537 # first handle the cache and counters
538
538
539 # do not print output if input ends in ';'
539 # do not print output if input ends in ';'
540 try:
540 try:
541 if self.input_hist[self.prompt_count].endswith(';\n'):
541 if self.input_hist[self.prompt_count].endswith(';\n'):
542 return
542 return
543 except IndexError:
543 except IndexError:
544 # some uses of ipshellembed may fail here
544 # some uses of ipshellembed may fail here
545 pass
545 pass
546 # don't use print, puts an extra space
546 # don't use print, puts an extra space
547 cout_write(self.output_sep)
547 cout_write(self.output_sep)
548 outprompt = self.shell.hooks.generate_output_prompt()
548 outprompt = self.shell.hooks.generate_output_prompt()
549 if self.do_full_cache:
549 if self.do_full_cache:
550 cout_write(outprompt)
550 cout_write(outprompt)
551
551
552 # and now call a possibly user-defined print mechanism
552 # and now call a possibly user-defined print mechanism
553 manipulated_val = self.display(arg)
553 manipulated_val = self.display(arg)
554
554
555 # user display hooks can change the variable to be stored in
555 # user display hooks can change the variable to be stored in
556 # output history
556 # output history
557
557
558 if manipulated_val is not None:
558 if manipulated_val is not None:
559 arg = manipulated_val
559 arg = manipulated_val
560
560
561 # avoid recursive reference when displaying _oh/Out
561 # avoid recursive reference when displaying _oh/Out
562 if arg is not self.user_ns['_oh']:
562 if arg is not self.user_ns['_oh']:
563 self.update(arg)
563 self.update(arg)
564
564
565 if self.logger.log_output:
565 if self.logger.log_output:
566 self.logger.log_write(repr(arg),'output')
566 self.logger.log_write(repr(arg),'output')
567 cout_write(self.output_sep2)
567 cout_write(self.output_sep2)
568 Term.cout.flush()
568 Term.cout.flush()
569
569
570 def _display(self,arg):
570 def _display(self,arg):
571 """Default printer method, uses pprint.
571 """Default printer method, uses pprint.
572
572
573 Do ip.set_hook("result_display", my_displayhook) for custom result
573 Do ip.set_hook("result_display", my_displayhook) for custom result
574 display, e.g. when your own objects need special formatting.
574 display, e.g. when your own objects need special formatting.
575 """
575 """
576 try:
576 try:
577 return IPython.utils.generics.result_display(arg)
577 return IPython.utils.generics.result_display(arg)
578 except TryNext:
578 except TryNext:
579 return self.shell.hooks.result_display(arg)
579 return self.shell.hooks.result_display(arg)
580
580
581 # Assign the default display method:
581 # Assign the default display method:
582 display = _display
582 display = _display
583
583
584 def update(self,arg):
584 def update(self,arg):
585 #print '***cache_count', self.cache_count # dbg
585 #print '***cache_count', self.cache_count # dbg
586 if len(self.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
586 if len(self.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
587 warn('Output cache limit (currently '+
587 warn('Output cache limit (currently '+
588 `self.cache_size`+' entries) hit.\n'
588 `self.cache_size`+' entries) hit.\n'
589 'Flushing cache and resetting history counter...\n'
589 'Flushing cache and resetting history counter...\n'
590 'The only history variables available will be _,__,___ and _1\n'
590 'The only history variables available will be _,__,___ and _1\n'
591 'with the current result.')
591 'with the current result.')
592
592
593 self.flush()
593 self.flush()
594 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
594 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
595 # we cause buggy behavior for things like gettext).
595 # we cause buggy behavior for things like gettext).
596 if '_' not in __builtin__.__dict__:
596 if '_' not in __builtin__.__dict__:
597 self.___ = self.__
597 self.___ = self.__
598 self.__ = self._
598 self.__ = self._
599 self._ = arg
599 self._ = arg
600 self.user_ns.update({'_':self._,'__':self.__,'___':self.___})
600 self.user_ns.update({'_':self._,'__':self.__,'___':self.___})
601
601
602 # hackish access to top-level namespace to create _1,_2... dynamically
602 # hackish access to top-level namespace to create _1,_2... dynamically
603 to_main = {}
603 to_main = {}
604 if self.do_full_cache:
604 if self.do_full_cache:
605 new_result = '_'+`self.prompt_count`
605 new_result = '_'+`self.prompt_count`
606 to_main[new_result] = arg
606 to_main[new_result] = arg
607 self.user_ns.update(to_main)
607 self.user_ns.update(to_main)
608 self.user_ns['_oh'][self.prompt_count] = arg
608 self.user_ns['_oh'][self.prompt_count] = arg
609
609
610 def flush(self):
610 def flush(self):
611 if not self.do_full_cache:
611 if not self.do_full_cache:
612 raise ValueError,"You shouldn't have reached the cache flush "\
612 raise ValueError,"You shouldn't have reached the cache flush "\
613 "if full caching is not enabled!"
613 "if full caching is not enabled!"
614 # delete auto-generated vars from global namespace
614 # delete auto-generated vars from global namespace
615
615
616 for n in range(1,self.prompt_count + 1):
616 for n in range(1,self.prompt_count + 1):
617 key = '_'+`n`
617 key = '_'+`n`
618 try:
618 try:
619 del self.user_ns[key]
619 del self.user_ns[key]
620 except: pass
620 except: pass
621 self.user_ns['_oh'].clear()
621 self.user_ns['_oh'].clear()
622
622
623 if '_' not in __builtin__.__dict__:
623 if '_' not in __builtin__.__dict__:
624 self.user_ns.update({'_':None,'__':None, '___':None})
624 self.user_ns.update({'_':None,'__':None, '___':None})
625 import gc
625 import gc
626 gc.collect() # xxx needed?
626 gc.collect() # xxx needed?
627
627
1 NO CONTENT: file renamed from IPython/Release.py to IPython/core/release.py
NO CONTENT: file renamed from IPython/Release.py to IPython/core/release.py
@@ -1,53 +1,56
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3
3
4 def test_import_completer():
4 def test_import_completer():
5 from IPython.core import completer
5 from IPython.core import completer
6
6
7 def test_import_crashhandler():
7 def test_import_crashhandler():
8 from IPython.core import crashhandler
8 from IPython.core import crashhandler
9
9
10 def test_import_debugger():
10 def test_import_debugger():
11 from IPython.core import debugger
11 from IPython.core import debugger
12
12
13 def test_import_fakemodule():
13 def test_import_fakemodule():
14 from IPython.core import fakemodule
14 from IPython.core import fakemodule
15
15
16 def test_import_excolors():
16 def test_import_excolors():
17 from IPython.core import excolors
17 from IPython.core import excolors
18
18
19 def test_import_history():
19 def test_import_history():
20 from IPython.core import history
20 from IPython.core import history
21
21
22 def test_import_hooks():
22 def test_import_hooks():
23 from IPython.core import hooks
23 from IPython.core import hooks
24
24
25 def test_import_ipapi():
25 def test_import_ipapi():
26 from IPython.core import ipapi
26 from IPython.core import ipapi
27
27
28 def test_import_iplib():
28 def test_import_iplib():
29 from IPython.core import iplib
29 from IPython.core import iplib
30
30
31 def test_import_ipmaker():
31 def test_import_ipmaker():
32 from IPython.core import ipmaker
32 from IPython.core import ipmaker
33
33
34 def test_import_logger():
34 def test_import_logger():
35 from IPython.core import logger
35 from IPython.core import logger
36
36
37 def test_import_macro():
37 def test_import_macro():
38 from IPython.core import macro
38 from IPython.core import macro
39
39
40 def test_import_magic():
40 def test_import_magic():
41 from IPython.core import magic
41 from IPython.core import magic
42
42
43 def test_import_oinspect():
43 def test_import_oinspect():
44 from IPython.core import oinspect
44 from IPython.core import oinspect
45
45
46 def test_import_outputtrap():
46 def test_import_outputtrap():
47 from IPython.core import outputtrap
47 from IPython.core import outputtrap
48
48
49 def test_import_prefilter():
49 def test_import_prefilter():
50 from IPython.core import prefilter
50 from IPython.core import prefilter
51
51
52 def test_import_prompts():
52 def test_import_prompts():
53 from IPython.core import prompts
53 from IPython.core import prompts
54
55 def test_import_release():
56 from IPython.core import release No newline at end of file
@@ -1,585 +1,585
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 socket
24 import socket
25 import sys
25 import sys
26
26
27 # IPython's own
27 # IPython's own
28 from IPython.external.Itpl import ItplNS
28 from IPython.external.Itpl import ItplNS
29
29
30 from IPython.utils import coloransi
30 from IPython.utils import coloransi
31 from IPython import Release
31 from IPython.core import release
32 from IPython.core.ipapi import TryNext
32 from IPython.core.ipapi import TryNext
33 from IPython.utils.genutils import *
33 from IPython.utils.genutils import *
34 import IPython.utils.generics
34 import IPython.utils.generics
35
35
36 #****************************************************************************
36 #****************************************************************************
37 #Color schemes for Prompts.
37 #Color schemes for Prompts.
38
38
39 PromptColors = coloransi.ColorSchemeTable()
39 PromptColors = coloransi.ColorSchemeTable()
40 InputColors = coloransi.InputTermColors # just a shorthand
40 InputColors = coloransi.InputTermColors # just a shorthand
41 Colors = coloransi.TermColors # just a shorthand
41 Colors = coloransi.TermColors # just a shorthand
42
42
43
43
44 __PColNoColor = coloransi.ColorScheme(
44 __PColNoColor = coloransi.ColorScheme(
45 'NoColor',
45 'NoColor',
46 in_prompt = InputColors.NoColor, # Input prompt
46 in_prompt = InputColors.NoColor, # Input prompt
47 in_number = InputColors.NoColor, # Input prompt number
47 in_number = InputColors.NoColor, # Input prompt number
48 in_prompt2 = InputColors.NoColor, # Continuation prompt
48 in_prompt2 = InputColors.NoColor, # Continuation prompt
49 in_normal = InputColors.NoColor, # color off (usu. Colors.Normal)
49 in_normal = InputColors.NoColor, # color off (usu. Colors.Normal)
50
50
51 out_prompt = Colors.NoColor, # Output prompt
51 out_prompt = Colors.NoColor, # Output prompt
52 out_number = Colors.NoColor, # Output prompt number
52 out_number = Colors.NoColor, # Output prompt number
53
53
54 normal = Colors.NoColor # color off (usu. Colors.Normal)
54 normal = Colors.NoColor # color off (usu. Colors.Normal)
55 )
55 )
56
56
57 PromptColors.add_scheme(__PColNoColor)
57 PromptColors.add_scheme(__PColNoColor)
58
58
59 # make some schemes as instances so we can copy them for modification easily:
59 # make some schemes as instances so we can copy them for modification easily:
60 __PColLinux = __PColNoColor.copy('Linux')
60 __PColLinux = __PColNoColor.copy('Linux')
61 # Don't forget to enter it into the table!
61 # Don't forget to enter it into the table!
62 PromptColors.add_scheme(__PColLinux)
62 PromptColors.add_scheme(__PColLinux)
63 __PColLightBG = __PColLinux.copy('LightBG')
63 __PColLightBG = __PColLinux.copy('LightBG')
64 PromptColors.add_scheme(__PColLightBG)
64 PromptColors.add_scheme(__PColLightBG)
65
65
66 del Colors,InputColors
66 del Colors,InputColors
67
67
68 #-----------------------------------------------------------------------------
68 #-----------------------------------------------------------------------------
69 def multiple_replace(dict, text):
69 def multiple_replace(dict, text):
70 """ Replace in 'text' all occurences of any key in the given
70 """ Replace in 'text' all occurences of any key in the given
71 dictionary by its corresponding value. Returns the new string."""
71 dictionary by its corresponding value. Returns the new string."""
72
72
73 # Function by Xavier Defrang, originally found at:
73 # Function by Xavier Defrang, originally found at:
74 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
74 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
75
75
76 # Create a regular expression from the dictionary keys
76 # Create a regular expression from the dictionary keys
77 regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
77 regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
78 # For each match, look-up corresponding value in dictionary
78 # For each match, look-up corresponding value in dictionary
79 return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
79 return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
80
80
81 #-----------------------------------------------------------------------------
81 #-----------------------------------------------------------------------------
82 # Special characters that can be used in prompt templates, mainly bash-like
82 # Special characters that can be used in prompt templates, mainly bash-like
83
83
84 # If $HOME isn't defined (Windows), make it an absurd string so that it can
84 # If $HOME isn't defined (Windows), make it an absurd string so that it can
85 # never be expanded out into '~'. Basically anything which can never be a
85 # never be expanded out into '~'. Basically anything which can never be a
86 # reasonable directory name will do, we just want the $HOME -> '~' operation
86 # reasonable directory name will do, we just want the $HOME -> '~' operation
87 # to become a no-op. We pre-compute $HOME here so it's not done on every
87 # to become a no-op. We pre-compute $HOME here so it's not done on every
88 # prompt call.
88 # prompt call.
89
89
90 # FIXME:
90 # FIXME:
91
91
92 # - This should be turned into a class which does proper namespace management,
92 # - This should be turned into a class which does proper namespace management,
93 # since the prompt specials need to be evaluated in a certain namespace.
93 # since the prompt specials need to be evaluated in a certain namespace.
94 # Currently it's just globals, which need to be managed manually by code
94 # Currently it's just globals, which need to be managed manually by code
95 # below.
95 # below.
96
96
97 # - I also need to split up the color schemes from the prompt specials
97 # - I also need to split up the color schemes from the prompt specials
98 # somehow. I don't have a clean design for that quite yet.
98 # somehow. I don't have a clean design for that quite yet.
99
99
100 HOME = os.environ.get("HOME","//////:::::ZZZZZ,,,~~~")
100 HOME = os.environ.get("HOME","//////:::::ZZZZZ,,,~~~")
101
101
102 # We precompute a few more strings here for the prompt_specials, which are
102 # We precompute a few more strings here for the prompt_specials, which are
103 # fixed once ipython starts. This reduces the runtime overhead of computing
103 # fixed once ipython starts. This reduces the runtime overhead of computing
104 # prompt strings.
104 # prompt strings.
105 USER = os.environ.get("USER")
105 USER = os.environ.get("USER")
106 HOSTNAME = socket.gethostname()
106 HOSTNAME = socket.gethostname()
107 HOSTNAME_SHORT = HOSTNAME.split(".")[0]
107 HOSTNAME_SHORT = HOSTNAME.split(".")[0]
108 ROOT_SYMBOL = "$#"[os.name=='nt' or os.getuid()==0]
108 ROOT_SYMBOL = "$#"[os.name=='nt' or os.getuid()==0]
109
109
110 prompt_specials_color = {
110 prompt_specials_color = {
111 # Prompt/history count
111 # Prompt/history count
112 '%n' : '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
112 '%n' : '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
113 r'\#': '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
113 r'\#': '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
114 # Just the prompt counter number, WITHOUT any coloring wrappers, so users
114 # Just the prompt counter number, WITHOUT any coloring wrappers, so users
115 # can get numbers displayed in whatever color they want.
115 # can get numbers displayed in whatever color they want.
116 r'\N': '${self.cache.prompt_count}',
116 r'\N': '${self.cache.prompt_count}',
117 # Prompt/history count, with the actual digits replaced by dots. Used
117 # Prompt/history count, with the actual digits replaced by dots. Used
118 # mainly in continuation prompts (prompt_in2)
118 # mainly in continuation prompts (prompt_in2)
119 r'\D': '${"."*len(str(self.cache.prompt_count))}',
119 r'\D': '${"."*len(str(self.cache.prompt_count))}',
120 # Current working directory
120 # Current working directory
121 r'\w': '${os.getcwd()}',
121 r'\w': '${os.getcwd()}',
122 # Current time
122 # Current time
123 r'\t' : '${time.strftime("%H:%M:%S")}',
123 r'\t' : '${time.strftime("%H:%M:%S")}',
124 # Basename of current working directory.
124 # Basename of current working directory.
125 # (use os.sep to make this portable across OSes)
125 # (use os.sep to make this portable across OSes)
126 r'\W' : '${os.getcwd().split("%s")[-1]}' % os.sep,
126 r'\W' : '${os.getcwd().split("%s")[-1]}' % os.sep,
127 # These X<N> are an extension to the normal bash prompts. They return
127 # These X<N> are an extension to the normal bash prompts. They return
128 # N terms of the path, after replacing $HOME with '~'
128 # N terms of the path, after replacing $HOME with '~'
129 r'\X0': '${os.getcwd().replace("%s","~")}' % HOME,
129 r'\X0': '${os.getcwd().replace("%s","~")}' % HOME,
130 r'\X1': '${self.cwd_filt(1)}',
130 r'\X1': '${self.cwd_filt(1)}',
131 r'\X2': '${self.cwd_filt(2)}',
131 r'\X2': '${self.cwd_filt(2)}',
132 r'\X3': '${self.cwd_filt(3)}',
132 r'\X3': '${self.cwd_filt(3)}',
133 r'\X4': '${self.cwd_filt(4)}',
133 r'\X4': '${self.cwd_filt(4)}',
134 r'\X5': '${self.cwd_filt(5)}',
134 r'\X5': '${self.cwd_filt(5)}',
135 # Y<N> are similar to X<N>, but they show '~' if it's the directory
135 # Y<N> are similar to X<N>, but they show '~' if it's the directory
136 # N+1 in the list. Somewhat like %cN in tcsh.
136 # N+1 in the list. Somewhat like %cN in tcsh.
137 r'\Y0': '${self.cwd_filt2(0)}',
137 r'\Y0': '${self.cwd_filt2(0)}',
138 r'\Y1': '${self.cwd_filt2(1)}',
138 r'\Y1': '${self.cwd_filt2(1)}',
139 r'\Y2': '${self.cwd_filt2(2)}',
139 r'\Y2': '${self.cwd_filt2(2)}',
140 r'\Y3': '${self.cwd_filt2(3)}',
140 r'\Y3': '${self.cwd_filt2(3)}',
141 r'\Y4': '${self.cwd_filt2(4)}',
141 r'\Y4': '${self.cwd_filt2(4)}',
142 r'\Y5': '${self.cwd_filt2(5)}',
142 r'\Y5': '${self.cwd_filt2(5)}',
143 # Hostname up to first .
143 # Hostname up to first .
144 r'\h': HOSTNAME_SHORT,
144 r'\h': HOSTNAME_SHORT,
145 # Full hostname
145 # Full hostname
146 r'\H': HOSTNAME,
146 r'\H': HOSTNAME,
147 # Username of current user
147 # Username of current user
148 r'\u': USER,
148 r'\u': USER,
149 # Escaped '\'
149 # Escaped '\'
150 '\\\\': '\\',
150 '\\\\': '\\',
151 # Newline
151 # Newline
152 r'\n': '\n',
152 r'\n': '\n',
153 # Carriage return
153 # Carriage return
154 r'\r': '\r',
154 r'\r': '\r',
155 # Release version
155 # Release version
156 r'\v': Release.version,
156 r'\v': release.version,
157 # Root symbol ($ or #)
157 # Root symbol ($ or #)
158 r'\$': ROOT_SYMBOL,
158 r'\$': ROOT_SYMBOL,
159 }
159 }
160
160
161 # A copy of the prompt_specials dictionary but with all color escapes removed,
161 # A copy of the prompt_specials dictionary but with all color escapes removed,
162 # so we can correctly compute the prompt length for the auto_rewrite method.
162 # so we can correctly compute the prompt length for the auto_rewrite method.
163 prompt_specials_nocolor = prompt_specials_color.copy()
163 prompt_specials_nocolor = prompt_specials_color.copy()
164 prompt_specials_nocolor['%n'] = '${self.cache.prompt_count}'
164 prompt_specials_nocolor['%n'] = '${self.cache.prompt_count}'
165 prompt_specials_nocolor[r'\#'] = '${self.cache.prompt_count}'
165 prompt_specials_nocolor[r'\#'] = '${self.cache.prompt_count}'
166
166
167 # Add in all the InputTermColors color escapes as valid prompt characters.
167 # Add in all the InputTermColors color escapes as valid prompt characters.
168 # They all get added as \\C_COLORNAME, so that we don't have any conflicts
168 # They all get added as \\C_COLORNAME, so that we don't have any conflicts
169 # with a color name which may begin with a letter used by any other of the
169 # with a color name which may begin with a letter used by any other of the
170 # allowed specials. This of course means that \\C will never be allowed for
170 # allowed specials. This of course means that \\C will never be allowed for
171 # anything else.
171 # anything else.
172 input_colors = coloransi.InputTermColors
172 input_colors = coloransi.InputTermColors
173 for _color in dir(input_colors):
173 for _color in dir(input_colors):
174 if _color[0] != '_':
174 if _color[0] != '_':
175 c_name = r'\C_'+_color
175 c_name = r'\C_'+_color
176 prompt_specials_color[c_name] = getattr(input_colors,_color)
176 prompt_specials_color[c_name] = getattr(input_colors,_color)
177 prompt_specials_nocolor[c_name] = ''
177 prompt_specials_nocolor[c_name] = ''
178
178
179 # we default to no color for safety. Note that prompt_specials is a global
179 # we default to no color for safety. Note that prompt_specials is a global
180 # variable used by all prompt objects.
180 # variable used by all prompt objects.
181 prompt_specials = prompt_specials_nocolor
181 prompt_specials = prompt_specials_nocolor
182
182
183 #-----------------------------------------------------------------------------
183 #-----------------------------------------------------------------------------
184 def str_safe(arg):
184 def str_safe(arg):
185 """Convert to a string, without ever raising an exception.
185 """Convert to a string, without ever raising an exception.
186
186
187 If str(arg) fails, <ERROR: ... > is returned, where ... is the exception
187 If str(arg) fails, <ERROR: ... > is returned, where ... is the exception
188 error message."""
188 error message."""
189
189
190 try:
190 try:
191 out = str(arg)
191 out = str(arg)
192 except UnicodeError:
192 except UnicodeError:
193 try:
193 try:
194 out = arg.encode('utf_8','replace')
194 out = arg.encode('utf_8','replace')
195 except Exception,msg:
195 except Exception,msg:
196 # let's keep this little duplication here, so that the most common
196 # let's keep this little duplication here, so that the most common
197 # case doesn't suffer from a double try wrapping.
197 # case doesn't suffer from a double try wrapping.
198 out = '<ERROR: %s>' % msg
198 out = '<ERROR: %s>' % msg
199 except Exception,msg:
199 except Exception,msg:
200 out = '<ERROR: %s>' % msg
200 out = '<ERROR: %s>' % msg
201 return out
201 return out
202
202
203 class BasePrompt(object):
203 class BasePrompt(object):
204 """Interactive prompt similar to Mathematica's."""
204 """Interactive prompt similar to Mathematica's."""
205
205
206 def _get_p_template(self):
206 def _get_p_template(self):
207 return self._p_template
207 return self._p_template
208
208
209 def _set_p_template(self,val):
209 def _set_p_template(self,val):
210 self._p_template = val
210 self._p_template = val
211 self.set_p_str()
211 self.set_p_str()
212
212
213 p_template = property(_get_p_template,_set_p_template,
213 p_template = property(_get_p_template,_set_p_template,
214 doc='Template for prompt string creation')
214 doc='Template for prompt string creation')
215
215
216 def __init__(self,cache,sep,prompt,pad_left=False):
216 def __init__(self,cache,sep,prompt,pad_left=False):
217
217
218 # Hack: we access information about the primary prompt through the
218 # Hack: we access information about the primary prompt through the
219 # cache argument. We need this, because we want the secondary prompt
219 # cache argument. We need this, because we want the secondary prompt
220 # to be aligned with the primary one. Color table info is also shared
220 # to be aligned with the primary one. Color table info is also shared
221 # by all prompt classes through the cache. Nice OO spaghetti code!
221 # by all prompt classes through the cache. Nice OO spaghetti code!
222 self.cache = cache
222 self.cache = cache
223 self.sep = sep
223 self.sep = sep
224
224
225 # regexp to count the number of spaces at the end of a prompt
225 # regexp to count the number of spaces at the end of a prompt
226 # expression, useful for prompt auto-rewriting
226 # expression, useful for prompt auto-rewriting
227 self.rspace = re.compile(r'(\s*)$')
227 self.rspace = re.compile(r'(\s*)$')
228 # Flag to left-pad prompt strings to match the length of the primary
228 # Flag to left-pad prompt strings to match the length of the primary
229 # prompt
229 # prompt
230 self.pad_left = pad_left
230 self.pad_left = pad_left
231
231
232 # Set template to create each actual prompt (where numbers change).
232 # Set template to create each actual prompt (where numbers change).
233 # Use a property
233 # Use a property
234 self.p_template = prompt
234 self.p_template = prompt
235 self.set_p_str()
235 self.set_p_str()
236
236
237 def set_p_str(self):
237 def set_p_str(self):
238 """ Set the interpolating prompt strings.
238 """ Set the interpolating prompt strings.
239
239
240 This must be called every time the color settings change, because the
240 This must be called every time the color settings change, because the
241 prompt_specials global may have changed."""
241 prompt_specials global may have changed."""
242
242
243 import os,time # needed in locals for prompt string handling
243 import os,time # needed in locals for prompt string handling
244 loc = locals()
244 loc = locals()
245 self.p_str = ItplNS('%s%s%s' %
245 self.p_str = ItplNS('%s%s%s' %
246 ('${self.sep}${self.col_p}',
246 ('${self.sep}${self.col_p}',
247 multiple_replace(prompt_specials, self.p_template),
247 multiple_replace(prompt_specials, self.p_template),
248 '${self.col_norm}'),self.cache.user_ns,loc)
248 '${self.col_norm}'),self.cache.user_ns,loc)
249
249
250 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
250 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
251 self.p_template),
251 self.p_template),
252 self.cache.user_ns,loc)
252 self.cache.user_ns,loc)
253
253
254 def write(self,msg): # dbg
254 def write(self,msg): # dbg
255 sys.stdout.write(msg)
255 sys.stdout.write(msg)
256 return ''
256 return ''
257
257
258 def __str__(self):
258 def __str__(self):
259 """Return a string form of the prompt.
259 """Return a string form of the prompt.
260
260
261 This for is useful for continuation and output prompts, since it is
261 This for is useful for continuation and output prompts, since it is
262 left-padded to match lengths with the primary one (if the
262 left-padded to match lengths with the primary one (if the
263 self.pad_left attribute is set)."""
263 self.pad_left attribute is set)."""
264
264
265 out_str = str_safe(self.p_str)
265 out_str = str_safe(self.p_str)
266 if self.pad_left:
266 if self.pad_left:
267 # We must find the amount of padding required to match lengths,
267 # We must find the amount of padding required to match lengths,
268 # taking the color escapes (which are invisible on-screen) into
268 # taking the color escapes (which are invisible on-screen) into
269 # account.
269 # account.
270 esc_pad = len(out_str) - len(str_safe(self.p_str_nocolor))
270 esc_pad = len(out_str) - len(str_safe(self.p_str_nocolor))
271 format = '%%%ss' % (len(str(self.cache.last_prompt))+esc_pad)
271 format = '%%%ss' % (len(str(self.cache.last_prompt))+esc_pad)
272 return format % out_str
272 return format % out_str
273 else:
273 else:
274 return out_str
274 return out_str
275
275
276 # these path filters are put in as methods so that we can control the
276 # these path filters are put in as methods so that we can control the
277 # namespace where the prompt strings get evaluated
277 # namespace where the prompt strings get evaluated
278 def cwd_filt(self,depth):
278 def cwd_filt(self,depth):
279 """Return the last depth elements of the current working directory.
279 """Return the last depth elements of the current working directory.
280
280
281 $HOME is always replaced with '~'.
281 $HOME is always replaced with '~'.
282 If depth==0, the full path is returned."""
282 If depth==0, the full path is returned."""
283
283
284 cwd = os.getcwd().replace(HOME,"~")
284 cwd = os.getcwd().replace(HOME,"~")
285 out = os.sep.join(cwd.split(os.sep)[-depth:])
285 out = os.sep.join(cwd.split(os.sep)[-depth:])
286 if out:
286 if out:
287 return out
287 return out
288 else:
288 else:
289 return os.sep
289 return os.sep
290
290
291 def cwd_filt2(self,depth):
291 def cwd_filt2(self,depth):
292 """Return the last depth elements of the current working directory.
292 """Return the last depth elements of the current working directory.
293
293
294 $HOME is always replaced with '~'.
294 $HOME is always replaced with '~'.
295 If depth==0, the full path is returned."""
295 If depth==0, the full path is returned."""
296
296
297 cwd = os.getcwd().replace(HOME,"~").split(os.sep)
297 cwd = os.getcwd().replace(HOME,"~").split(os.sep)
298 if '~' in cwd and len(cwd) == depth+1:
298 if '~' in cwd and len(cwd) == depth+1:
299 depth += 1
299 depth += 1
300 out = os.sep.join(cwd[-depth:])
300 out = os.sep.join(cwd[-depth:])
301 if out:
301 if out:
302 return out
302 return out
303 else:
303 else:
304 return os.sep
304 return os.sep
305
305
306 class Prompt1(BasePrompt):
306 class Prompt1(BasePrompt):
307 """Input interactive prompt similar to Mathematica's."""
307 """Input interactive prompt similar to Mathematica's."""
308
308
309 def __init__(self,cache,sep='\n',prompt='In [\\#]: ',pad_left=True):
309 def __init__(self,cache,sep='\n',prompt='In [\\#]: ',pad_left=True):
310 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
310 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
311
311
312 def set_colors(self):
312 def set_colors(self):
313 self.set_p_str()
313 self.set_p_str()
314 Colors = self.cache.color_table.active_colors # shorthand
314 Colors = self.cache.color_table.active_colors # shorthand
315 self.col_p = Colors.in_prompt
315 self.col_p = Colors.in_prompt
316 self.col_num = Colors.in_number
316 self.col_num = Colors.in_number
317 self.col_norm = Colors.in_normal
317 self.col_norm = Colors.in_normal
318 # We need a non-input version of these escapes for the '--->'
318 # We need a non-input version of these escapes for the '--->'
319 # auto-call prompts used in the auto_rewrite() method.
319 # auto-call prompts used in the auto_rewrite() method.
320 self.col_p_ni = self.col_p.replace('\001','').replace('\002','')
320 self.col_p_ni = self.col_p.replace('\001','').replace('\002','')
321 self.col_norm_ni = Colors.normal
321 self.col_norm_ni = Colors.normal
322
322
323 def __str__(self):
323 def __str__(self):
324 self.cache.prompt_count += 1
324 self.cache.prompt_count += 1
325 self.cache.last_prompt = str_safe(self.p_str_nocolor).split('\n')[-1]
325 self.cache.last_prompt = str_safe(self.p_str_nocolor).split('\n')[-1]
326 return str_safe(self.p_str)
326 return str_safe(self.p_str)
327
327
328 def auto_rewrite(self):
328 def auto_rewrite(self):
329 """Print a string of the form '--->' which lines up with the previous
329 """Print a string of the form '--->' which lines up with the previous
330 input string. Useful for systems which re-write the user input when
330 input string. Useful for systems which re-write the user input when
331 handling automatically special syntaxes."""
331 handling automatically special syntaxes."""
332
332
333 curr = str(self.cache.last_prompt)
333 curr = str(self.cache.last_prompt)
334 nrspaces = len(self.rspace.search(curr).group())
334 nrspaces = len(self.rspace.search(curr).group())
335 return '%s%s>%s%s' % (self.col_p_ni,'-'*(len(curr)-nrspaces-1),
335 return '%s%s>%s%s' % (self.col_p_ni,'-'*(len(curr)-nrspaces-1),
336 ' '*nrspaces,self.col_norm_ni)
336 ' '*nrspaces,self.col_norm_ni)
337
337
338 class PromptOut(BasePrompt):
338 class PromptOut(BasePrompt):
339 """Output interactive prompt similar to Mathematica's."""
339 """Output interactive prompt similar to Mathematica's."""
340
340
341 def __init__(self,cache,sep='',prompt='Out[\\#]: ',pad_left=True):
341 def __init__(self,cache,sep='',prompt='Out[\\#]: ',pad_left=True):
342 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
342 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
343 if not self.p_template:
343 if not self.p_template:
344 self.__str__ = lambda: ''
344 self.__str__ = lambda: ''
345
345
346 def set_colors(self):
346 def set_colors(self):
347 self.set_p_str()
347 self.set_p_str()
348 Colors = self.cache.color_table.active_colors # shorthand
348 Colors = self.cache.color_table.active_colors # shorthand
349 self.col_p = Colors.out_prompt
349 self.col_p = Colors.out_prompt
350 self.col_num = Colors.out_number
350 self.col_num = Colors.out_number
351 self.col_norm = Colors.normal
351 self.col_norm = Colors.normal
352
352
353 class Prompt2(BasePrompt):
353 class Prompt2(BasePrompt):
354 """Interactive continuation prompt."""
354 """Interactive continuation prompt."""
355
355
356 def __init__(self,cache,prompt=' .\\D.: ',pad_left=True):
356 def __init__(self,cache,prompt=' .\\D.: ',pad_left=True):
357 self.cache = cache
357 self.cache = cache
358 self.p_template = prompt
358 self.p_template = prompt
359 self.pad_left = pad_left
359 self.pad_left = pad_left
360 self.set_p_str()
360 self.set_p_str()
361
361
362 def set_p_str(self):
362 def set_p_str(self):
363 import os,time # needed in locals for prompt string handling
363 import os,time # needed in locals for prompt string handling
364 loc = locals()
364 loc = locals()
365 self.p_str = ItplNS('%s%s%s' %
365 self.p_str = ItplNS('%s%s%s' %
366 ('${self.col_p2}',
366 ('${self.col_p2}',
367 multiple_replace(prompt_specials, self.p_template),
367 multiple_replace(prompt_specials, self.p_template),
368 '$self.col_norm'),
368 '$self.col_norm'),
369 self.cache.user_ns,loc)
369 self.cache.user_ns,loc)
370 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
370 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
371 self.p_template),
371 self.p_template),
372 self.cache.user_ns,loc)
372 self.cache.user_ns,loc)
373
373
374 def set_colors(self):
374 def set_colors(self):
375 self.set_p_str()
375 self.set_p_str()
376 Colors = self.cache.color_table.active_colors
376 Colors = self.cache.color_table.active_colors
377 self.col_p2 = Colors.in_prompt2
377 self.col_p2 = Colors.in_prompt2
378 self.col_norm = Colors.in_normal
378 self.col_norm = Colors.in_normal
379 # FIXME (2004-06-16) HACK: prevent crashes for users who haven't
379 # FIXME (2004-06-16) HACK: prevent crashes for users who haven't
380 # updated their prompt_in2 definitions. Remove eventually.
380 # updated their prompt_in2 definitions. Remove eventually.
381 self.col_p = Colors.out_prompt
381 self.col_p = Colors.out_prompt
382 self.col_num = Colors.out_number
382 self.col_num = Colors.out_number
383
383
384
384
385 #-----------------------------------------------------------------------------
385 #-----------------------------------------------------------------------------
386 class CachedOutput:
386 class CachedOutput:
387 """Class for printing output from calculations while keeping a cache of
387 """Class for printing output from calculations while keeping a cache of
388 reults. It dynamically creates global variables prefixed with _ which
388 reults. It dynamically creates global variables prefixed with _ which
389 contain these results.
389 contain these results.
390
390
391 Meant to be used as a sys.displayhook replacement, providing numbered
391 Meant to be used as a sys.displayhook replacement, providing numbered
392 prompts and cache services.
392 prompts and cache services.
393
393
394 Initialize with initial and final values for cache counter (this defines
394 Initialize with initial and final values for cache counter (this defines
395 the maximum size of the cache."""
395 the maximum size of the cache."""
396
396
397 def __init__(self,shell,cache_size,Pprint,
397 def __init__(self,shell,cache_size,Pprint,
398 colors='NoColor',input_sep='\n',
398 colors='NoColor',input_sep='\n',
399 output_sep='\n',output_sep2='',
399 output_sep='\n',output_sep2='',
400 ps1 = None, ps2 = None,ps_out = None,pad_left=True):
400 ps1 = None, ps2 = None,ps_out = None,pad_left=True):
401
401
402 cache_size_min = 3
402 cache_size_min = 3
403 if cache_size <= 0:
403 if cache_size <= 0:
404 self.do_full_cache = 0
404 self.do_full_cache = 0
405 cache_size = 0
405 cache_size = 0
406 elif cache_size < cache_size_min:
406 elif cache_size < cache_size_min:
407 self.do_full_cache = 0
407 self.do_full_cache = 0
408 cache_size = 0
408 cache_size = 0
409 warn('caching was disabled (min value for cache size is %s).' %
409 warn('caching was disabled (min value for cache size is %s).' %
410 cache_size_min,level=3)
410 cache_size_min,level=3)
411 else:
411 else:
412 self.do_full_cache = 1
412 self.do_full_cache = 1
413
413
414 self.cache_size = cache_size
414 self.cache_size = cache_size
415 self.input_sep = input_sep
415 self.input_sep = input_sep
416
416
417 # we need a reference to the user-level namespace
417 # we need a reference to the user-level namespace
418 self.shell = shell
418 self.shell = shell
419 self.user_ns = shell.user_ns
419 self.user_ns = shell.user_ns
420 # and to the user's input
420 # and to the user's input
421 self.input_hist = shell.history.input_cache
421 self.input_hist = shell.history.input_cache
422
422
423 # Set input prompt strings and colors
423 # Set input prompt strings and colors
424 if cache_size == 0:
424 if cache_size == 0:
425 if ps1.find('%n') > -1 or ps1.find(r'\#') > -1 \
425 if ps1.find('%n') > -1 or ps1.find(r'\#') > -1 \
426 or ps1.find(r'\N') > -1:
426 or ps1.find(r'\N') > -1:
427 ps1 = '>>> '
427 ps1 = '>>> '
428 if ps2.find('%n') > -1 or ps2.find(r'\#') > -1 \
428 if ps2.find('%n') > -1 or ps2.find(r'\#') > -1 \
429 or ps2.find(r'\N') > -1:
429 or ps2.find(r'\N') > -1:
430 ps2 = '... '
430 ps2 = '... '
431 self.ps1_str = self._set_prompt_str(ps1,'In [\\#]: ','>>> ')
431 self.ps1_str = self._set_prompt_str(ps1,'In [\\#]: ','>>> ')
432 self.ps2_str = self._set_prompt_str(ps2,' .\\D.: ','... ')
432 self.ps2_str = self._set_prompt_str(ps2,' .\\D.: ','... ')
433 self.ps_out_str = self._set_prompt_str(ps_out,'Out[\\#]: ','')
433 self.ps_out_str = self._set_prompt_str(ps_out,'Out[\\#]: ','')
434
434
435 self.color_table = PromptColors
435 self.color_table = PromptColors
436 self.prompt1 = Prompt1(self,sep=input_sep,prompt=self.ps1_str,
436 self.prompt1 = Prompt1(self,sep=input_sep,prompt=self.ps1_str,
437 pad_left=pad_left)
437 pad_left=pad_left)
438 self.prompt2 = Prompt2(self,prompt=self.ps2_str,pad_left=pad_left)
438 self.prompt2 = Prompt2(self,prompt=self.ps2_str,pad_left=pad_left)
439 self.prompt_out = PromptOut(self,sep='',prompt=self.ps_out_str,
439 self.prompt_out = PromptOut(self,sep='',prompt=self.ps_out_str,
440 pad_left=pad_left)
440 pad_left=pad_left)
441 self.set_colors(colors)
441 self.set_colors(colors)
442
442
443 # other more normal stuff
443 # other more normal stuff
444 # b/c each call to the In[] prompt raises it by 1, even the first.
444 # b/c each call to the In[] prompt raises it by 1, even the first.
445 self.prompt_count = 0
445 self.prompt_count = 0
446 # Store the last prompt string each time, we need it for aligning
446 # Store the last prompt string each time, we need it for aligning
447 # continuation and auto-rewrite prompts
447 # continuation and auto-rewrite prompts
448 self.last_prompt = ''
448 self.last_prompt = ''
449 self.Pprint = Pprint
449 self.Pprint = Pprint
450 self.output_sep = output_sep
450 self.output_sep = output_sep
451 self.output_sep2 = output_sep2
451 self.output_sep2 = output_sep2
452 self._,self.__,self.___ = '','',''
452 self._,self.__,self.___ = '','',''
453 self.pprint_types = map(type,[(),[],{}])
453 self.pprint_types = map(type,[(),[],{}])
454
454
455 # these are deliberately global:
455 # these are deliberately global:
456 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
456 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
457 self.user_ns.update(to_user_ns)
457 self.user_ns.update(to_user_ns)
458
458
459 def _set_prompt_str(self,p_str,cache_def,no_cache_def):
459 def _set_prompt_str(self,p_str,cache_def,no_cache_def):
460 if p_str is None:
460 if p_str is None:
461 if self.do_full_cache:
461 if self.do_full_cache:
462 return cache_def
462 return cache_def
463 else:
463 else:
464 return no_cache_def
464 return no_cache_def
465 else:
465 else:
466 return p_str
466 return p_str
467
467
468 def set_colors(self,colors):
468 def set_colors(self,colors):
469 """Set the active color scheme and configure colors for the three
469 """Set the active color scheme and configure colors for the three
470 prompt subsystems."""
470 prompt subsystems."""
471
471
472 # FIXME: the prompt_specials global should be gobbled inside this
472 # FIXME: the prompt_specials global should be gobbled inside this
473 # class instead. Do it when cleaning up the whole 3-prompt system.
473 # class instead. Do it when cleaning up the whole 3-prompt system.
474 global prompt_specials
474 global prompt_specials
475 if colors.lower()=='nocolor':
475 if colors.lower()=='nocolor':
476 prompt_specials = prompt_specials_nocolor
476 prompt_specials = prompt_specials_nocolor
477 else:
477 else:
478 prompt_specials = prompt_specials_color
478 prompt_specials = prompt_specials_color
479
479
480 self.color_table.set_active_scheme(colors)
480 self.color_table.set_active_scheme(colors)
481 self.prompt1.set_colors()
481 self.prompt1.set_colors()
482 self.prompt2.set_colors()
482 self.prompt2.set_colors()
483 self.prompt_out.set_colors()
483 self.prompt_out.set_colors()
484
484
485 def __call__(self,arg=None):
485 def __call__(self,arg=None):
486 """Printing with history cache management.
486 """Printing with history cache management.
487
487
488 This is invoked everytime the interpreter needs to print, and is
488 This is invoked everytime the interpreter needs to print, and is
489 activated by setting the variable sys.displayhook to it."""
489 activated by setting the variable sys.displayhook to it."""
490
490
491 # If something injected a '_' variable in __builtin__, delete
491 # If something injected a '_' variable in __builtin__, delete
492 # ipython's automatic one so we don't clobber that. gettext() in
492 # ipython's automatic one so we don't clobber that. gettext() in
493 # particular uses _, so we need to stay away from it.
493 # particular uses _, so we need to stay away from it.
494 if '_' in __builtin__.__dict__:
494 if '_' in __builtin__.__dict__:
495 try:
495 try:
496 del self.user_ns['_']
496 del self.user_ns['_']
497 except KeyError:
497 except KeyError:
498 pass
498 pass
499 if arg is not None:
499 if arg is not None:
500 cout_write = Term.cout.write # fast lookup
500 cout_write = Term.cout.write # fast lookup
501 # first handle the cache and counters
501 # first handle the cache and counters
502
502
503 # do not print output if input ends in ';'
503 # do not print output if input ends in ';'
504 if self.input_hist[self.prompt_count].endswith(';\n'):
504 if self.input_hist[self.prompt_count].endswith(';\n'):
505 return
505 return
506 # don't use print, puts an extra space
506 # don't use print, puts an extra space
507 cout_write(self.output_sep)
507 cout_write(self.output_sep)
508 outprompt = self.shell.hooks.generate_output_prompt()
508 outprompt = self.shell.hooks.generate_output_prompt()
509 if self.do_full_cache:
509 if self.do_full_cache:
510 cout_write(outprompt)
510 cout_write(outprompt)
511
511
512 # and now call a possibly user-defined print mechanism
512 # and now call a possibly user-defined print mechanism
513 manipulated_val = self.display(arg)
513 manipulated_val = self.display(arg)
514
514
515 # user display hooks can change the variable to be stored in
515 # user display hooks can change the variable to be stored in
516 # output history
516 # output history
517
517
518 if manipulated_val is not None:
518 if manipulated_val is not None:
519 arg = manipulated_val
519 arg = manipulated_val
520
520
521 # avoid recursive reference when displaying _oh/Out
521 # avoid recursive reference when displaying _oh/Out
522 if arg is not self.user_ns['_oh']:
522 if arg is not self.user_ns['_oh']:
523 self.update(arg)
523 self.update(arg)
524
524
525 cout_write(self.output_sep2)
525 cout_write(self.output_sep2)
526 Term.cout.flush()
526 Term.cout.flush()
527
527
528 def _display(self,arg):
528 def _display(self,arg):
529 """Default printer method, uses pprint.
529 """Default printer method, uses pprint.
530
530
531 Do ip.set_hook("result_display", my_displayhook) for custom result
531 Do ip.set_hook("result_display", my_displayhook) for custom result
532 display, e.g. when your own objects need special formatting.
532 display, e.g. when your own objects need special formatting.
533 """
533 """
534 try:
534 try:
535 return IPython.utils.generics.result_display(arg)
535 return IPython.utils.generics.result_display(arg)
536 except TryNext:
536 except TryNext:
537 return self.shell.hooks.result_display(arg)
537 return self.shell.hooks.result_display(arg)
538
538
539 # Assign the default display method:
539 # Assign the default display method:
540 display = _display
540 display = _display
541
541
542 def update(self,arg):
542 def update(self,arg):
543 #print '***cache_count', self.cache_count # dbg
543 #print '***cache_count', self.cache_count # dbg
544 if len(self.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
544 if len(self.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
545 warn('Output cache limit (currently '+
545 warn('Output cache limit (currently '+
546 `self.cache_size`+' entries) hit.\n'
546 `self.cache_size`+' entries) hit.\n'
547 'Flushing cache and resetting history counter...\n'
547 'Flushing cache and resetting history counter...\n'
548 'The only history variables available will be _,__,___ and _1\n'
548 'The only history variables available will be _,__,___ and _1\n'
549 'with the current result.')
549 'with the current result.')
550
550
551 self.flush()
551 self.flush()
552 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
552 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
553 # we cause buggy behavior for things like gettext).
553 # we cause buggy behavior for things like gettext).
554 if '_' not in __builtin__.__dict__:
554 if '_' not in __builtin__.__dict__:
555 self.___ = self.__
555 self.___ = self.__
556 self.__ = self._
556 self.__ = self._
557 self._ = arg
557 self._ = arg
558 self.user_ns.update({'_':self._,'__':self.__,'___':self.___})
558 self.user_ns.update({'_':self._,'__':self.__,'___':self.___})
559
559
560 # hackish access to top-level namespace to create _1,_2... dynamically
560 # hackish access to top-level namespace to create _1,_2... dynamically
561 to_main = {}
561 to_main = {}
562 if self.do_full_cache:
562 if self.do_full_cache:
563 new_result = '_'+`self.prompt_count`
563 new_result = '_'+`self.prompt_count`
564 to_main[new_result] = arg
564 to_main[new_result] = arg
565 self.user_ns.update(to_main)
565 self.user_ns.update(to_main)
566 self.user_ns['_oh'][self.prompt_count] = arg
566 self.user_ns['_oh'][self.prompt_count] = arg
567
567
568 def flush(self):
568 def flush(self):
569 if not self.do_full_cache:
569 if not self.do_full_cache:
570 raise ValueError,"You shouldn't have reached the cache flush "\
570 raise ValueError,"You shouldn't have reached the cache flush "\
571 "if full caching is not enabled!"
571 "if full caching is not enabled!"
572 # delete auto-generated vars from global namespace
572 # delete auto-generated vars from global namespace
573
573
574 for n in range(1,self.prompt_count + 1):
574 for n in range(1,self.prompt_count + 1):
575 key = '_'+`n`
575 key = '_'+`n`
576 try:
576 try:
577 del self.user_ns[key]
577 del self.user_ns[key]
578 except: pass
578 except: pass
579 self.user_ns['_oh'].clear()
579 self.user_ns['_oh'].clear()
580
580
581 if '_' not in __builtin__.__dict__:
581 if '_' not in __builtin__.__dict__:
582 self.user_ns.update({'_':None,'__':None, '___':None})
582 self.user_ns.update({'_':None,'__':None, '___':None})
583 import gc
583 import gc
584 gc.collect() # xxx needed?
584 gc.collect() # xxx needed?
585
585
@@ -1,300 +1,300
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.utils.platutils import find_cmd
33 from IPython.utils.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', 'lib', 'irunner'))
102 EXCLUDE.append(pjoin('IPython', 'lib', '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 ['backgroundjobs.py', 'coloransi.py', 'completer.py', 'configloader.py',
201 ['backgroundjobs.py', 'coloransi.py', 'completer.py', 'configloader.py',
202 'crashhandler.py', 'debugger.py', 'deepreload.py', 'demo.py',
202 'crashhandler.py', 'debugger.py', 'deepreload.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()
General Comments 0
You need to be logged in to leave comments. Login now