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