##// END OF EJS Templates
Fix typos
Min ho Kim -
Show More
@@ -1,462 +1,462 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 An application for IPython.
3 An application for IPython.
4
4
5 All top-level applications should use the classes in this module for
5 All top-level applications should use the classes in this module for
6 handling configuration and creating configurables.
6 handling configuration and creating configurables.
7
7
8 The job of an :class:`Application` is to create the master configuration
8 The job of an :class:`Application` is to create the master configuration
9 object and then create the configurable objects, passing the config to them.
9 object and then create the configurable objects, passing the config to them.
10 """
10 """
11
11
12 # Copyright (c) IPython Development Team.
12 # Copyright (c) IPython Development Team.
13 # Distributed under the terms of the Modified BSD License.
13 # Distributed under the terms of the Modified BSD License.
14
14
15 import atexit
15 import atexit
16 from copy import deepcopy
16 from copy import deepcopy
17 import glob
17 import glob
18 import logging
18 import logging
19 import os
19 import os
20 import shutil
20 import shutil
21 import sys
21 import sys
22
22
23 from traitlets.config.application import Application, catch_config_error
23 from traitlets.config.application import Application, catch_config_error
24 from traitlets.config.loader import ConfigFileNotFound, PyFileConfigLoader
24 from traitlets.config.loader import ConfigFileNotFound, PyFileConfigLoader
25 from IPython.core import release, crashhandler
25 from IPython.core import release, crashhandler
26 from IPython.core.profiledir import ProfileDir, ProfileDirError
26 from IPython.core.profiledir import ProfileDir, ProfileDirError
27 from IPython.paths import get_ipython_dir, get_ipython_package_dir
27 from IPython.paths import get_ipython_dir, get_ipython_package_dir
28 from IPython.utils.path import ensure_dir_exists
28 from IPython.utils.path import ensure_dir_exists
29 from traitlets import (
29 from traitlets import (
30 List, Unicode, Type, Bool, Set, Instance, Undefined,
30 List, Unicode, Type, Bool, Set, Instance, Undefined,
31 default, observe,
31 default, observe,
32 )
32 )
33
33
34 if os.name == 'nt':
34 if os.name == 'nt':
35 programdata = os.environ.get('PROGRAMDATA', None)
35 programdata = os.environ.get('PROGRAMDATA', None)
36 if programdata:
36 if programdata:
37 SYSTEM_CONFIG_DIRS = [os.path.join(programdata, 'ipython')]
37 SYSTEM_CONFIG_DIRS = [os.path.join(programdata, 'ipython')]
38 else: # PROGRAMDATA is not defined by default on XP.
38 else: # PROGRAMDATA is not defined by default on XP.
39 SYSTEM_CONFIG_DIRS = []
39 SYSTEM_CONFIG_DIRS = []
40 else:
40 else:
41 SYSTEM_CONFIG_DIRS = [
41 SYSTEM_CONFIG_DIRS = [
42 "/usr/local/etc/ipython",
42 "/usr/local/etc/ipython",
43 "/etc/ipython",
43 "/etc/ipython",
44 ]
44 ]
45
45
46
46
47 ENV_CONFIG_DIRS = []
47 ENV_CONFIG_DIRS = []
48 _env_config_dir = os.path.join(sys.prefix, 'etc', 'ipython')
48 _env_config_dir = os.path.join(sys.prefix, 'etc', 'ipython')
49 if _env_config_dir not in SYSTEM_CONFIG_DIRS:
49 if _env_config_dir not in SYSTEM_CONFIG_DIRS:
50 # only add ENV_CONFIG if sys.prefix is not already included
50 # only add ENV_CONFIG if sys.prefix is not already included
51 ENV_CONFIG_DIRS.append(_env_config_dir)
51 ENV_CONFIG_DIRS.append(_env_config_dir)
52
52
53
53
54 _envvar = os.environ.get('IPYTHON_SUPPRESS_CONFIG_ERRORS')
54 _envvar = os.environ.get('IPYTHON_SUPPRESS_CONFIG_ERRORS')
55 if _envvar in {None, ''}:
55 if _envvar in {None, ''}:
56 IPYTHON_SUPPRESS_CONFIG_ERRORS = None
56 IPYTHON_SUPPRESS_CONFIG_ERRORS = None
57 else:
57 else:
58 if _envvar.lower() in {'1','true'}:
58 if _envvar.lower() in {'1','true'}:
59 IPYTHON_SUPPRESS_CONFIG_ERRORS = True
59 IPYTHON_SUPPRESS_CONFIG_ERRORS = True
60 elif _envvar.lower() in {'0','false'} :
60 elif _envvar.lower() in {'0','false'} :
61 IPYTHON_SUPPRESS_CONFIG_ERRORS = False
61 IPYTHON_SUPPRESS_CONFIG_ERRORS = False
62 else:
62 else:
63 sys.exit("Unsupported value for environment variable: 'IPYTHON_SUPPRESS_CONFIG_ERRORS' is set to '%s' which is none of {'0', '1', 'false', 'true', ''}."% _envvar )
63 sys.exit("Unsupported value for environment variable: 'IPYTHON_SUPPRESS_CONFIG_ERRORS' is set to '%s' which is none of {'0', '1', 'false', 'true', ''}."% _envvar )
64
64
65 # aliases and flags
65 # aliases and flags
66
66
67 base_aliases = {
67 base_aliases = {
68 'profile-dir' : 'ProfileDir.location',
68 'profile-dir' : 'ProfileDir.location',
69 'profile' : 'BaseIPythonApplication.profile',
69 'profile' : 'BaseIPythonApplication.profile',
70 'ipython-dir' : 'BaseIPythonApplication.ipython_dir',
70 'ipython-dir' : 'BaseIPythonApplication.ipython_dir',
71 'log-level' : 'Application.log_level',
71 'log-level' : 'Application.log_level',
72 'config' : 'BaseIPythonApplication.extra_config_file',
72 'config' : 'BaseIPythonApplication.extra_config_file',
73 }
73 }
74
74
75 base_flags = dict(
75 base_flags = dict(
76 debug = ({'Application' : {'log_level' : logging.DEBUG}},
76 debug = ({'Application' : {'log_level' : logging.DEBUG}},
77 "set log level to logging.DEBUG (maximize logging output)"),
77 "set log level to logging.DEBUG (maximize logging output)"),
78 quiet = ({'Application' : {'log_level' : logging.CRITICAL}},
78 quiet = ({'Application' : {'log_level' : logging.CRITICAL}},
79 "set log level to logging.CRITICAL (minimize logging output)"),
79 "set log level to logging.CRITICAL (minimize logging output)"),
80 init = ({'BaseIPythonApplication' : {
80 init = ({'BaseIPythonApplication' : {
81 'copy_config_files' : True,
81 'copy_config_files' : True,
82 'auto_create' : True}
82 'auto_create' : True}
83 }, """Initialize profile with default config files. This is equivalent
83 }, """Initialize profile with default config files. This is equivalent
84 to running `ipython profile create <profile>` prior to startup.
84 to running `ipython profile create <profile>` prior to startup.
85 """)
85 """)
86 )
86 )
87
87
88 class ProfileAwareConfigLoader(PyFileConfigLoader):
88 class ProfileAwareConfigLoader(PyFileConfigLoader):
89 """A Python file config loader that is aware of IPython profiles."""
89 """A Python file config loader that is aware of IPython profiles."""
90 def load_subconfig(self, fname, path=None, profile=None):
90 def load_subconfig(self, fname, path=None, profile=None):
91 if profile is not None:
91 if profile is not None:
92 try:
92 try:
93 profile_dir = ProfileDir.find_profile_dir_by_name(
93 profile_dir = ProfileDir.find_profile_dir_by_name(
94 get_ipython_dir(),
94 get_ipython_dir(),
95 profile,
95 profile,
96 )
96 )
97 except ProfileDirError:
97 except ProfileDirError:
98 return
98 return
99 path = profile_dir.location
99 path = profile_dir.location
100 return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path)
100 return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path)
101
101
102 class BaseIPythonApplication(Application):
102 class BaseIPythonApplication(Application):
103
103
104 name = u'ipython'
104 name = u'ipython'
105 description = Unicode(u'IPython: an enhanced interactive Python shell.')
105 description = Unicode(u'IPython: an enhanced interactive Python shell.')
106 version = Unicode(release.version)
106 version = Unicode(release.version)
107
107
108 aliases = base_aliases
108 aliases = base_aliases
109 flags = base_flags
109 flags = base_flags
110 classes = List([ProfileDir])
110 classes = List([ProfileDir])
111
111
112 # enable `load_subconfig('cfg.py', profile='name')`
112 # enable `load_subconfig('cfg.py', profile='name')`
113 python_config_loader_class = ProfileAwareConfigLoader
113 python_config_loader_class = ProfileAwareConfigLoader
114
114
115 # Track whether the config_file has changed,
115 # Track whether the config_file has changed,
116 # because some logic happens only if we aren't using the default.
116 # because some logic happens only if we aren't using the default.
117 config_file_specified = Set()
117 config_file_specified = Set()
118
118
119 config_file_name = Unicode()
119 config_file_name = Unicode()
120 @default('config_file_name')
120 @default('config_file_name')
121 def _config_file_name_default(self):
121 def _config_file_name_default(self):
122 return self.name.replace('-','_') + u'_config.py'
122 return self.name.replace('-','_') + u'_config.py'
123 @observe('config_file_name')
123 @observe('config_file_name')
124 def _config_file_name_changed(self, change):
124 def _config_file_name_changed(self, change):
125 if change['new'] != change['old']:
125 if change['new'] != change['old']:
126 self.config_file_specified.add(change['new'])
126 self.config_file_specified.add(change['new'])
127
127
128 # The directory that contains IPython's builtin profiles.
128 # The directory that contains IPython's builtin profiles.
129 builtin_profile_dir = Unicode(
129 builtin_profile_dir = Unicode(
130 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
130 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
131 )
131 )
132
132
133 config_file_paths = List(Unicode())
133 config_file_paths = List(Unicode())
134 @default('config_file_paths')
134 @default('config_file_paths')
135 def _config_file_paths_default(self):
135 def _config_file_paths_default(self):
136 return [os.getcwd()]
136 return [os.getcwd()]
137
137
138 extra_config_file = Unicode(
138 extra_config_file = Unicode(
139 help="""Path to an extra config file to load.
139 help="""Path to an extra config file to load.
140
140
141 If specified, load this config file in addition to any other IPython config.
141 If specified, load this config file in addition to any other IPython config.
142 """).tag(config=True)
142 """).tag(config=True)
143 @observe('extra_config_file')
143 @observe('extra_config_file')
144 def _extra_config_file_changed(self, change):
144 def _extra_config_file_changed(self, change):
145 old = change['old']
145 old = change['old']
146 new = change['new']
146 new = change['new']
147 try:
147 try:
148 self.config_files.remove(old)
148 self.config_files.remove(old)
149 except ValueError:
149 except ValueError:
150 pass
150 pass
151 self.config_file_specified.add(new)
151 self.config_file_specified.add(new)
152 self.config_files.append(new)
152 self.config_files.append(new)
153
153
154 profile = Unicode(u'default',
154 profile = Unicode(u'default',
155 help="""The IPython profile to use."""
155 help="""The IPython profile to use."""
156 ).tag(config=True)
156 ).tag(config=True)
157
157
158 @observe('profile')
158 @observe('profile')
159 def _profile_changed(self, change):
159 def _profile_changed(self, change):
160 self.builtin_profile_dir = os.path.join(
160 self.builtin_profile_dir = os.path.join(
161 get_ipython_package_dir(), u'config', u'profile', change['new']
161 get_ipython_package_dir(), u'config', u'profile', change['new']
162 )
162 )
163
163
164 ipython_dir = Unicode(
164 ipython_dir = Unicode(
165 help="""
165 help="""
166 The name of the IPython directory. This directory is used for logging
166 The name of the IPython directory. This directory is used for logging
167 configuration (through profiles), history storage, etc. The default
167 configuration (through profiles), history storage, etc. The default
168 is usually $HOME/.ipython. This option can also be specified through
168 is usually $HOME/.ipython. This option can also be specified through
169 the environment variable IPYTHONDIR.
169 the environment variable IPYTHONDIR.
170 """
170 """
171 ).tag(config=True)
171 ).tag(config=True)
172 @default('ipython_dir')
172 @default('ipython_dir')
173 def _ipython_dir_default(self):
173 def _ipython_dir_default(self):
174 d = get_ipython_dir()
174 d = get_ipython_dir()
175 self._ipython_dir_changed({
175 self._ipython_dir_changed({
176 'name': 'ipython_dir',
176 'name': 'ipython_dir',
177 'old': d,
177 'old': d,
178 'new': d,
178 'new': d,
179 })
179 })
180 return d
180 return d
181
181
182 _in_init_profile_dir = False
182 _in_init_profile_dir = False
183 profile_dir = Instance(ProfileDir, allow_none=True)
183 profile_dir = Instance(ProfileDir, allow_none=True)
184 @default('profile_dir')
184 @default('profile_dir')
185 def _profile_dir_default(self):
185 def _profile_dir_default(self):
186 # avoid recursion
186 # avoid recursion
187 if self._in_init_profile_dir:
187 if self._in_init_profile_dir:
188 return
188 return
189 # profile_dir requested early, force initialization
189 # profile_dir requested early, force initialization
190 self.init_profile_dir()
190 self.init_profile_dir()
191 return self.profile_dir
191 return self.profile_dir
192
192
193 overwrite = Bool(False,
193 overwrite = Bool(False,
194 help="""Whether to overwrite existing config files when copying"""
194 help="""Whether to overwrite existing config files when copying"""
195 ).tag(config=True)
195 ).tag(config=True)
196 auto_create = Bool(False,
196 auto_create = Bool(False,
197 help="""Whether to create profile dir if it doesn't exist"""
197 help="""Whether to create profile dir if it doesn't exist"""
198 ).tag(config=True)
198 ).tag(config=True)
199
199
200 config_files = List(Unicode())
200 config_files = List(Unicode())
201 @default('config_files')
201 @default('config_files')
202 def _config_files_default(self):
202 def _config_files_default(self):
203 return [self.config_file_name]
203 return [self.config_file_name]
204
204
205 copy_config_files = Bool(False,
205 copy_config_files = Bool(False,
206 help="""Whether to install the default config files into the profile dir.
206 help="""Whether to install the default config files into the profile dir.
207 If a new profile is being created, and IPython contains config files for that
207 If a new profile is being created, and IPython contains config files for that
208 profile, then they will be staged into the new directory. Otherwise,
208 profile, then they will be staged into the new directory. Otherwise,
209 default config files will be automatically generated.
209 default config files will be automatically generated.
210 """).tag(config=True)
210 """).tag(config=True)
211
211
212 verbose_crash = Bool(False,
212 verbose_crash = Bool(False,
213 help="""Create a massive crash report when IPython encounters what may be an
213 help="""Create a massive crash report when IPython encounters what may be an
214 internal error. The default is to append a short message to the
214 internal error. The default is to append a short message to the
215 usual traceback""").tag(config=True)
215 usual traceback""").tag(config=True)
216
216
217 # The class to use as the crash handler.
217 # The class to use as the crash handler.
218 crash_handler_class = Type(crashhandler.CrashHandler)
218 crash_handler_class = Type(crashhandler.CrashHandler)
219
219
220 @catch_config_error
220 @catch_config_error
221 def __init__(self, **kwargs):
221 def __init__(self, **kwargs):
222 super(BaseIPythonApplication, self).__init__(**kwargs)
222 super(BaseIPythonApplication, self).__init__(**kwargs)
223 # ensure current working directory exists
223 # ensure current working directory exists
224 try:
224 try:
225 os.getcwd()
225 os.getcwd()
226 except:
226 except:
227 # exit if cwd doesn't exist
227 # exit if cwd doesn't exist
228 self.log.error("Current working directory doesn't exist.")
228 self.log.error("Current working directory doesn't exist.")
229 self.exit(1)
229 self.exit(1)
230
230
231 #-------------------------------------------------------------------------
231 #-------------------------------------------------------------------------
232 # Various stages of Application creation
232 # Various stages of Application creation
233 #-------------------------------------------------------------------------
233 #-------------------------------------------------------------------------
234
234
235 deprecated_subcommands = {}
235 deprecated_subcommands = {}
236
236
237 def initialize_subcommand(self, subc, argv=None):
237 def initialize_subcommand(self, subc, argv=None):
238 if subc in self.deprecated_subcommands:
238 if subc in self.deprecated_subcommands:
239 self.log.warning("Subcommand `ipython {sub}` is deprecated and will be removed "
239 self.log.warning("Subcommand `ipython {sub}` is deprecated and will be removed "
240 "in future versions.".format(sub=subc))
240 "in future versions.".format(sub=subc))
241 self.log.warning("You likely want to use `jupyter {sub}` in the "
241 self.log.warning("You likely want to use `jupyter {sub}` in the "
242 "future".format(sub=subc))
242 "future".format(sub=subc))
243 return super(BaseIPythonApplication, self).initialize_subcommand(subc, argv)
243 return super(BaseIPythonApplication, self).initialize_subcommand(subc, argv)
244
244
245 def init_crash_handler(self):
245 def init_crash_handler(self):
246 """Create a crash handler, typically setting sys.excepthook to it."""
246 """Create a crash handler, typically setting sys.excepthook to it."""
247 self.crash_handler = self.crash_handler_class(self)
247 self.crash_handler = self.crash_handler_class(self)
248 sys.excepthook = self.excepthook
248 sys.excepthook = self.excepthook
249 def unset_crashhandler():
249 def unset_crashhandler():
250 sys.excepthook = sys.__excepthook__
250 sys.excepthook = sys.__excepthook__
251 atexit.register(unset_crashhandler)
251 atexit.register(unset_crashhandler)
252
252
253 def excepthook(self, etype, evalue, tb):
253 def excepthook(self, etype, evalue, tb):
254 """this is sys.excepthook after init_crashhandler
254 """this is sys.excepthook after init_crashhandler
255
255
256 set self.verbose_crash=True to use our full crashhandler, instead of
256 set self.verbose_crash=True to use our full crashhandler, instead of
257 a regular traceback with a short message (crash_handler_lite)
257 a regular traceback with a short message (crash_handler_lite)
258 """
258 """
259
259
260 if self.verbose_crash:
260 if self.verbose_crash:
261 return self.crash_handler(etype, evalue, tb)
261 return self.crash_handler(etype, evalue, tb)
262 else:
262 else:
263 return crashhandler.crash_handler_lite(etype, evalue, tb)
263 return crashhandler.crash_handler_lite(etype, evalue, tb)
264
264
265 @observe('ipython_dir')
265 @observe('ipython_dir')
266 def _ipython_dir_changed(self, change):
266 def _ipython_dir_changed(self, change):
267 old = change['old']
267 old = change['old']
268 new = change['new']
268 new = change['new']
269 if old is not Undefined:
269 if old is not Undefined:
270 str_old = os.path.abspath(old)
270 str_old = os.path.abspath(old)
271 if str_old in sys.path:
271 if str_old in sys.path:
272 sys.path.remove(str_old)
272 sys.path.remove(str_old)
273 str_path = os.path.abspath(new)
273 str_path = os.path.abspath(new)
274 sys.path.append(str_path)
274 sys.path.append(str_path)
275 ensure_dir_exists(new)
275 ensure_dir_exists(new)
276 readme = os.path.join(new, 'README')
276 readme = os.path.join(new, 'README')
277 readme_src = os.path.join(get_ipython_package_dir(), u'config', u'profile', 'README')
277 readme_src = os.path.join(get_ipython_package_dir(), u'config', u'profile', 'README')
278 if not os.path.exists(readme) and os.path.exists(readme_src):
278 if not os.path.exists(readme) and os.path.exists(readme_src):
279 shutil.copy(readme_src, readme)
279 shutil.copy(readme_src, readme)
280 for d in ('extensions', 'nbextensions'):
280 for d in ('extensions', 'nbextensions'):
281 path = os.path.join(new, d)
281 path = os.path.join(new, d)
282 try:
282 try:
283 ensure_dir_exists(path)
283 ensure_dir_exists(path)
284 except OSError as e:
284 except OSError as e:
285 # this will not be EEXIST
285 # this will not be EEXIST
286 self.log.error("couldn't create path %s: %s", path, e)
286 self.log.error("couldn't create path %s: %s", path, e)
287 self.log.debug("IPYTHONDIR set to: %s" % new)
287 self.log.debug("IPYTHONDIR set to: %s" % new)
288
288
289 def load_config_file(self, suppress_errors=IPYTHON_SUPPRESS_CONFIG_ERRORS):
289 def load_config_file(self, suppress_errors=IPYTHON_SUPPRESS_CONFIG_ERRORS):
290 """Load the config file.
290 """Load the config file.
291
291
292 By default, errors in loading config are handled, and a warning
292 By default, errors in loading config are handled, and a warning
293 printed on screen. For testing, the suppress_errors option is set
293 printed on screen. For testing, the suppress_errors option is set
294 to False, so errors will make tests fail.
294 to False, so errors will make tests fail.
295
295
296 `supress_errors` default value is to be `None` in which case the
296 `suppress_errors` default value is to be `None` in which case the
297 behavior default to the one of `traitlets.Application`.
297 behavior default to the one of `traitlets.Application`.
298
298
299 The default value can be set :
299 The default value can be set :
300 - to `False` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '0', or 'false' (case insensitive).
300 - to `False` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '0', or 'false' (case insensitive).
301 - to `True` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '1' or 'true' (case insensitive).
301 - to `True` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '1' or 'true' (case insensitive).
302 - to `None` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '' (empty string) or leaving it unset.
302 - to `None` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '' (empty string) or leaving it unset.
303
303
304 Any other value are invalid, and will make IPython exit with a non-zero return code.
304 Any other value are invalid, and will make IPython exit with a non-zero return code.
305 """
305 """
306
306
307
307
308 self.log.debug("Searching path %s for config files", self.config_file_paths)
308 self.log.debug("Searching path %s for config files", self.config_file_paths)
309 base_config = 'ipython_config.py'
309 base_config = 'ipython_config.py'
310 self.log.debug("Attempting to load config file: %s" %
310 self.log.debug("Attempting to load config file: %s" %
311 base_config)
311 base_config)
312 try:
312 try:
313 if suppress_errors is not None:
313 if suppress_errors is not None:
314 old_value = Application.raise_config_file_errors
314 old_value = Application.raise_config_file_errors
315 Application.raise_config_file_errors = not suppress_errors;
315 Application.raise_config_file_errors = not suppress_errors;
316 Application.load_config_file(
316 Application.load_config_file(
317 self,
317 self,
318 base_config,
318 base_config,
319 path=self.config_file_paths
319 path=self.config_file_paths
320 )
320 )
321 except ConfigFileNotFound:
321 except ConfigFileNotFound:
322 # ignore errors loading parent
322 # ignore errors loading parent
323 self.log.debug("Config file %s not found", base_config)
323 self.log.debug("Config file %s not found", base_config)
324 pass
324 pass
325 if suppress_errors is not None:
325 if suppress_errors is not None:
326 Application.raise_config_file_errors = old_value
326 Application.raise_config_file_errors = old_value
327
327
328 for config_file_name in self.config_files:
328 for config_file_name in self.config_files:
329 if not config_file_name or config_file_name == base_config:
329 if not config_file_name or config_file_name == base_config:
330 continue
330 continue
331 self.log.debug("Attempting to load config file: %s" %
331 self.log.debug("Attempting to load config file: %s" %
332 self.config_file_name)
332 self.config_file_name)
333 try:
333 try:
334 Application.load_config_file(
334 Application.load_config_file(
335 self,
335 self,
336 config_file_name,
336 config_file_name,
337 path=self.config_file_paths
337 path=self.config_file_paths
338 )
338 )
339 except ConfigFileNotFound:
339 except ConfigFileNotFound:
340 # Only warn if the default config file was NOT being used.
340 # Only warn if the default config file was NOT being used.
341 if config_file_name in self.config_file_specified:
341 if config_file_name in self.config_file_specified:
342 msg = self.log.warning
342 msg = self.log.warning
343 else:
343 else:
344 msg = self.log.debug
344 msg = self.log.debug
345 msg("Config file not found, skipping: %s", config_file_name)
345 msg("Config file not found, skipping: %s", config_file_name)
346 except Exception:
346 except Exception:
347 # For testing purposes.
347 # For testing purposes.
348 if not suppress_errors:
348 if not suppress_errors:
349 raise
349 raise
350 self.log.warning("Error loading config file: %s" %
350 self.log.warning("Error loading config file: %s" %
351 self.config_file_name, exc_info=True)
351 self.config_file_name, exc_info=True)
352
352
353 def init_profile_dir(self):
353 def init_profile_dir(self):
354 """initialize the profile dir"""
354 """initialize the profile dir"""
355 self._in_init_profile_dir = True
355 self._in_init_profile_dir = True
356 if self.profile_dir is not None:
356 if self.profile_dir is not None:
357 # already ran
357 # already ran
358 return
358 return
359 if 'ProfileDir.location' not in self.config:
359 if 'ProfileDir.location' not in self.config:
360 # location not specified, find by profile name
360 # location not specified, find by profile name
361 try:
361 try:
362 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
362 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
363 except ProfileDirError:
363 except ProfileDirError:
364 # not found, maybe create it (always create default profile)
364 # not found, maybe create it (always create default profile)
365 if self.auto_create or self.profile == 'default':
365 if self.auto_create or self.profile == 'default':
366 try:
366 try:
367 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
367 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
368 except ProfileDirError:
368 except ProfileDirError:
369 self.log.fatal("Could not create profile: %r"%self.profile)
369 self.log.fatal("Could not create profile: %r"%self.profile)
370 self.exit(1)
370 self.exit(1)
371 else:
371 else:
372 self.log.info("Created profile dir: %r"%p.location)
372 self.log.info("Created profile dir: %r"%p.location)
373 else:
373 else:
374 self.log.fatal("Profile %r not found."%self.profile)
374 self.log.fatal("Profile %r not found."%self.profile)
375 self.exit(1)
375 self.exit(1)
376 else:
376 else:
377 self.log.debug("Using existing profile dir: %r"%p.location)
377 self.log.debug("Using existing profile dir: %r"%p.location)
378 else:
378 else:
379 location = self.config.ProfileDir.location
379 location = self.config.ProfileDir.location
380 # location is fully specified
380 # location is fully specified
381 try:
381 try:
382 p = ProfileDir.find_profile_dir(location, self.config)
382 p = ProfileDir.find_profile_dir(location, self.config)
383 except ProfileDirError:
383 except ProfileDirError:
384 # not found, maybe create it
384 # not found, maybe create it
385 if self.auto_create:
385 if self.auto_create:
386 try:
386 try:
387 p = ProfileDir.create_profile_dir(location, self.config)
387 p = ProfileDir.create_profile_dir(location, self.config)
388 except ProfileDirError:
388 except ProfileDirError:
389 self.log.fatal("Could not create profile directory: %r"%location)
389 self.log.fatal("Could not create profile directory: %r"%location)
390 self.exit(1)
390 self.exit(1)
391 else:
391 else:
392 self.log.debug("Creating new profile dir: %r"%location)
392 self.log.debug("Creating new profile dir: %r"%location)
393 else:
393 else:
394 self.log.fatal("Profile directory %r not found."%location)
394 self.log.fatal("Profile directory %r not found."%location)
395 self.exit(1)
395 self.exit(1)
396 else:
396 else:
397 self.log.info("Using existing profile dir: %r"%location)
397 self.log.info("Using existing profile dir: %r"%location)
398 # if profile_dir is specified explicitly, set profile name
398 # if profile_dir is specified explicitly, set profile name
399 dir_name = os.path.basename(p.location)
399 dir_name = os.path.basename(p.location)
400 if dir_name.startswith('profile_'):
400 if dir_name.startswith('profile_'):
401 self.profile = dir_name[8:]
401 self.profile = dir_name[8:]
402
402
403 self.profile_dir = p
403 self.profile_dir = p
404 self.config_file_paths.append(p.location)
404 self.config_file_paths.append(p.location)
405 self._in_init_profile_dir = False
405 self._in_init_profile_dir = False
406
406
407 def init_config_files(self):
407 def init_config_files(self):
408 """[optionally] copy default config files into profile dir."""
408 """[optionally] copy default config files into profile dir."""
409 self.config_file_paths.extend(ENV_CONFIG_DIRS)
409 self.config_file_paths.extend(ENV_CONFIG_DIRS)
410 self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
410 self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
411 # copy config files
411 # copy config files
412 path = self.builtin_profile_dir
412 path = self.builtin_profile_dir
413 if self.copy_config_files:
413 if self.copy_config_files:
414 src = self.profile
414 src = self.profile
415
415
416 cfg = self.config_file_name
416 cfg = self.config_file_name
417 if path and os.path.exists(os.path.join(path, cfg)):
417 if path and os.path.exists(os.path.join(path, cfg)):
418 self.log.warning("Staging %r from %s into %r [overwrite=%s]"%(
418 self.log.warning("Staging %r from %s into %r [overwrite=%s]"%(
419 cfg, src, self.profile_dir.location, self.overwrite)
419 cfg, src, self.profile_dir.location, self.overwrite)
420 )
420 )
421 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
421 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
422 else:
422 else:
423 self.stage_default_config_file()
423 self.stage_default_config_file()
424 else:
424 else:
425 # Still stage *bundled* config files, but not generated ones
425 # Still stage *bundled* config files, but not generated ones
426 # This is necessary for `ipython profile=sympy` to load the profile
426 # This is necessary for `ipython profile=sympy` to load the profile
427 # on the first go
427 # on the first go
428 files = glob.glob(os.path.join(path, '*.py'))
428 files = glob.glob(os.path.join(path, '*.py'))
429 for fullpath in files:
429 for fullpath in files:
430 cfg = os.path.basename(fullpath)
430 cfg = os.path.basename(fullpath)
431 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
431 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
432 # file was copied
432 # file was copied
433 self.log.warning("Staging bundled %s from %s into %r"%(
433 self.log.warning("Staging bundled %s from %s into %r"%(
434 cfg, self.profile, self.profile_dir.location)
434 cfg, self.profile, self.profile_dir.location)
435 )
435 )
436
436
437
437
438 def stage_default_config_file(self):
438 def stage_default_config_file(self):
439 """auto generate default config file, and stage it into the profile."""
439 """auto generate default config file, and stage it into the profile."""
440 s = self.generate_config_file()
440 s = self.generate_config_file()
441 fname = os.path.join(self.profile_dir.location, self.config_file_name)
441 fname = os.path.join(self.profile_dir.location, self.config_file_name)
442 if self.overwrite or not os.path.exists(fname):
442 if self.overwrite or not os.path.exists(fname):
443 self.log.warning("Generating default config file: %r"%(fname))
443 self.log.warning("Generating default config file: %r"%(fname))
444 with open(fname, 'w') as f:
444 with open(fname, 'w') as f:
445 f.write(s)
445 f.write(s)
446
446
447 @catch_config_error
447 @catch_config_error
448 def initialize(self, argv=None):
448 def initialize(self, argv=None):
449 # don't hook up crash handler before parsing command-line
449 # don't hook up crash handler before parsing command-line
450 self.parse_command_line(argv)
450 self.parse_command_line(argv)
451 self.init_crash_handler()
451 self.init_crash_handler()
452 if self.subapp is not None:
452 if self.subapp is not None:
453 # stop here if subapp is taking over
453 # stop here if subapp is taking over
454 return
454 return
455 # save a copy of CLI config to re-load after config files
455 # save a copy of CLI config to re-load after config files
456 # so that it has highest priority
456 # so that it has highest priority
457 cl_config = deepcopy(self.config)
457 cl_config = deepcopy(self.config)
458 self.init_profile_dir()
458 self.init_profile_dir()
459 self.init_config_files()
459 self.init_config_files()
460 self.load_config_file()
460 self.load_config_file()
461 # enforce cl-opts override configfile opts:
461 # enforce cl-opts override configfile opts:
462 self.update_config(cl_config)
462 self.update_config(cl_config)
@@ -1,325 +1,325 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Displayhook for IPython.
2 """Displayhook for IPython.
3
3
4 This defines a callable class that IPython uses for `sys.displayhook`.
4 This defines a callable class that IPython uses for `sys.displayhook`.
5 """
5 """
6
6
7 # Copyright (c) IPython Development Team.
7 # Copyright (c) IPython Development Team.
8 # Distributed under the terms of the Modified BSD License.
8 # Distributed under the terms of the Modified BSD License.
9
9
10 import builtins as builtin_mod
10 import builtins as builtin_mod
11 import sys
11 import sys
12 import io as _io
12 import io as _io
13 import tokenize
13 import tokenize
14
14
15 from traitlets.config.configurable import Configurable
15 from traitlets.config.configurable import Configurable
16 from traitlets import Instance, Float
16 from traitlets import Instance, Float
17 from warnings import warn
17 from warnings import warn
18
18
19 # TODO: Move the various attributes (cache_size, [others now moved]). Some
19 # TODO: Move the various attributes (cache_size, [others now moved]). Some
20 # of these are also attributes of InteractiveShell. They should be on ONE object
20 # of these are also attributes of InteractiveShell. They should be on ONE object
21 # only and the other objects should ask that one object for their values.
21 # only and the other objects should ask that one object for their values.
22
22
23 class DisplayHook(Configurable):
23 class DisplayHook(Configurable):
24 """The custom IPython displayhook to replace sys.displayhook.
24 """The custom IPython displayhook to replace sys.displayhook.
25
25
26 This class does many things, but the basic idea is that it is a callable
26 This class does many things, but the basic idea is that it is a callable
27 that gets called anytime user code returns a value.
27 that gets called anytime user code returns a value.
28 """
28 """
29
29
30 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
30 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
31 allow_none=True)
31 allow_none=True)
32 exec_result = Instance('IPython.core.interactiveshell.ExecutionResult',
32 exec_result = Instance('IPython.core.interactiveshell.ExecutionResult',
33 allow_none=True)
33 allow_none=True)
34 cull_fraction = Float(0.2)
34 cull_fraction = Float(0.2)
35
35
36 def __init__(self, shell=None, cache_size=1000, **kwargs):
36 def __init__(self, shell=None, cache_size=1000, **kwargs):
37 super(DisplayHook, self).__init__(shell=shell, **kwargs)
37 super(DisplayHook, self).__init__(shell=shell, **kwargs)
38 cache_size_min = 3
38 cache_size_min = 3
39 if cache_size <= 0:
39 if cache_size <= 0:
40 self.do_full_cache = 0
40 self.do_full_cache = 0
41 cache_size = 0
41 cache_size = 0
42 elif cache_size < cache_size_min:
42 elif cache_size < cache_size_min:
43 self.do_full_cache = 0
43 self.do_full_cache = 0
44 cache_size = 0
44 cache_size = 0
45 warn('caching was disabled (min value for cache size is %s).' %
45 warn('caching was disabled (min value for cache size is %s).' %
46 cache_size_min,stacklevel=3)
46 cache_size_min,stacklevel=3)
47 else:
47 else:
48 self.do_full_cache = 1
48 self.do_full_cache = 1
49
49
50 self.cache_size = cache_size
50 self.cache_size = cache_size
51
51
52 # we need a reference to the user-level namespace
52 # we need a reference to the user-level namespace
53 self.shell = shell
53 self.shell = shell
54
54
55 self._,self.__,self.___ = '','',''
55 self._,self.__,self.___ = '','',''
56
56
57 # these are deliberately global:
57 # these are deliberately global:
58 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
58 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
59 self.shell.user_ns.update(to_user_ns)
59 self.shell.user_ns.update(to_user_ns)
60
60
61 @property
61 @property
62 def prompt_count(self):
62 def prompt_count(self):
63 return self.shell.execution_count
63 return self.shell.execution_count
64
64
65 #-------------------------------------------------------------------------
65 #-------------------------------------------------------------------------
66 # Methods used in __call__. Override these methods to modify the behavior
66 # Methods used in __call__. Override these methods to modify the behavior
67 # of the displayhook.
67 # of the displayhook.
68 #-------------------------------------------------------------------------
68 #-------------------------------------------------------------------------
69
69
70 def check_for_underscore(self):
70 def check_for_underscore(self):
71 """Check if the user has set the '_' variable by hand."""
71 """Check if the user has set the '_' variable by hand."""
72 # If something injected a '_' variable in __builtin__, delete
72 # If something injected a '_' variable in __builtin__, delete
73 # ipython's automatic one so we don't clobber that. gettext() in
73 # ipython's automatic one so we don't clobber that. gettext() in
74 # particular uses _, so we need to stay away from it.
74 # particular uses _, so we need to stay away from it.
75 if '_' in builtin_mod.__dict__:
75 if '_' in builtin_mod.__dict__:
76 try:
76 try:
77 user_value = self.shell.user_ns['_']
77 user_value = self.shell.user_ns['_']
78 if user_value is not self._:
78 if user_value is not self._:
79 return
79 return
80 del self.shell.user_ns['_']
80 del self.shell.user_ns['_']
81 except KeyError:
81 except KeyError:
82 pass
82 pass
83
83
84 def quiet(self):
84 def quiet(self):
85 """Should we silence the display hook because of ';'?"""
85 """Should we silence the display hook because of ';'?"""
86 # do not print output if input ends in ';'
86 # do not print output if input ends in ';'
87
87
88 try:
88 try:
89 cell = self.shell.history_manager.input_hist_parsed[-1]
89 cell = self.shell.history_manager.input_hist_parsed[-1]
90 except IndexError:
90 except IndexError:
91 # some uses of ipshellembed may fail here
91 # some uses of ipshellembed may fail here
92 return False
92 return False
93
93
94 sio = _io.StringIO(cell)
94 sio = _io.StringIO(cell)
95 tokens = list(tokenize.generate_tokens(sio.readline))
95 tokens = list(tokenize.generate_tokens(sio.readline))
96
96
97 for token in reversed(tokens):
97 for token in reversed(tokens):
98 if token[0] in (tokenize.ENDMARKER, tokenize.NL, tokenize.NEWLINE, tokenize.COMMENT):
98 if token[0] in (tokenize.ENDMARKER, tokenize.NL, tokenize.NEWLINE, tokenize.COMMENT):
99 continue
99 continue
100 if (token[0] == tokenize.OP) and (token[1] == ';'):
100 if (token[0] == tokenize.OP) and (token[1] == ';'):
101 return True
101 return True
102 else:
102 else:
103 return False
103 return False
104
104
105 def start_displayhook(self):
105 def start_displayhook(self):
106 """Start the displayhook, initializing resources."""
106 """Start the displayhook, initializing resources."""
107 pass
107 pass
108
108
109 def write_output_prompt(self):
109 def write_output_prompt(self):
110 """Write the output prompt.
110 """Write the output prompt.
111
111
112 The default implementation simply writes the prompt to
112 The default implementation simply writes the prompt to
113 ``sys.stdout``.
113 ``sys.stdout``.
114 """
114 """
115 # Use write, not print which adds an extra space.
115 # Use write, not print which adds an extra space.
116 sys.stdout.write(self.shell.separate_out)
116 sys.stdout.write(self.shell.separate_out)
117 outprompt = 'Out[{}]: '.format(self.shell.execution_count)
117 outprompt = 'Out[{}]: '.format(self.shell.execution_count)
118 if self.do_full_cache:
118 if self.do_full_cache:
119 sys.stdout.write(outprompt)
119 sys.stdout.write(outprompt)
120
120
121 def compute_format_data(self, result):
121 def compute_format_data(self, result):
122 """Compute format data of the object to be displayed.
122 """Compute format data of the object to be displayed.
123
123
124 The format data is a generalization of the :func:`repr` of an object.
124 The format data is a generalization of the :func:`repr` of an object.
125 In the default implementation the format data is a :class:`dict` of
125 In the default implementation the format data is a :class:`dict` of
126 key value pair where the keys are valid MIME types and the values
126 key value pair where the keys are valid MIME types and the values
127 are JSON'able data structure containing the raw data for that MIME
127 are JSON'able data structure containing the raw data for that MIME
128 type. It is up to frontends to determine pick a MIME to to use and
128 type. It is up to frontends to determine pick a MIME to to use and
129 display that data in an appropriate manner.
129 display that data in an appropriate manner.
130
130
131 This method only computes the format data for the object and should
131 This method only computes the format data for the object and should
132 NOT actually print or write that to a stream.
132 NOT actually print or write that to a stream.
133
133
134 Parameters
134 Parameters
135 ----------
135 ----------
136 result : object
136 result : object
137 The Python object passed to the display hook, whose format will be
137 The Python object passed to the display hook, whose format will be
138 computed.
138 computed.
139
139
140 Returns
140 Returns
141 -------
141 -------
142 (format_dict, md_dict) : dict
142 (format_dict, md_dict) : dict
143 format_dict is a :class:`dict` whose keys are valid MIME types and values are
143 format_dict is a :class:`dict` whose keys are valid MIME types and values are
144 JSON'able raw data for that MIME type. It is recommended that
144 JSON'able raw data for that MIME type. It is recommended that
145 all return values of this should always include the "text/plain"
145 all return values of this should always include the "text/plain"
146 MIME type representation of the object.
146 MIME type representation of the object.
147 md_dict is a :class:`dict` with the same MIME type keys
147 md_dict is a :class:`dict` with the same MIME type keys
148 of metadata associated with each output.
148 of metadata associated with each output.
149
149
150 """
150 """
151 return self.shell.display_formatter.format(result)
151 return self.shell.display_formatter.format(result)
152
152
153 # This can be set to True by the write_output_prompt method in a subclass
153 # This can be set to True by the write_output_prompt method in a subclass
154 prompt_end_newline = False
154 prompt_end_newline = False
155
155
156 def write_format_data(self, format_dict, md_dict=None):
156 def write_format_data(self, format_dict, md_dict=None):
157 """Write the format data dict to the frontend.
157 """Write the format data dict to the frontend.
158
158
159 This default version of this method simply writes the plain text
159 This default version of this method simply writes the plain text
160 representation of the object to ``sys.stdout``. Subclasses should
160 representation of the object to ``sys.stdout``. Subclasses should
161 override this method to send the entire `format_dict` to the
161 override this method to send the entire `format_dict` to the
162 frontends.
162 frontends.
163
163
164 Parameters
164 Parameters
165 ----------
165 ----------
166 format_dict : dict
166 format_dict : dict
167 The format dict for the object passed to `sys.displayhook`.
167 The format dict for the object passed to `sys.displayhook`.
168 md_dict : dict (optional)
168 md_dict : dict (optional)
169 The metadata dict to be associated with the display data.
169 The metadata dict to be associated with the display data.
170 """
170 """
171 if 'text/plain' not in format_dict:
171 if 'text/plain' not in format_dict:
172 # nothing to do
172 # nothing to do
173 return
173 return
174 # We want to print because we want to always make sure we have a
174 # We want to print because we want to always make sure we have a
175 # newline, even if all the prompt separators are ''. This is the
175 # newline, even if all the prompt separators are ''. This is the
176 # standard IPython behavior.
176 # standard IPython behavior.
177 result_repr = format_dict['text/plain']
177 result_repr = format_dict['text/plain']
178 if '\n' in result_repr:
178 if '\n' in result_repr:
179 # So that multi-line strings line up with the left column of
179 # So that multi-line strings line up with the left column of
180 # the screen, instead of having the output prompt mess up
180 # the screen, instead of having the output prompt mess up
181 # their first line.
181 # their first line.
182 # We use the prompt template instead of the expanded prompt
182 # We use the prompt template instead of the expanded prompt
183 # because the expansion may add ANSI escapes that will interfere
183 # because the expansion may add ANSI escapes that will interfere
184 # with our ability to determine whether or not we should add
184 # with our ability to determine whether or not we should add
185 # a newline.
185 # a newline.
186 if not self.prompt_end_newline:
186 if not self.prompt_end_newline:
187 # But avoid extraneous empty lines.
187 # But avoid extraneous empty lines.
188 result_repr = '\n' + result_repr
188 result_repr = '\n' + result_repr
189
189
190 try:
190 try:
191 print(result_repr)
191 print(result_repr)
192 except UnicodeEncodeError:
192 except UnicodeEncodeError:
193 # If a character is not supported by the terminal encoding replace
193 # If a character is not supported by the terminal encoding replace
194 # it with its \u or \x representation
194 # it with its \u or \x representation
195 print(result_repr.encode(sys.stdout.encoding,'backslashreplace').decode(sys.stdout.encoding))
195 print(result_repr.encode(sys.stdout.encoding,'backslashreplace').decode(sys.stdout.encoding))
196
196
197 def update_user_ns(self, result):
197 def update_user_ns(self, result):
198 """Update user_ns with various things like _, __, _1, etc."""
198 """Update user_ns with various things like _, __, _1, etc."""
199
199
200 # Avoid recursive reference when displaying _oh/Out
200 # Avoid recursive reference when displaying _oh/Out
201 if result is not self.shell.user_ns['_oh']:
201 if result is not self.shell.user_ns['_oh']:
202 if len(self.shell.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
202 if len(self.shell.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
203 self.cull_cache()
203 self.cull_cache()
204
204
205 # Don't overwrite '_' and friends if '_' is in __builtin__
205 # Don't overwrite '_' and friends if '_' is in __builtin__
206 # (otherwise we cause buggy behavior for things like gettext). and
206 # (otherwise we cause buggy behavior for things like gettext). and
207 # do not overwrite _, __ or ___ if one of these has been assigned
207 # do not overwrite _, __ or ___ if one of these has been assigned
208 # by the user.
208 # by the user.
209 update_unders = True
209 update_unders = True
210 for unders in ['_'*i for i in range(1,4)]:
210 for unders in ['_'*i for i in range(1,4)]:
211 if not unders in self.shell.user_ns:
211 if not unders in self.shell.user_ns:
212 continue
212 continue
213 if getattr(self, unders) is not self.shell.user_ns.get(unders):
213 if getattr(self, unders) is not self.shell.user_ns.get(unders):
214 update_unders = False
214 update_unders = False
215
215
216 self.___ = self.__
216 self.___ = self.__
217 self.__ = self._
217 self.__ = self._
218 self._ = result
218 self._ = result
219
219
220 if ('_' not in builtin_mod.__dict__) and (update_unders):
220 if ('_' not in builtin_mod.__dict__) and (update_unders):
221 self.shell.push({'_':self._,
221 self.shell.push({'_':self._,
222 '__':self.__,
222 '__':self.__,
223 '___':self.___}, interactive=False)
223 '___':self.___}, interactive=False)
224
224
225 # hackish access to top-level namespace to create _1,_2... dynamically
225 # hackish access to top-level namespace to create _1,_2... dynamically
226 to_main = {}
226 to_main = {}
227 if self.do_full_cache:
227 if self.do_full_cache:
228 new_result = '_%s' % self.prompt_count
228 new_result = '_%s' % self.prompt_count
229 to_main[new_result] = result
229 to_main[new_result] = result
230 self.shell.push(to_main, interactive=False)
230 self.shell.push(to_main, interactive=False)
231 self.shell.user_ns['_oh'][self.prompt_count] = result
231 self.shell.user_ns['_oh'][self.prompt_count] = result
232
232
233 def fill_exec_result(self, result):
233 def fill_exec_result(self, result):
234 if self.exec_result is not None:
234 if self.exec_result is not None:
235 self.exec_result.result = result
235 self.exec_result.result = result
236
236
237 def log_output(self, format_dict):
237 def log_output(self, format_dict):
238 """Log the output."""
238 """Log the output."""
239 if 'text/plain' not in format_dict:
239 if 'text/plain' not in format_dict:
240 # nothing to do
240 # nothing to do
241 return
241 return
242 if self.shell.logger.log_output:
242 if self.shell.logger.log_output:
243 self.shell.logger.log_write(format_dict['text/plain'], 'output')
243 self.shell.logger.log_write(format_dict['text/plain'], 'output')
244 self.shell.history_manager.output_hist_reprs[self.prompt_count] = \
244 self.shell.history_manager.output_hist_reprs[self.prompt_count] = \
245 format_dict['text/plain']
245 format_dict['text/plain']
246
246
247 def finish_displayhook(self):
247 def finish_displayhook(self):
248 """Finish up all displayhook activities."""
248 """Finish up all displayhook activities."""
249 sys.stdout.write(self.shell.separate_out2)
249 sys.stdout.write(self.shell.separate_out2)
250 sys.stdout.flush()
250 sys.stdout.flush()
251
251
252 def __call__(self, result=None):
252 def __call__(self, result=None):
253 """Printing with history cache management.
253 """Printing with history cache management.
254
254
255 This is invoked everytime the interpreter needs to print, and is
255 This is invoked every time the interpreter needs to print, and is
256 activated by setting the variable sys.displayhook to it.
256 activated by setting the variable sys.displayhook to it.
257 """
257 """
258 self.check_for_underscore()
258 self.check_for_underscore()
259 if result is not None and not self.quiet():
259 if result is not None and not self.quiet():
260 self.start_displayhook()
260 self.start_displayhook()
261 self.write_output_prompt()
261 self.write_output_prompt()
262 format_dict, md_dict = self.compute_format_data(result)
262 format_dict, md_dict = self.compute_format_data(result)
263 self.update_user_ns(result)
263 self.update_user_ns(result)
264 self.fill_exec_result(result)
264 self.fill_exec_result(result)
265 if format_dict:
265 if format_dict:
266 self.write_format_data(format_dict, md_dict)
266 self.write_format_data(format_dict, md_dict)
267 self.log_output(format_dict)
267 self.log_output(format_dict)
268 self.finish_displayhook()
268 self.finish_displayhook()
269
269
270 def cull_cache(self):
270 def cull_cache(self):
271 """Output cache is full, cull the oldest entries"""
271 """Output cache is full, cull the oldest entries"""
272 oh = self.shell.user_ns.get('_oh', {})
272 oh = self.shell.user_ns.get('_oh', {})
273 sz = len(oh)
273 sz = len(oh)
274 cull_count = max(int(sz * self.cull_fraction), 2)
274 cull_count = max(int(sz * self.cull_fraction), 2)
275 warn('Output cache limit (currently {sz} entries) hit.\n'
275 warn('Output cache limit (currently {sz} entries) hit.\n'
276 'Flushing oldest {cull_count} entries.'.format(sz=sz, cull_count=cull_count))
276 'Flushing oldest {cull_count} entries.'.format(sz=sz, cull_count=cull_count))
277
277
278 for i, n in enumerate(sorted(oh)):
278 for i, n in enumerate(sorted(oh)):
279 if i >= cull_count:
279 if i >= cull_count:
280 break
280 break
281 self.shell.user_ns.pop('_%i' % n, None)
281 self.shell.user_ns.pop('_%i' % n, None)
282 oh.pop(n, None)
282 oh.pop(n, None)
283
283
284
284
285 def flush(self):
285 def flush(self):
286 if not self.do_full_cache:
286 if not self.do_full_cache:
287 raise ValueError("You shouldn't have reached the cache flush "
287 raise ValueError("You shouldn't have reached the cache flush "
288 "if full caching is not enabled!")
288 "if full caching is not enabled!")
289 # delete auto-generated vars from global namespace
289 # delete auto-generated vars from global namespace
290
290
291 for n in range(1,self.prompt_count + 1):
291 for n in range(1,self.prompt_count + 1):
292 key = '_'+repr(n)
292 key = '_'+repr(n)
293 try:
293 try:
294 del self.shell.user_ns[key]
294 del self.shell.user_ns[key]
295 except: pass
295 except: pass
296 # In some embedded circumstances, the user_ns doesn't have the
296 # In some embedded circumstances, the user_ns doesn't have the
297 # '_oh' key set up.
297 # '_oh' key set up.
298 oh = self.shell.user_ns.get('_oh', None)
298 oh = self.shell.user_ns.get('_oh', None)
299 if oh is not None:
299 if oh is not None:
300 oh.clear()
300 oh.clear()
301
301
302 # Release our own references to objects:
302 # Release our own references to objects:
303 self._, self.__, self.___ = '', '', ''
303 self._, self.__, self.___ = '', '', ''
304
304
305 if '_' not in builtin_mod.__dict__:
305 if '_' not in builtin_mod.__dict__:
306 self.shell.user_ns.update({'_':self._,'__':self.__,'___':self.___})
306 self.shell.user_ns.update({'_':self._,'__':self.__,'___':self.___})
307 import gc
307 import gc
308 # TODO: Is this really needed?
308 # TODO: Is this really needed?
309 # IronPython blocks here forever
309 # IronPython blocks here forever
310 if sys.platform != "cli":
310 if sys.platform != "cli":
311 gc.collect()
311 gc.collect()
312
312
313
313
314 class CapturingDisplayHook(object):
314 class CapturingDisplayHook(object):
315 def __init__(self, shell, outputs=None):
315 def __init__(self, shell, outputs=None):
316 self.shell = shell
316 self.shell = shell
317 if outputs is None:
317 if outputs is None:
318 outputs = []
318 outputs = []
319 self.outputs = outputs
319 self.outputs = outputs
320
320
321 def __call__(self, result=None):
321 def __call__(self, result=None):
322 if result is None:
322 if result is None:
323 return
323 return
324 format_dict, md_dict = self.shell.display_formatter.format(result)
324 format_dict, md_dict = self.shell.display_formatter.format(result)
325 self.outputs.append({ 'data': format_dict, 'metadata': md_dict })
325 self.outputs.append({ 'data': format_dict, 'metadata': md_dict })
@@ -1,366 +1,366 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Paging capabilities for IPython.core
3 Paging capabilities for IPython.core
4
4
5 Notes
5 Notes
6 -----
6 -----
7
7
8 For now this uses IPython hooks, so it can't be in IPython.utils. If we can get
8 For now this uses IPython hooks, so it can't be in IPython.utils. If we can get
9 rid of that dependency, we could move it there.
9 rid of that dependency, we could move it there.
10 -----
10 -----
11 """
11 """
12
12
13 # Copyright (c) IPython Development Team.
13 # Copyright (c) IPython Development Team.
14 # Distributed under the terms of the Modified BSD License.
14 # Distributed under the terms of the Modified BSD License.
15
15
16
16
17 import os
17 import os
18 import re
18 import re
19 import sys
19 import sys
20 import tempfile
20 import tempfile
21
21
22 from io import UnsupportedOperation
22 from io import UnsupportedOperation
23
23
24 from IPython import get_ipython
24 from IPython import get_ipython
25 from IPython.core.display import display
25 from IPython.core.display import display
26 from IPython.core.error import TryNext
26 from IPython.core.error import TryNext
27 from IPython.utils.data import chop
27 from IPython.utils.data import chop
28 from IPython.utils.process import system
28 from IPython.utils.process import system
29 from IPython.utils.terminal import get_terminal_size
29 from IPython.utils.terminal import get_terminal_size
30 from IPython.utils import py3compat
30 from IPython.utils import py3compat
31
31
32
32
33 def display_page(strng, start=0, screen_lines=25):
33 def display_page(strng, start=0, screen_lines=25):
34 """Just display, no paging. screen_lines is ignored."""
34 """Just display, no paging. screen_lines is ignored."""
35 if isinstance(strng, dict):
35 if isinstance(strng, dict):
36 data = strng
36 data = strng
37 else:
37 else:
38 if start:
38 if start:
39 strng = u'\n'.join(strng.splitlines()[start:])
39 strng = u'\n'.join(strng.splitlines()[start:])
40 data = { 'text/plain': strng }
40 data = { 'text/plain': strng }
41 display(data, raw=True)
41 display(data, raw=True)
42
42
43
43
44 def as_hook(page_func):
44 def as_hook(page_func):
45 """Wrap a pager func to strip the `self` arg
45 """Wrap a pager func to strip the `self` arg
46
46
47 so it can be called as a hook.
47 so it can be called as a hook.
48 """
48 """
49 return lambda self, *args, **kwargs: page_func(*args, **kwargs)
49 return lambda self, *args, **kwargs: page_func(*args, **kwargs)
50
50
51
51
52 esc_re = re.compile(r"(\x1b[^m]+m)")
52 esc_re = re.compile(r"(\x1b[^m]+m)")
53
53
54 def page_dumb(strng, start=0, screen_lines=25):
54 def page_dumb(strng, start=0, screen_lines=25):
55 """Very dumb 'pager' in Python, for when nothing else works.
55 """Very dumb 'pager' in Python, for when nothing else works.
56
56
57 Only moves forward, same interface as page(), except for pager_cmd and
57 Only moves forward, same interface as page(), except for pager_cmd and
58 mode.
58 mode.
59 """
59 """
60 if isinstance(strng, dict):
60 if isinstance(strng, dict):
61 strng = strng.get('text/plain', '')
61 strng = strng.get('text/plain', '')
62 out_ln = strng.splitlines()[start:]
62 out_ln = strng.splitlines()[start:]
63 screens = chop(out_ln,screen_lines-1)
63 screens = chop(out_ln,screen_lines-1)
64 if len(screens) == 1:
64 if len(screens) == 1:
65 print(os.linesep.join(screens[0]))
65 print(os.linesep.join(screens[0]))
66 else:
66 else:
67 last_escape = ""
67 last_escape = ""
68 for scr in screens[0:-1]:
68 for scr in screens[0:-1]:
69 hunk = os.linesep.join(scr)
69 hunk = os.linesep.join(scr)
70 print(last_escape + hunk)
70 print(last_escape + hunk)
71 if not page_more():
71 if not page_more():
72 return
72 return
73 esc_list = esc_re.findall(hunk)
73 esc_list = esc_re.findall(hunk)
74 if len(esc_list) > 0:
74 if len(esc_list) > 0:
75 last_escape = esc_list[-1]
75 last_escape = esc_list[-1]
76 print(last_escape + os.linesep.join(screens[-1]))
76 print(last_escape + os.linesep.join(screens[-1]))
77
77
78 def _detect_screen_size(screen_lines_def):
78 def _detect_screen_size(screen_lines_def):
79 """Attempt to work out the number of lines on the screen.
79 """Attempt to work out the number of lines on the screen.
80
80
81 This is called by page(). It can raise an error (e.g. when run in the
81 This is called by page(). It can raise an error (e.g. when run in the
82 test suite), so it's separated out so it can easily be called in a try block.
82 test suite), so it's separated out so it can easily be called in a try block.
83 """
83 """
84 TERM = os.environ.get('TERM',None)
84 TERM = os.environ.get('TERM',None)
85 if not((TERM=='xterm' or TERM=='xterm-color') and sys.platform != 'sunos5'):
85 if not((TERM=='xterm' or TERM=='xterm-color') and sys.platform != 'sunos5'):
86 # curses causes problems on many terminals other than xterm, and
86 # curses causes problems on many terminals other than xterm, and
87 # some termios calls lock up on Sun OS5.
87 # some termios calls lock up on Sun OS5.
88 return screen_lines_def
88 return screen_lines_def
89
89
90 try:
90 try:
91 import termios
91 import termios
92 import curses
92 import curses
93 except ImportError:
93 except ImportError:
94 return screen_lines_def
94 return screen_lines_def
95
95
96 # There is a bug in curses, where *sometimes* it fails to properly
96 # There is a bug in curses, where *sometimes* it fails to properly
97 # initialize, and then after the endwin() call is made, the
97 # initialize, and then after the endwin() call is made, the
98 # terminal is left in an unusable state. Rather than trying to
98 # terminal is left in an unusable state. Rather than trying to
99 # check everytime for this (by requesting and comparing termios
99 # check every time for this (by requesting and comparing termios
100 # flags each time), we just save the initial terminal state and
100 # flags each time), we just save the initial terminal state and
101 # unconditionally reset it every time. It's cheaper than making
101 # unconditionally reset it every time. It's cheaper than making
102 # the checks.
102 # the checks.
103 try:
103 try:
104 term_flags = termios.tcgetattr(sys.stdout)
104 term_flags = termios.tcgetattr(sys.stdout)
105 except termios.error as err:
105 except termios.error as err:
106 # can fail on Linux 2.6, pager_page will catch the TypeError
106 # can fail on Linux 2.6, pager_page will catch the TypeError
107 raise TypeError('termios error: {0}'.format(err))
107 raise TypeError('termios error: {0}'.format(err))
108
108
109 try:
109 try:
110 scr = curses.initscr()
110 scr = curses.initscr()
111 except AttributeError:
111 except AttributeError:
112 # Curses on Solaris may not be complete, so we can't use it there
112 # Curses on Solaris may not be complete, so we can't use it there
113 return screen_lines_def
113 return screen_lines_def
114
114
115 screen_lines_real,screen_cols = scr.getmaxyx()
115 screen_lines_real,screen_cols = scr.getmaxyx()
116 curses.endwin()
116 curses.endwin()
117
117
118 # Restore terminal state in case endwin() didn't.
118 # Restore terminal state in case endwin() didn't.
119 termios.tcsetattr(sys.stdout,termios.TCSANOW,term_flags)
119 termios.tcsetattr(sys.stdout,termios.TCSANOW,term_flags)
120 # Now we have what we needed: the screen size in rows/columns
120 # Now we have what we needed: the screen size in rows/columns
121 return screen_lines_real
121 return screen_lines_real
122 #print '***Screen size:',screen_lines_real,'lines x',\
122 #print '***Screen size:',screen_lines_real,'lines x',\
123 #screen_cols,'columns.' # dbg
123 #screen_cols,'columns.' # dbg
124
124
125 def pager_page(strng, start=0, screen_lines=0, pager_cmd=None):
125 def pager_page(strng, start=0, screen_lines=0, pager_cmd=None):
126 """Display a string, piping through a pager after a certain length.
126 """Display a string, piping through a pager after a certain length.
127
127
128 strng can be a mime-bundle dict, supplying multiple representations,
128 strng can be a mime-bundle dict, supplying multiple representations,
129 keyed by mime-type.
129 keyed by mime-type.
130
130
131 The screen_lines parameter specifies the number of *usable* lines of your
131 The screen_lines parameter specifies the number of *usable* lines of your
132 terminal screen (total lines minus lines you need to reserve to show other
132 terminal screen (total lines minus lines you need to reserve to show other
133 information).
133 information).
134
134
135 If you set screen_lines to a number <=0, page() will try to auto-determine
135 If you set screen_lines to a number <=0, page() will try to auto-determine
136 your screen size and will only use up to (screen_size+screen_lines) for
136 your screen size and will only use up to (screen_size+screen_lines) for
137 printing, paging after that. That is, if you want auto-detection but need
137 printing, paging after that. That is, if you want auto-detection but need
138 to reserve the bottom 3 lines of the screen, use screen_lines = -3, and for
138 to reserve the bottom 3 lines of the screen, use screen_lines = -3, and for
139 auto-detection without any lines reserved simply use screen_lines = 0.
139 auto-detection without any lines reserved simply use screen_lines = 0.
140
140
141 If a string won't fit in the allowed lines, it is sent through the
141 If a string won't fit in the allowed lines, it is sent through the
142 specified pager command. If none given, look for PAGER in the environment,
142 specified pager command. If none given, look for PAGER in the environment,
143 and ultimately default to less.
143 and ultimately default to less.
144
144
145 If no system pager works, the string is sent through a 'dumb pager'
145 If no system pager works, the string is sent through a 'dumb pager'
146 written in python, very simplistic.
146 written in python, very simplistic.
147 """
147 """
148
148
149 # for compatibility with mime-bundle form:
149 # for compatibility with mime-bundle form:
150 if isinstance(strng, dict):
150 if isinstance(strng, dict):
151 strng = strng['text/plain']
151 strng = strng['text/plain']
152
152
153 # Ugly kludge, but calling curses.initscr() flat out crashes in emacs
153 # Ugly kludge, but calling curses.initscr() flat out crashes in emacs
154 TERM = os.environ.get('TERM','dumb')
154 TERM = os.environ.get('TERM','dumb')
155 if TERM in ['dumb','emacs'] and os.name != 'nt':
155 if TERM in ['dumb','emacs'] and os.name != 'nt':
156 print(strng)
156 print(strng)
157 return
157 return
158 # chop off the topmost part of the string we don't want to see
158 # chop off the topmost part of the string we don't want to see
159 str_lines = strng.splitlines()[start:]
159 str_lines = strng.splitlines()[start:]
160 str_toprint = os.linesep.join(str_lines)
160 str_toprint = os.linesep.join(str_lines)
161 num_newlines = len(str_lines)
161 num_newlines = len(str_lines)
162 len_str = len(str_toprint)
162 len_str = len(str_toprint)
163
163
164 # Dumb heuristics to guesstimate number of on-screen lines the string
164 # Dumb heuristics to guesstimate number of on-screen lines the string
165 # takes. Very basic, but good enough for docstrings in reasonable
165 # takes. Very basic, but good enough for docstrings in reasonable
166 # terminals. If someone later feels like refining it, it's not hard.
166 # terminals. If someone later feels like refining it, it's not hard.
167 numlines = max(num_newlines,int(len_str/80)+1)
167 numlines = max(num_newlines,int(len_str/80)+1)
168
168
169 screen_lines_def = get_terminal_size()[1]
169 screen_lines_def = get_terminal_size()[1]
170
170
171 # auto-determine screen size
171 # auto-determine screen size
172 if screen_lines <= 0:
172 if screen_lines <= 0:
173 try:
173 try:
174 screen_lines += _detect_screen_size(screen_lines_def)
174 screen_lines += _detect_screen_size(screen_lines_def)
175 except (TypeError, UnsupportedOperation):
175 except (TypeError, UnsupportedOperation):
176 print(str_toprint)
176 print(str_toprint)
177 return
177 return
178
178
179 #print 'numlines',numlines,'screenlines',screen_lines # dbg
179 #print 'numlines',numlines,'screenlines',screen_lines # dbg
180 if numlines <= screen_lines :
180 if numlines <= screen_lines :
181 #print '*** normal print' # dbg
181 #print '*** normal print' # dbg
182 print(str_toprint)
182 print(str_toprint)
183 else:
183 else:
184 # Try to open pager and default to internal one if that fails.
184 # Try to open pager and default to internal one if that fails.
185 # All failure modes are tagged as 'retval=1', to match the return
185 # All failure modes are tagged as 'retval=1', to match the return
186 # value of a failed system command. If any intermediate attempt
186 # value of a failed system command. If any intermediate attempt
187 # sets retval to 1, at the end we resort to our own page_dumb() pager.
187 # sets retval to 1, at the end we resort to our own page_dumb() pager.
188 pager_cmd = get_pager_cmd(pager_cmd)
188 pager_cmd = get_pager_cmd(pager_cmd)
189 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
189 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
190 if os.name == 'nt':
190 if os.name == 'nt':
191 if pager_cmd.startswith('type'):
191 if pager_cmd.startswith('type'):
192 # The default WinXP 'type' command is failing on complex strings.
192 # The default WinXP 'type' command is failing on complex strings.
193 retval = 1
193 retval = 1
194 else:
194 else:
195 fd, tmpname = tempfile.mkstemp('.txt')
195 fd, tmpname = tempfile.mkstemp('.txt')
196 try:
196 try:
197 os.close(fd)
197 os.close(fd)
198 with open(tmpname, 'wt') as tmpfile:
198 with open(tmpname, 'wt') as tmpfile:
199 tmpfile.write(strng)
199 tmpfile.write(strng)
200 cmd = "%s < %s" % (pager_cmd, tmpname)
200 cmd = "%s < %s" % (pager_cmd, tmpname)
201 # tmpfile needs to be closed for windows
201 # tmpfile needs to be closed for windows
202 if os.system(cmd):
202 if os.system(cmd):
203 retval = 1
203 retval = 1
204 else:
204 else:
205 retval = None
205 retval = None
206 finally:
206 finally:
207 os.remove(tmpname)
207 os.remove(tmpname)
208 else:
208 else:
209 try:
209 try:
210 retval = None
210 retval = None
211 # if I use popen4, things hang. No idea why.
211 # if I use popen4, things hang. No idea why.
212 #pager,shell_out = os.popen4(pager_cmd)
212 #pager,shell_out = os.popen4(pager_cmd)
213 pager = os.popen(pager_cmd, 'w')
213 pager = os.popen(pager_cmd, 'w')
214 try:
214 try:
215 pager_encoding = pager.encoding or sys.stdout.encoding
215 pager_encoding = pager.encoding or sys.stdout.encoding
216 pager.write(strng)
216 pager.write(strng)
217 finally:
217 finally:
218 retval = pager.close()
218 retval = pager.close()
219 except IOError as msg: # broken pipe when user quits
219 except IOError as msg: # broken pipe when user quits
220 if msg.args == (32, 'Broken pipe'):
220 if msg.args == (32, 'Broken pipe'):
221 retval = None
221 retval = None
222 else:
222 else:
223 retval = 1
223 retval = 1
224 except OSError:
224 except OSError:
225 # Other strange problems, sometimes seen in Win2k/cygwin
225 # Other strange problems, sometimes seen in Win2k/cygwin
226 retval = 1
226 retval = 1
227 if retval is not None:
227 if retval is not None:
228 page_dumb(strng,screen_lines=screen_lines)
228 page_dumb(strng,screen_lines=screen_lines)
229
229
230
230
231 def page(data, start=0, screen_lines=0, pager_cmd=None):
231 def page(data, start=0, screen_lines=0, pager_cmd=None):
232 """Display content in a pager, piping through a pager after a certain length.
232 """Display content in a pager, piping through a pager after a certain length.
233
233
234 data can be a mime-bundle dict, supplying multiple representations,
234 data can be a mime-bundle dict, supplying multiple representations,
235 keyed by mime-type, or text.
235 keyed by mime-type, or text.
236
236
237 Pager is dispatched via the `show_in_pager` IPython hook.
237 Pager is dispatched via the `show_in_pager` IPython hook.
238 If no hook is registered, `pager_page` will be used.
238 If no hook is registered, `pager_page` will be used.
239 """
239 """
240 # Some routines may auto-compute start offsets incorrectly and pass a
240 # Some routines may auto-compute start offsets incorrectly and pass a
241 # negative value. Offset to 0 for robustness.
241 # negative value. Offset to 0 for robustness.
242 start = max(0, start)
242 start = max(0, start)
243
243
244 # first, try the hook
244 # first, try the hook
245 ip = get_ipython()
245 ip = get_ipython()
246 if ip:
246 if ip:
247 try:
247 try:
248 ip.hooks.show_in_pager(data, start=start, screen_lines=screen_lines)
248 ip.hooks.show_in_pager(data, start=start, screen_lines=screen_lines)
249 return
249 return
250 except TryNext:
250 except TryNext:
251 pass
251 pass
252
252
253 # fallback on default pager
253 # fallback on default pager
254 return pager_page(data, start, screen_lines, pager_cmd)
254 return pager_page(data, start, screen_lines, pager_cmd)
255
255
256
256
257 def page_file(fname, start=0, pager_cmd=None):
257 def page_file(fname, start=0, pager_cmd=None):
258 """Page a file, using an optional pager command and starting line.
258 """Page a file, using an optional pager command and starting line.
259 """
259 """
260
260
261 pager_cmd = get_pager_cmd(pager_cmd)
261 pager_cmd = get_pager_cmd(pager_cmd)
262 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
262 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
263
263
264 try:
264 try:
265 if os.environ['TERM'] in ['emacs','dumb']:
265 if os.environ['TERM'] in ['emacs','dumb']:
266 raise EnvironmentError
266 raise EnvironmentError
267 system(pager_cmd + ' ' + fname)
267 system(pager_cmd + ' ' + fname)
268 except:
268 except:
269 try:
269 try:
270 if start > 0:
270 if start > 0:
271 start -= 1
271 start -= 1
272 page(open(fname).read(),start)
272 page(open(fname).read(),start)
273 except:
273 except:
274 print('Unable to show file',repr(fname))
274 print('Unable to show file',repr(fname))
275
275
276
276
277 def get_pager_cmd(pager_cmd=None):
277 def get_pager_cmd(pager_cmd=None):
278 """Return a pager command.
278 """Return a pager command.
279
279
280 Makes some attempts at finding an OS-correct one.
280 Makes some attempts at finding an OS-correct one.
281 """
281 """
282 if os.name == 'posix':
282 if os.name == 'posix':
283 default_pager_cmd = 'less -R' # -R for color control sequences
283 default_pager_cmd = 'less -R' # -R for color control sequences
284 elif os.name in ['nt','dos']:
284 elif os.name in ['nt','dos']:
285 default_pager_cmd = 'type'
285 default_pager_cmd = 'type'
286
286
287 if pager_cmd is None:
287 if pager_cmd is None:
288 try:
288 try:
289 pager_cmd = os.environ['PAGER']
289 pager_cmd = os.environ['PAGER']
290 except:
290 except:
291 pager_cmd = default_pager_cmd
291 pager_cmd = default_pager_cmd
292
292
293 if pager_cmd == 'less' and '-r' not in os.environ.get('LESS', '').lower():
293 if pager_cmd == 'less' and '-r' not in os.environ.get('LESS', '').lower():
294 pager_cmd += ' -R'
294 pager_cmd += ' -R'
295
295
296 return pager_cmd
296 return pager_cmd
297
297
298
298
299 def get_pager_start(pager, start):
299 def get_pager_start(pager, start):
300 """Return the string for paging files with an offset.
300 """Return the string for paging files with an offset.
301
301
302 This is the '+N' argument which less and more (under Unix) accept.
302 This is the '+N' argument which less and more (under Unix) accept.
303 """
303 """
304
304
305 if pager in ['less','more']:
305 if pager in ['less','more']:
306 if start:
306 if start:
307 start_string = '+' + str(start)
307 start_string = '+' + str(start)
308 else:
308 else:
309 start_string = ''
309 start_string = ''
310 else:
310 else:
311 start_string = ''
311 start_string = ''
312 return start_string
312 return start_string
313
313
314
314
315 # (X)emacs on win32 doesn't like to be bypassed with msvcrt.getch()
315 # (X)emacs on win32 doesn't like to be bypassed with msvcrt.getch()
316 if os.name == 'nt' and os.environ.get('TERM','dumb') != 'emacs':
316 if os.name == 'nt' and os.environ.get('TERM','dumb') != 'emacs':
317 import msvcrt
317 import msvcrt
318 def page_more():
318 def page_more():
319 """ Smart pausing between pages
319 """ Smart pausing between pages
320
320
321 @return: True if need print more lines, False if quit
321 @return: True if need print more lines, False if quit
322 """
322 """
323 sys.stdout.write('---Return to continue, q to quit--- ')
323 sys.stdout.write('---Return to continue, q to quit--- ')
324 ans = msvcrt.getwch()
324 ans = msvcrt.getwch()
325 if ans in ("q", "Q"):
325 if ans in ("q", "Q"):
326 result = False
326 result = False
327 else:
327 else:
328 result = True
328 result = True
329 sys.stdout.write("\b"*37 + " "*37 + "\b"*37)
329 sys.stdout.write("\b"*37 + " "*37 + "\b"*37)
330 return result
330 return result
331 else:
331 else:
332 def page_more():
332 def page_more():
333 ans = py3compat.input('---Return to continue, q to quit--- ')
333 ans = py3compat.input('---Return to continue, q to quit--- ')
334 if ans.lower().startswith('q'):
334 if ans.lower().startswith('q'):
335 return False
335 return False
336 else:
336 else:
337 return True
337 return True
338
338
339
339
340 def snip_print(str,width = 75,print_full = 0,header = ''):
340 def snip_print(str,width = 75,print_full = 0,header = ''):
341 """Print a string snipping the midsection to fit in width.
341 """Print a string snipping the midsection to fit in width.
342
342
343 print_full: mode control:
343 print_full: mode control:
344
344
345 - 0: only snip long strings
345 - 0: only snip long strings
346 - 1: send to page() directly.
346 - 1: send to page() directly.
347 - 2: snip long strings and ask for full length viewing with page()
347 - 2: snip long strings and ask for full length viewing with page()
348
348
349 Return 1 if snipping was necessary, 0 otherwise."""
349 Return 1 if snipping was necessary, 0 otherwise."""
350
350
351 if print_full == 1:
351 if print_full == 1:
352 page(header+str)
352 page(header+str)
353 return 0
353 return 0
354
354
355 print(header, end=' ')
355 print(header, end=' ')
356 if len(str) < width:
356 if len(str) < width:
357 print(str)
357 print(str)
358 snip = 0
358 snip = 0
359 else:
359 else:
360 whalf = int((width -5)/2)
360 whalf = int((width -5)/2)
361 print(str[:whalf] + ' <...> ' + str[-whalf:])
361 print(str[:whalf] + ' <...> ' + str[-whalf:])
362 snip = 1
362 snip = 1
363 if snip and print_full == 2:
363 if snip and print_full == 2:
364 if py3compat.input(header+' Snipped. View (y/n)? [N]').lower() == 'y':
364 if py3compat.input(header+' Snipped. View (y/n)? [N]').lower() == 'y':
365 page(str)
365 page(str)
366 return snip
366 return snip
@@ -1,1473 +1,1473 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Verbose and colourful traceback formatting.
3 Verbose and colourful traceback formatting.
4
4
5 **ColorTB**
5 **ColorTB**
6
6
7 I've always found it a bit hard to visually parse tracebacks in Python. The
7 I've always found it a bit hard to visually parse tracebacks in Python. The
8 ColorTB class is a solution to that problem. It colors the different parts of a
8 ColorTB class is a solution to that problem. It colors the different parts of a
9 traceback in a manner similar to what you would expect from a syntax-highlighting
9 traceback in a manner similar to what you would expect from a syntax-highlighting
10 text editor.
10 text editor.
11
11
12 Installation instructions for ColorTB::
12 Installation instructions for ColorTB::
13
13
14 import sys,ultratb
14 import sys,ultratb
15 sys.excepthook = ultratb.ColorTB()
15 sys.excepthook = ultratb.ColorTB()
16
16
17 **VerboseTB**
17 **VerboseTB**
18
18
19 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
19 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
20 of useful info when a traceback occurs. Ping originally had it spit out HTML
20 of useful info when a traceback occurs. Ping originally had it spit out HTML
21 and intended it for CGI programmers, but why should they have all the fun? I
21 and intended it for CGI programmers, but why should they have all the fun? I
22 altered it to spit out colored text to the terminal. It's a bit overwhelming,
22 altered it to spit out colored text to the terminal. It's a bit overwhelming,
23 but kind of neat, and maybe useful for long-running programs that you believe
23 but kind of neat, and maybe useful for long-running programs that you believe
24 are bug-free. If a crash *does* occur in that type of program you want details.
24 are bug-free. If a crash *does* occur in that type of program you want details.
25 Give it a shot--you'll love it or you'll hate it.
25 Give it a shot--you'll love it or you'll hate it.
26
26
27 .. note::
27 .. note::
28
28
29 The Verbose mode prints the variables currently visible where the exception
29 The Verbose mode prints the variables currently visible where the exception
30 happened (shortening their strings if too long). This can potentially be
30 happened (shortening their strings if too long). This can potentially be
31 very slow, if you happen to have a huge data structure whose string
31 very slow, if you happen to have a huge data structure whose string
32 representation is complex to compute. Your computer may appear to freeze for
32 representation is complex to compute. Your computer may appear to freeze for
33 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
33 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
34 with Ctrl-C (maybe hitting it more than once).
34 with Ctrl-C (maybe hitting it more than once).
35
35
36 If you encounter this kind of situation often, you may want to use the
36 If you encounter this kind of situation often, you may want to use the
37 Verbose_novars mode instead of the regular Verbose, which avoids formatting
37 Verbose_novars mode instead of the regular Verbose, which avoids formatting
38 variables (but otherwise includes the information and context given by
38 variables (but otherwise includes the information and context given by
39 Verbose).
39 Verbose).
40
40
41 .. note::
41 .. note::
42
42
43 The verbose mode print all variables in the stack, which means it can
43 The verbose mode print all variables in the stack, which means it can
44 potentially leak sensitive information like access keys, or unencryted
44 potentially leak sensitive information like access keys, or unencrypted
45 password.
45 password.
46
46
47 Installation instructions for VerboseTB::
47 Installation instructions for VerboseTB::
48
48
49 import sys,ultratb
49 import sys,ultratb
50 sys.excepthook = ultratb.VerboseTB()
50 sys.excepthook = ultratb.VerboseTB()
51
51
52 Note: Much of the code in this module was lifted verbatim from the standard
52 Note: Much of the code in this module was lifted verbatim from the standard
53 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
53 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
54
54
55 Color schemes
55 Color schemes
56 -------------
56 -------------
57
57
58 The colors are defined in the class TBTools through the use of the
58 The colors are defined in the class TBTools through the use of the
59 ColorSchemeTable class. Currently the following exist:
59 ColorSchemeTable class. Currently the following exist:
60
60
61 - NoColor: allows all of this module to be used in any terminal (the color
61 - NoColor: allows all of this module to be used in any terminal (the color
62 escapes are just dummy blank strings).
62 escapes are just dummy blank strings).
63
63
64 - Linux: is meant to look good in a terminal like the Linux console (black
64 - Linux: is meant to look good in a terminal like the Linux console (black
65 or very dark background).
65 or very dark background).
66
66
67 - LightBG: similar to Linux but swaps dark/light colors to be more readable
67 - LightBG: similar to Linux but swaps dark/light colors to be more readable
68 in light background terminals.
68 in light background terminals.
69
69
70 - Neutral: a neutral color scheme that should be readable on both light and
70 - Neutral: a neutral color scheme that should be readable on both light and
71 dark background
71 dark background
72
72
73 You can implement other color schemes easily, the syntax is fairly
73 You can implement other color schemes easily, the syntax is fairly
74 self-explanatory. Please send back new schemes you develop to the author for
74 self-explanatory. Please send back new schemes you develop to the author for
75 possible inclusion in future releases.
75 possible inclusion in future releases.
76
76
77 Inheritance diagram:
77 Inheritance diagram:
78
78
79 .. inheritance-diagram:: IPython.core.ultratb
79 .. inheritance-diagram:: IPython.core.ultratb
80 :parts: 3
80 :parts: 3
81 """
81 """
82
82
83 #*****************************************************************************
83 #*****************************************************************************
84 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
84 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
85 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
85 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
86 #
86 #
87 # Distributed under the terms of the BSD License. The full license is in
87 # Distributed under the terms of the BSD License. The full license is in
88 # the file COPYING, distributed as part of this software.
88 # the file COPYING, distributed as part of this software.
89 #*****************************************************************************
89 #*****************************************************************************
90
90
91
91
92 import dis
92 import dis
93 import inspect
93 import inspect
94 import keyword
94 import keyword
95 import linecache
95 import linecache
96 import os
96 import os
97 import pydoc
97 import pydoc
98 import re
98 import re
99 import sys
99 import sys
100 import time
100 import time
101 import tokenize
101 import tokenize
102 import traceback
102 import traceback
103
103
104 try: # Python 2
104 try: # Python 2
105 generate_tokens = tokenize.generate_tokens
105 generate_tokens = tokenize.generate_tokens
106 except AttributeError: # Python 3
106 except AttributeError: # Python 3
107 generate_tokens = tokenize.tokenize
107 generate_tokens = tokenize.tokenize
108
108
109 # For purposes of monkeypatching inspect to fix a bug in it.
109 # For purposes of monkeypatching inspect to fix a bug in it.
110 from inspect import getsourcefile, getfile, getmodule, \
110 from inspect import getsourcefile, getfile, getmodule, \
111 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
111 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
112
112
113 # IPython's own modules
113 # IPython's own modules
114 from IPython import get_ipython
114 from IPython import get_ipython
115 from IPython.core import debugger
115 from IPython.core import debugger
116 from IPython.core.display_trap import DisplayTrap
116 from IPython.core.display_trap import DisplayTrap
117 from IPython.core.excolors import exception_colors
117 from IPython.core.excolors import exception_colors
118 from IPython.utils import PyColorize
118 from IPython.utils import PyColorize
119 from IPython.utils import path as util_path
119 from IPython.utils import path as util_path
120 from IPython.utils import py3compat
120 from IPython.utils import py3compat
121 from IPython.utils.data import uniq_stable
121 from IPython.utils.data import uniq_stable
122 from IPython.utils.terminal import get_terminal_size
122 from IPython.utils.terminal import get_terminal_size
123
123
124 from logging import info, error, debug
124 from logging import info, error, debug
125
125
126 from importlib.util import source_from_cache
126 from importlib.util import source_from_cache
127
127
128 import IPython.utils.colorable as colorable
128 import IPython.utils.colorable as colorable
129
129
130 # Globals
130 # Globals
131 # amount of space to put line numbers before verbose tracebacks
131 # amount of space to put line numbers before verbose tracebacks
132 INDENT_SIZE = 8
132 INDENT_SIZE = 8
133
133
134 # Default color scheme. This is used, for example, by the traceback
134 # Default color scheme. This is used, for example, by the traceback
135 # formatter. When running in an actual IPython instance, the user's rc.colors
135 # formatter. When running in an actual IPython instance, the user's rc.colors
136 # value is used, but having a module global makes this functionality available
136 # value is used, but having a module global makes this functionality available
137 # to users of ultratb who are NOT running inside ipython.
137 # to users of ultratb who are NOT running inside ipython.
138 DEFAULT_SCHEME = 'NoColor'
138 DEFAULT_SCHEME = 'NoColor'
139
139
140
140
141 # Number of frame above which we are likely to have a recursion and will
141 # Number of frame above which we are likely to have a recursion and will
142 # **attempt** to detect it. Made modifiable mostly to speedup test suite
142 # **attempt** to detect it. Made modifiable mostly to speedup test suite
143 # as detecting recursion is one of our slowest test
143 # as detecting recursion is one of our slowest test
144 _FRAME_RECURSION_LIMIT = 500
144 _FRAME_RECURSION_LIMIT = 500
145
145
146 # ---------------------------------------------------------------------------
146 # ---------------------------------------------------------------------------
147 # Code begins
147 # Code begins
148
148
149 # Utility functions
149 # Utility functions
150 def inspect_error():
150 def inspect_error():
151 """Print a message about internal inspect errors.
151 """Print a message about internal inspect errors.
152
152
153 These are unfortunately quite common."""
153 These are unfortunately quite common."""
154
154
155 error('Internal Python error in the inspect module.\n'
155 error('Internal Python error in the inspect module.\n'
156 'Below is the traceback from this internal error.\n')
156 'Below is the traceback from this internal error.\n')
157
157
158
158
159 # This function is a monkeypatch we apply to the Python inspect module. We have
159 # This function is a monkeypatch we apply to the Python inspect module. We have
160 # now found when it's needed (see discussion on issue gh-1456), and we have a
160 # now found when it's needed (see discussion on issue gh-1456), and we have a
161 # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
161 # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
162 # the monkeypatch is not applied. TK, Aug 2012.
162 # the monkeypatch is not applied. TK, Aug 2012.
163 def findsource(object):
163 def findsource(object):
164 """Return the entire source file and starting line number for an object.
164 """Return the entire source file and starting line number for an object.
165
165
166 The argument may be a module, class, method, function, traceback, frame,
166 The argument may be a module, class, method, function, traceback, frame,
167 or code object. The source code is returned as a list of all the lines
167 or code object. The source code is returned as a list of all the lines
168 in the file and the line number indexes a line in that list. An IOError
168 in the file and the line number indexes a line in that list. An IOError
169 is raised if the source code cannot be retrieved.
169 is raised if the source code cannot be retrieved.
170
170
171 FIXED version with which we monkeypatch the stdlib to work around a bug."""
171 FIXED version with which we monkeypatch the stdlib to work around a bug."""
172
172
173 file = getsourcefile(object) or getfile(object)
173 file = getsourcefile(object) or getfile(object)
174 # If the object is a frame, then trying to get the globals dict from its
174 # If the object is a frame, then trying to get the globals dict from its
175 # module won't work. Instead, the frame object itself has the globals
175 # module won't work. Instead, the frame object itself has the globals
176 # dictionary.
176 # dictionary.
177 globals_dict = None
177 globals_dict = None
178 if inspect.isframe(object):
178 if inspect.isframe(object):
179 # XXX: can this ever be false?
179 # XXX: can this ever be false?
180 globals_dict = object.f_globals
180 globals_dict = object.f_globals
181 else:
181 else:
182 module = getmodule(object, file)
182 module = getmodule(object, file)
183 if module:
183 if module:
184 globals_dict = module.__dict__
184 globals_dict = module.__dict__
185 lines = linecache.getlines(file, globals_dict)
185 lines = linecache.getlines(file, globals_dict)
186 if not lines:
186 if not lines:
187 raise IOError('could not get source code')
187 raise IOError('could not get source code')
188
188
189 if ismodule(object):
189 if ismodule(object):
190 return lines, 0
190 return lines, 0
191
191
192 if isclass(object):
192 if isclass(object):
193 name = object.__name__
193 name = object.__name__
194 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
194 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
195 # make some effort to find the best matching class definition:
195 # make some effort to find the best matching class definition:
196 # use the one with the least indentation, which is the one
196 # use the one with the least indentation, which is the one
197 # that's most probably not inside a function definition.
197 # that's most probably not inside a function definition.
198 candidates = []
198 candidates = []
199 for i, line in enumerate(lines):
199 for i, line in enumerate(lines):
200 match = pat.match(line)
200 match = pat.match(line)
201 if match:
201 if match:
202 # if it's at toplevel, it's already the best one
202 # if it's at toplevel, it's already the best one
203 if line[0] == 'c':
203 if line[0] == 'c':
204 return lines, i
204 return lines, i
205 # else add whitespace to candidate list
205 # else add whitespace to candidate list
206 candidates.append((match.group(1), i))
206 candidates.append((match.group(1), i))
207 if candidates:
207 if candidates:
208 # this will sort by whitespace, and by line number,
208 # this will sort by whitespace, and by line number,
209 # less whitespace first
209 # less whitespace first
210 candidates.sort()
210 candidates.sort()
211 return lines, candidates[0][1]
211 return lines, candidates[0][1]
212 else:
212 else:
213 raise IOError('could not find class definition')
213 raise IOError('could not find class definition')
214
214
215 if ismethod(object):
215 if ismethod(object):
216 object = object.__func__
216 object = object.__func__
217 if isfunction(object):
217 if isfunction(object):
218 object = object.__code__
218 object = object.__code__
219 if istraceback(object):
219 if istraceback(object):
220 object = object.tb_frame
220 object = object.tb_frame
221 if isframe(object):
221 if isframe(object):
222 object = object.f_code
222 object = object.f_code
223 if iscode(object):
223 if iscode(object):
224 if not hasattr(object, 'co_firstlineno'):
224 if not hasattr(object, 'co_firstlineno'):
225 raise IOError('could not find function definition')
225 raise IOError('could not find function definition')
226 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
226 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
227 pmatch = pat.match
227 pmatch = pat.match
228 # fperez - fix: sometimes, co_firstlineno can give a number larger than
228 # fperez - fix: sometimes, co_firstlineno can give a number larger than
229 # the length of lines, which causes an error. Safeguard against that.
229 # the length of lines, which causes an error. Safeguard against that.
230 lnum = min(object.co_firstlineno, len(lines)) - 1
230 lnum = min(object.co_firstlineno, len(lines)) - 1
231 while lnum > 0:
231 while lnum > 0:
232 if pmatch(lines[lnum]):
232 if pmatch(lines[lnum]):
233 break
233 break
234 lnum -= 1
234 lnum -= 1
235
235
236 return lines, lnum
236 return lines, lnum
237 raise IOError('could not find code object')
237 raise IOError('could not find code object')
238
238
239
239
240 # This is a patched version of inspect.getargs that applies the (unmerged)
240 # This is a patched version of inspect.getargs that applies the (unmerged)
241 # patch for http://bugs.python.org/issue14611 by Stefano Taschini. This fixes
241 # patch for http://bugs.python.org/issue14611 by Stefano Taschini. This fixes
242 # https://github.com/ipython/ipython/issues/8205 and
242 # https://github.com/ipython/ipython/issues/8205 and
243 # https://github.com/ipython/ipython/issues/8293
243 # https://github.com/ipython/ipython/issues/8293
244 def getargs(co):
244 def getargs(co):
245 """Get information about the arguments accepted by a code object.
245 """Get information about the arguments accepted by a code object.
246
246
247 Three things are returned: (args, varargs, varkw), where 'args' is
247 Three things are returned: (args, varargs, varkw), where 'args' is
248 a list of argument names (possibly containing nested lists), and
248 a list of argument names (possibly containing nested lists), and
249 'varargs' and 'varkw' are the names of the * and ** arguments or None."""
249 'varargs' and 'varkw' are the names of the * and ** arguments or None."""
250 if not iscode(co):
250 if not iscode(co):
251 raise TypeError('{!r} is not a code object'.format(co))
251 raise TypeError('{!r} is not a code object'.format(co))
252
252
253 nargs = co.co_argcount
253 nargs = co.co_argcount
254 names = co.co_varnames
254 names = co.co_varnames
255 args = list(names[:nargs])
255 args = list(names[:nargs])
256 step = 0
256 step = 0
257
257
258 # The following acrobatics are for anonymous (tuple) arguments.
258 # The following acrobatics are for anonymous (tuple) arguments.
259 for i in range(nargs):
259 for i in range(nargs):
260 if args[i][:1] in ('', '.'):
260 if args[i][:1] in ('', '.'):
261 stack, remain, count = [], [], []
261 stack, remain, count = [], [], []
262 while step < len(co.co_code):
262 while step < len(co.co_code):
263 op = ord(co.co_code[step])
263 op = ord(co.co_code[step])
264 step = step + 1
264 step = step + 1
265 if op >= dis.HAVE_ARGUMENT:
265 if op >= dis.HAVE_ARGUMENT:
266 opname = dis.opname[op]
266 opname = dis.opname[op]
267 value = ord(co.co_code[step]) + ord(co.co_code[step+1])*256
267 value = ord(co.co_code[step]) + ord(co.co_code[step+1])*256
268 step = step + 2
268 step = step + 2
269 if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'):
269 if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'):
270 remain.append(value)
270 remain.append(value)
271 count.append(value)
271 count.append(value)
272 elif opname in ('STORE_FAST', 'STORE_DEREF'):
272 elif opname in ('STORE_FAST', 'STORE_DEREF'):
273 if op in dis.haslocal:
273 if op in dis.haslocal:
274 stack.append(co.co_varnames[value])
274 stack.append(co.co_varnames[value])
275 elif op in dis.hasfree:
275 elif op in dis.hasfree:
276 stack.append((co.co_cellvars + co.co_freevars)[value])
276 stack.append((co.co_cellvars + co.co_freevars)[value])
277 # Special case for sublists of length 1: def foo((bar))
277 # Special case for sublists of length 1: def foo((bar))
278 # doesn't generate the UNPACK_TUPLE bytecode, so if
278 # doesn't generate the UNPACK_TUPLE bytecode, so if
279 # `remain` is empty here, we have such a sublist.
279 # `remain` is empty here, we have such a sublist.
280 if not remain:
280 if not remain:
281 stack[0] = [stack[0]]
281 stack[0] = [stack[0]]
282 break
282 break
283 else:
283 else:
284 remain[-1] = remain[-1] - 1
284 remain[-1] = remain[-1] - 1
285 while remain[-1] == 0:
285 while remain[-1] == 0:
286 remain.pop()
286 remain.pop()
287 size = count.pop()
287 size = count.pop()
288 stack[-size:] = [stack[-size:]]
288 stack[-size:] = [stack[-size:]]
289 if not remain:
289 if not remain:
290 break
290 break
291 remain[-1] = remain[-1] - 1
291 remain[-1] = remain[-1] - 1
292 if not remain:
292 if not remain:
293 break
293 break
294 args[i] = stack[0]
294 args[i] = stack[0]
295
295
296 varargs = None
296 varargs = None
297 if co.co_flags & inspect.CO_VARARGS:
297 if co.co_flags & inspect.CO_VARARGS:
298 varargs = co.co_varnames[nargs]
298 varargs = co.co_varnames[nargs]
299 nargs = nargs + 1
299 nargs = nargs + 1
300 varkw = None
300 varkw = None
301 if co.co_flags & inspect.CO_VARKEYWORDS:
301 if co.co_flags & inspect.CO_VARKEYWORDS:
302 varkw = co.co_varnames[nargs]
302 varkw = co.co_varnames[nargs]
303 return inspect.Arguments(args, varargs, varkw)
303 return inspect.Arguments(args, varargs, varkw)
304
304
305
305
306 # Monkeypatch inspect to apply our bugfix.
306 # Monkeypatch inspect to apply our bugfix.
307 def with_patch_inspect(f):
307 def with_patch_inspect(f):
308 """
308 """
309 Deprecated since IPython 6.0
309 Deprecated since IPython 6.0
310 decorator for monkeypatching inspect.findsource
310 decorator for monkeypatching inspect.findsource
311 """
311 """
312
312
313 def wrapped(*args, **kwargs):
313 def wrapped(*args, **kwargs):
314 save_findsource = inspect.findsource
314 save_findsource = inspect.findsource
315 save_getargs = inspect.getargs
315 save_getargs = inspect.getargs
316 inspect.findsource = findsource
316 inspect.findsource = findsource
317 inspect.getargs = getargs
317 inspect.getargs = getargs
318 try:
318 try:
319 return f(*args, **kwargs)
319 return f(*args, **kwargs)
320 finally:
320 finally:
321 inspect.findsource = save_findsource
321 inspect.findsource = save_findsource
322 inspect.getargs = save_getargs
322 inspect.getargs = save_getargs
323
323
324 return wrapped
324 return wrapped
325
325
326
326
327 def fix_frame_records_filenames(records):
327 def fix_frame_records_filenames(records):
328 """Try to fix the filenames in each record from inspect.getinnerframes().
328 """Try to fix the filenames in each record from inspect.getinnerframes().
329
329
330 Particularly, modules loaded from within zip files have useless filenames
330 Particularly, modules loaded from within zip files have useless filenames
331 attached to their code object, and inspect.getinnerframes() just uses it.
331 attached to their code object, and inspect.getinnerframes() just uses it.
332 """
332 """
333 fixed_records = []
333 fixed_records = []
334 for frame, filename, line_no, func_name, lines, index in records:
334 for frame, filename, line_no, func_name, lines, index in records:
335 # Look inside the frame's globals dictionary for __file__,
335 # Look inside the frame's globals dictionary for __file__,
336 # which should be better. However, keep Cython filenames since
336 # which should be better. However, keep Cython filenames since
337 # we prefer the source filenames over the compiled .so file.
337 # we prefer the source filenames over the compiled .so file.
338 if not filename.endswith(('.pyx', '.pxd', '.pxi')):
338 if not filename.endswith(('.pyx', '.pxd', '.pxi')):
339 better_fn = frame.f_globals.get('__file__', None)
339 better_fn = frame.f_globals.get('__file__', None)
340 if isinstance(better_fn, str):
340 if isinstance(better_fn, str):
341 # Check the type just in case someone did something weird with
341 # Check the type just in case someone did something weird with
342 # __file__. It might also be None if the error occurred during
342 # __file__. It might also be None if the error occurred during
343 # import.
343 # import.
344 filename = better_fn
344 filename = better_fn
345 fixed_records.append((frame, filename, line_no, func_name, lines, index))
345 fixed_records.append((frame, filename, line_no, func_name, lines, index))
346 return fixed_records
346 return fixed_records
347
347
348
348
349 @with_patch_inspect
349 @with_patch_inspect
350 def _fixed_getinnerframes(etb, context=1, tb_offset=0):
350 def _fixed_getinnerframes(etb, context=1, tb_offset=0):
351 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
351 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
352
352
353 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
353 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
354 # If the error is at the console, don't build any context, since it would
354 # If the error is at the console, don't build any context, since it would
355 # otherwise produce 5 blank lines printed out (there is no file at the
355 # otherwise produce 5 blank lines printed out (there is no file at the
356 # console)
356 # console)
357 rec_check = records[tb_offset:]
357 rec_check = records[tb_offset:]
358 try:
358 try:
359 rname = rec_check[0][1]
359 rname = rec_check[0][1]
360 if rname == '<ipython console>' or rname.endswith('<string>'):
360 if rname == '<ipython console>' or rname.endswith('<string>'):
361 return rec_check
361 return rec_check
362 except IndexError:
362 except IndexError:
363 pass
363 pass
364
364
365 aux = traceback.extract_tb(etb)
365 aux = traceback.extract_tb(etb)
366 assert len(records) == len(aux)
366 assert len(records) == len(aux)
367 for i, (file, lnum, _, _) in enumerate(aux):
367 for i, (file, lnum, _, _) in enumerate(aux):
368 maybeStart = lnum - 1 - context // 2
368 maybeStart = lnum - 1 - context // 2
369 start = max(maybeStart, 0)
369 start = max(maybeStart, 0)
370 end = start + context
370 end = start + context
371 lines = linecache.getlines(file)[start:end]
371 lines = linecache.getlines(file)[start:end]
372 buf = list(records[i])
372 buf = list(records[i])
373 buf[LNUM_POS] = lnum
373 buf[LNUM_POS] = lnum
374 buf[INDEX_POS] = lnum - 1 - start
374 buf[INDEX_POS] = lnum - 1 - start
375 buf[LINES_POS] = lines
375 buf[LINES_POS] = lines
376 records[i] = tuple(buf)
376 records[i] = tuple(buf)
377 return records[tb_offset:]
377 return records[tb_offset:]
378
378
379 # Helper function -- largely belongs to VerboseTB, but we need the same
379 # Helper function -- largely belongs to VerboseTB, but we need the same
380 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
380 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
381 # can be recognized properly by ipython.el's py-traceback-line-re
381 # can be recognized properly by ipython.el's py-traceback-line-re
382 # (SyntaxErrors have to be treated specially because they have no traceback)
382 # (SyntaxErrors have to be treated specially because they have no traceback)
383
383
384
384
385 def _format_traceback_lines(lnum, index, lines, Colors, lvals, _line_format):
385 def _format_traceback_lines(lnum, index, lines, Colors, lvals, _line_format):
386 """
386 """
387 Format tracebacks lines with pointing arrow, leading numbers...
387 Format tracebacks lines with pointing arrow, leading numbers...
388
388
389 Parameters
389 Parameters
390 ==========
390 ==========
391
391
392 lnum: int
392 lnum: int
393 index: int
393 index: int
394 lines: list[string]
394 lines: list[string]
395 Colors:
395 Colors:
396 ColorScheme used.
396 ColorScheme used.
397 lvals: bytes
397 lvals: bytes
398 Values of local variables, already colored, to inject just after the error line.
398 Values of local variables, already colored, to inject just after the error line.
399 _line_format: f (str) -> (str, bool)
399 _line_format: f (str) -> (str, bool)
400 return (colorized version of str, failure to do so)
400 return (colorized version of str, failure to do so)
401 """
401 """
402 numbers_width = INDENT_SIZE - 1
402 numbers_width = INDENT_SIZE - 1
403 res = []
403 res = []
404
404
405 for i,line in enumerate(lines, lnum-index):
405 for i,line in enumerate(lines, lnum-index):
406 line = py3compat.cast_unicode(line)
406 line = py3compat.cast_unicode(line)
407
407
408 new_line, err = _line_format(line, 'str')
408 new_line, err = _line_format(line, 'str')
409 if not err:
409 if not err:
410 line = new_line
410 line = new_line
411
411
412 if i == lnum:
412 if i == lnum:
413 # This is the line with the error
413 # This is the line with the error
414 pad = numbers_width - len(str(i))
414 pad = numbers_width - len(str(i))
415 num = '%s%s' % (debugger.make_arrow(pad), str(lnum))
415 num = '%s%s' % (debugger.make_arrow(pad), str(lnum))
416 line = '%s%s%s %s%s' % (Colors.linenoEm, num,
416 line = '%s%s%s %s%s' % (Colors.linenoEm, num,
417 Colors.line, line, Colors.Normal)
417 Colors.line, line, Colors.Normal)
418 else:
418 else:
419 num = '%*s' % (numbers_width, i)
419 num = '%*s' % (numbers_width, i)
420 line = '%s%s%s %s' % (Colors.lineno, num,
420 line = '%s%s%s %s' % (Colors.lineno, num,
421 Colors.Normal, line)
421 Colors.Normal, line)
422
422
423 res.append(line)
423 res.append(line)
424 if lvals and i == lnum:
424 if lvals and i == lnum:
425 res.append(lvals + '\n')
425 res.append(lvals + '\n')
426 return res
426 return res
427
427
428 def is_recursion_error(etype, value, records):
428 def is_recursion_error(etype, value, records):
429 try:
429 try:
430 # RecursionError is new in Python 3.5
430 # RecursionError is new in Python 3.5
431 recursion_error_type = RecursionError
431 recursion_error_type = RecursionError
432 except NameError:
432 except NameError:
433 recursion_error_type = RuntimeError
433 recursion_error_type = RuntimeError
434
434
435 # The default recursion limit is 1000, but some of that will be taken up
435 # The default recursion limit is 1000, but some of that will be taken up
436 # by stack frames in IPython itself. >500 frames probably indicates
436 # by stack frames in IPython itself. >500 frames probably indicates
437 # a recursion error.
437 # a recursion error.
438 return (etype is recursion_error_type) \
438 return (etype is recursion_error_type) \
439 and "recursion" in str(value).lower() \
439 and "recursion" in str(value).lower() \
440 and len(records) > _FRAME_RECURSION_LIMIT
440 and len(records) > _FRAME_RECURSION_LIMIT
441
441
442 def find_recursion(etype, value, records):
442 def find_recursion(etype, value, records):
443 """Identify the repeating stack frames from a RecursionError traceback
443 """Identify the repeating stack frames from a RecursionError traceback
444
444
445 'records' is a list as returned by VerboseTB.get_records()
445 'records' is a list as returned by VerboseTB.get_records()
446
446
447 Returns (last_unique, repeat_length)
447 Returns (last_unique, repeat_length)
448 """
448 """
449 # This involves a bit of guesswork - we want to show enough of the traceback
449 # This involves a bit of guesswork - we want to show enough of the traceback
450 # to indicate where the recursion is occurring. We guess that the innermost
450 # to indicate where the recursion is occurring. We guess that the innermost
451 # quarter of the traceback (250 frames by default) is repeats, and find the
451 # quarter of the traceback (250 frames by default) is repeats, and find the
452 # first frame (from in to out) that looks different.
452 # first frame (from in to out) that looks different.
453 if not is_recursion_error(etype, value, records):
453 if not is_recursion_error(etype, value, records):
454 return len(records), 0
454 return len(records), 0
455
455
456 # Select filename, lineno, func_name to track frames with
456 # Select filename, lineno, func_name to track frames with
457 records = [r[1:4] for r in records]
457 records = [r[1:4] for r in records]
458 inner_frames = records[-(len(records)//4):]
458 inner_frames = records[-(len(records)//4):]
459 frames_repeated = set(inner_frames)
459 frames_repeated = set(inner_frames)
460
460
461 last_seen_at = {}
461 last_seen_at = {}
462 longest_repeat = 0
462 longest_repeat = 0
463 i = len(records)
463 i = len(records)
464 for frame in reversed(records):
464 for frame in reversed(records):
465 i -= 1
465 i -= 1
466 if frame not in frames_repeated:
466 if frame not in frames_repeated:
467 last_unique = i
467 last_unique = i
468 break
468 break
469
469
470 if frame in last_seen_at:
470 if frame in last_seen_at:
471 distance = last_seen_at[frame] - i
471 distance = last_seen_at[frame] - i
472 longest_repeat = max(longest_repeat, distance)
472 longest_repeat = max(longest_repeat, distance)
473
473
474 last_seen_at[frame] = i
474 last_seen_at[frame] = i
475 else:
475 else:
476 last_unique = 0 # The whole traceback was recursion
476 last_unique = 0 # The whole traceback was recursion
477
477
478 return last_unique, longest_repeat
478 return last_unique, longest_repeat
479
479
480 #---------------------------------------------------------------------------
480 #---------------------------------------------------------------------------
481 # Module classes
481 # Module classes
482 class TBTools(colorable.Colorable):
482 class TBTools(colorable.Colorable):
483 """Basic tools used by all traceback printer classes."""
483 """Basic tools used by all traceback printer classes."""
484
484
485 # Number of frames to skip when reporting tracebacks
485 # Number of frames to skip when reporting tracebacks
486 tb_offset = 0
486 tb_offset = 0
487
487
488 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
488 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
489 # Whether to call the interactive pdb debugger after printing
489 # Whether to call the interactive pdb debugger after printing
490 # tracebacks or not
490 # tracebacks or not
491 super(TBTools, self).__init__(parent=parent, config=config)
491 super(TBTools, self).__init__(parent=parent, config=config)
492 self.call_pdb = call_pdb
492 self.call_pdb = call_pdb
493
493
494 # Output stream to write to. Note that we store the original value in
494 # Output stream to write to. Note that we store the original value in
495 # a private attribute and then make the public ostream a property, so
495 # a private attribute and then make the public ostream a property, so
496 # that we can delay accessing sys.stdout until runtime. The way
496 # that we can delay accessing sys.stdout until runtime. The way
497 # things are written now, the sys.stdout object is dynamically managed
497 # things are written now, the sys.stdout object is dynamically managed
498 # so a reference to it should NEVER be stored statically. This
498 # so a reference to it should NEVER be stored statically. This
499 # property approach confines this detail to a single location, and all
499 # property approach confines this detail to a single location, and all
500 # subclasses can simply access self.ostream for writing.
500 # subclasses can simply access self.ostream for writing.
501 self._ostream = ostream
501 self._ostream = ostream
502
502
503 # Create color table
503 # Create color table
504 self.color_scheme_table = exception_colors()
504 self.color_scheme_table = exception_colors()
505
505
506 self.set_colors(color_scheme)
506 self.set_colors(color_scheme)
507 self.old_scheme = color_scheme # save initial value for toggles
507 self.old_scheme = color_scheme # save initial value for toggles
508
508
509 if call_pdb:
509 if call_pdb:
510 self.pdb = debugger.Pdb()
510 self.pdb = debugger.Pdb()
511 else:
511 else:
512 self.pdb = None
512 self.pdb = None
513
513
514 def _get_ostream(self):
514 def _get_ostream(self):
515 """Output stream that exceptions are written to.
515 """Output stream that exceptions are written to.
516
516
517 Valid values are:
517 Valid values are:
518
518
519 - None: the default, which means that IPython will dynamically resolve
519 - None: the default, which means that IPython will dynamically resolve
520 to sys.stdout. This ensures compatibility with most tools, including
520 to sys.stdout. This ensures compatibility with most tools, including
521 Windows (where plain stdout doesn't recognize ANSI escapes).
521 Windows (where plain stdout doesn't recognize ANSI escapes).
522
522
523 - Any object with 'write' and 'flush' attributes.
523 - Any object with 'write' and 'flush' attributes.
524 """
524 """
525 return sys.stdout if self._ostream is None else self._ostream
525 return sys.stdout if self._ostream is None else self._ostream
526
526
527 def _set_ostream(self, val):
527 def _set_ostream(self, val):
528 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
528 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
529 self._ostream = val
529 self._ostream = val
530
530
531 ostream = property(_get_ostream, _set_ostream)
531 ostream = property(_get_ostream, _set_ostream)
532
532
533 def set_colors(self, *args, **kw):
533 def set_colors(self, *args, **kw):
534 """Shorthand access to the color table scheme selector method."""
534 """Shorthand access to the color table scheme selector method."""
535
535
536 # Set own color table
536 # Set own color table
537 self.color_scheme_table.set_active_scheme(*args, **kw)
537 self.color_scheme_table.set_active_scheme(*args, **kw)
538 # for convenience, set Colors to the active scheme
538 # for convenience, set Colors to the active scheme
539 self.Colors = self.color_scheme_table.active_colors
539 self.Colors = self.color_scheme_table.active_colors
540 # Also set colors of debugger
540 # Also set colors of debugger
541 if hasattr(self, 'pdb') and self.pdb is not None:
541 if hasattr(self, 'pdb') and self.pdb is not None:
542 self.pdb.set_colors(*args, **kw)
542 self.pdb.set_colors(*args, **kw)
543
543
544 def color_toggle(self):
544 def color_toggle(self):
545 """Toggle between the currently active color scheme and NoColor."""
545 """Toggle between the currently active color scheme and NoColor."""
546
546
547 if self.color_scheme_table.active_scheme_name == 'NoColor':
547 if self.color_scheme_table.active_scheme_name == 'NoColor':
548 self.color_scheme_table.set_active_scheme(self.old_scheme)
548 self.color_scheme_table.set_active_scheme(self.old_scheme)
549 self.Colors = self.color_scheme_table.active_colors
549 self.Colors = self.color_scheme_table.active_colors
550 else:
550 else:
551 self.old_scheme = self.color_scheme_table.active_scheme_name
551 self.old_scheme = self.color_scheme_table.active_scheme_name
552 self.color_scheme_table.set_active_scheme('NoColor')
552 self.color_scheme_table.set_active_scheme('NoColor')
553 self.Colors = self.color_scheme_table.active_colors
553 self.Colors = self.color_scheme_table.active_colors
554
554
555 def stb2text(self, stb):
555 def stb2text(self, stb):
556 """Convert a structured traceback (a list) to a string."""
556 """Convert a structured traceback (a list) to a string."""
557 return '\n'.join(stb)
557 return '\n'.join(stb)
558
558
559 def text(self, etype, value, tb, tb_offset=None, context=5):
559 def text(self, etype, value, tb, tb_offset=None, context=5):
560 """Return formatted traceback.
560 """Return formatted traceback.
561
561
562 Subclasses may override this if they add extra arguments.
562 Subclasses may override this if they add extra arguments.
563 """
563 """
564 tb_list = self.structured_traceback(etype, value, tb,
564 tb_list = self.structured_traceback(etype, value, tb,
565 tb_offset, context)
565 tb_offset, context)
566 return self.stb2text(tb_list)
566 return self.stb2text(tb_list)
567
567
568 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
568 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
569 context=5, mode=None):
569 context=5, mode=None):
570 """Return a list of traceback frames.
570 """Return a list of traceback frames.
571
571
572 Must be implemented by each class.
572 Must be implemented by each class.
573 """
573 """
574 raise NotImplementedError()
574 raise NotImplementedError()
575
575
576
576
577 #---------------------------------------------------------------------------
577 #---------------------------------------------------------------------------
578 class ListTB(TBTools):
578 class ListTB(TBTools):
579 """Print traceback information from a traceback list, with optional color.
579 """Print traceback information from a traceback list, with optional color.
580
580
581 Calling requires 3 arguments: (etype, evalue, elist)
581 Calling requires 3 arguments: (etype, evalue, elist)
582 as would be obtained by::
582 as would be obtained by::
583
583
584 etype, evalue, tb = sys.exc_info()
584 etype, evalue, tb = sys.exc_info()
585 if tb:
585 if tb:
586 elist = traceback.extract_tb(tb)
586 elist = traceback.extract_tb(tb)
587 else:
587 else:
588 elist = None
588 elist = None
589
589
590 It can thus be used by programs which need to process the traceback before
590 It can thus be used by programs which need to process the traceback before
591 printing (such as console replacements based on the code module from the
591 printing (such as console replacements based on the code module from the
592 standard library).
592 standard library).
593
593
594 Because they are meant to be called without a full traceback (only a
594 Because they are meant to be called without a full traceback (only a
595 list), instances of this class can't call the interactive pdb debugger."""
595 list), instances of this class can't call the interactive pdb debugger."""
596
596
597 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
597 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
598 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
598 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
599 ostream=ostream, parent=parent,config=config)
599 ostream=ostream, parent=parent,config=config)
600
600
601 def __call__(self, etype, value, elist):
601 def __call__(self, etype, value, elist):
602 self.ostream.flush()
602 self.ostream.flush()
603 self.ostream.write(self.text(etype, value, elist))
603 self.ostream.write(self.text(etype, value, elist))
604 self.ostream.write('\n')
604 self.ostream.write('\n')
605
605
606 def structured_traceback(self, etype, value, elist, tb_offset=None,
606 def structured_traceback(self, etype, value, elist, tb_offset=None,
607 context=5):
607 context=5):
608 """Return a color formatted string with the traceback info.
608 """Return a color formatted string with the traceback info.
609
609
610 Parameters
610 Parameters
611 ----------
611 ----------
612 etype : exception type
612 etype : exception type
613 Type of the exception raised.
613 Type of the exception raised.
614
614
615 value : object
615 value : object
616 Data stored in the exception
616 Data stored in the exception
617
617
618 elist : list
618 elist : list
619 List of frames, see class docstring for details.
619 List of frames, see class docstring for details.
620
620
621 tb_offset : int, optional
621 tb_offset : int, optional
622 Number of frames in the traceback to skip. If not given, the
622 Number of frames in the traceback to skip. If not given, the
623 instance value is used (set in constructor).
623 instance value is used (set in constructor).
624
624
625 context : int, optional
625 context : int, optional
626 Number of lines of context information to print.
626 Number of lines of context information to print.
627
627
628 Returns
628 Returns
629 -------
629 -------
630 String with formatted exception.
630 String with formatted exception.
631 """
631 """
632 tb_offset = self.tb_offset if tb_offset is None else tb_offset
632 tb_offset = self.tb_offset if tb_offset is None else tb_offset
633 Colors = self.Colors
633 Colors = self.Colors
634 out_list = []
634 out_list = []
635 if elist:
635 if elist:
636
636
637 if tb_offset and len(elist) > tb_offset:
637 if tb_offset and len(elist) > tb_offset:
638 elist = elist[tb_offset:]
638 elist = elist[tb_offset:]
639
639
640 out_list.append('Traceback %s(most recent call last)%s:' %
640 out_list.append('Traceback %s(most recent call last)%s:' %
641 (Colors.normalEm, Colors.Normal) + '\n')
641 (Colors.normalEm, Colors.Normal) + '\n')
642 out_list.extend(self._format_list(elist))
642 out_list.extend(self._format_list(elist))
643 # The exception info should be a single entry in the list.
643 # The exception info should be a single entry in the list.
644 lines = ''.join(self._format_exception_only(etype, value))
644 lines = ''.join(self._format_exception_only(etype, value))
645 out_list.append(lines)
645 out_list.append(lines)
646
646
647 return out_list
647 return out_list
648
648
649 def _format_list(self, extracted_list):
649 def _format_list(self, extracted_list):
650 """Format a list of traceback entry tuples for printing.
650 """Format a list of traceback entry tuples for printing.
651
651
652 Given a list of tuples as returned by extract_tb() or
652 Given a list of tuples as returned by extract_tb() or
653 extract_stack(), return a list of strings ready for printing.
653 extract_stack(), return a list of strings ready for printing.
654 Each string in the resulting list corresponds to the item with the
654 Each string in the resulting list corresponds to the item with the
655 same index in the argument list. Each string ends in a newline;
655 same index in the argument list. Each string ends in a newline;
656 the strings may contain internal newlines as well, for those items
656 the strings may contain internal newlines as well, for those items
657 whose source text line is not None.
657 whose source text line is not None.
658
658
659 Lifted almost verbatim from traceback.py
659 Lifted almost verbatim from traceback.py
660 """
660 """
661
661
662 Colors = self.Colors
662 Colors = self.Colors
663 list = []
663 list = []
664 for filename, lineno, name, line in extracted_list[:-1]:
664 for filename, lineno, name, line in extracted_list[:-1]:
665 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
665 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
666 (Colors.filename, filename, Colors.Normal,
666 (Colors.filename, filename, Colors.Normal,
667 Colors.lineno, lineno, Colors.Normal,
667 Colors.lineno, lineno, Colors.Normal,
668 Colors.name, name, Colors.Normal)
668 Colors.name, name, Colors.Normal)
669 if line:
669 if line:
670 item += ' %s\n' % line.strip()
670 item += ' %s\n' % line.strip()
671 list.append(item)
671 list.append(item)
672 # Emphasize the last entry
672 # Emphasize the last entry
673 filename, lineno, name, line = extracted_list[-1]
673 filename, lineno, name, line = extracted_list[-1]
674 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
674 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
675 (Colors.normalEm,
675 (Colors.normalEm,
676 Colors.filenameEm, filename, Colors.normalEm,
676 Colors.filenameEm, filename, Colors.normalEm,
677 Colors.linenoEm, lineno, Colors.normalEm,
677 Colors.linenoEm, lineno, Colors.normalEm,
678 Colors.nameEm, name, Colors.normalEm,
678 Colors.nameEm, name, Colors.normalEm,
679 Colors.Normal)
679 Colors.Normal)
680 if line:
680 if line:
681 item += '%s %s%s\n' % (Colors.line, line.strip(),
681 item += '%s %s%s\n' % (Colors.line, line.strip(),
682 Colors.Normal)
682 Colors.Normal)
683 list.append(item)
683 list.append(item)
684 return list
684 return list
685
685
686 def _format_exception_only(self, etype, value):
686 def _format_exception_only(self, etype, value):
687 """Format the exception part of a traceback.
687 """Format the exception part of a traceback.
688
688
689 The arguments are the exception type and value such as given by
689 The arguments are the exception type and value such as given by
690 sys.exc_info()[:2]. The return value is a list of strings, each ending
690 sys.exc_info()[:2]. The return value is a list of strings, each ending
691 in a newline. Normally, the list contains a single string; however,
691 in a newline. Normally, the list contains a single string; however,
692 for SyntaxError exceptions, it contains several lines that (when
692 for SyntaxError exceptions, it contains several lines that (when
693 printed) display detailed information about where the syntax error
693 printed) display detailed information about where the syntax error
694 occurred. The message indicating which exception occurred is the
694 occurred. The message indicating which exception occurred is the
695 always last string in the list.
695 always last string in the list.
696
696
697 Also lifted nearly verbatim from traceback.py
697 Also lifted nearly verbatim from traceback.py
698 """
698 """
699 have_filedata = False
699 have_filedata = False
700 Colors = self.Colors
700 Colors = self.Colors
701 list = []
701 list = []
702 stype = py3compat.cast_unicode(Colors.excName + etype.__name__ + Colors.Normal)
702 stype = py3compat.cast_unicode(Colors.excName + etype.__name__ + Colors.Normal)
703 if value is None:
703 if value is None:
704 # Not sure if this can still happen in Python 2.6 and above
704 # Not sure if this can still happen in Python 2.6 and above
705 list.append(stype + '\n')
705 list.append(stype + '\n')
706 else:
706 else:
707 if issubclass(etype, SyntaxError):
707 if issubclass(etype, SyntaxError):
708 have_filedata = True
708 have_filedata = True
709 if not value.filename: value.filename = "<string>"
709 if not value.filename: value.filename = "<string>"
710 if value.lineno:
710 if value.lineno:
711 lineno = value.lineno
711 lineno = value.lineno
712 textline = linecache.getline(value.filename, value.lineno)
712 textline = linecache.getline(value.filename, value.lineno)
713 else:
713 else:
714 lineno = 'unknown'
714 lineno = 'unknown'
715 textline = ''
715 textline = ''
716 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
716 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
717 (Colors.normalEm,
717 (Colors.normalEm,
718 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
718 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
719 Colors.linenoEm, lineno, Colors.Normal ))
719 Colors.linenoEm, lineno, Colors.Normal ))
720 if textline == '':
720 if textline == '':
721 textline = py3compat.cast_unicode(value.text, "utf-8")
721 textline = py3compat.cast_unicode(value.text, "utf-8")
722
722
723 if textline is not None:
723 if textline is not None:
724 i = 0
724 i = 0
725 while i < len(textline) and textline[i].isspace():
725 while i < len(textline) and textline[i].isspace():
726 i += 1
726 i += 1
727 list.append('%s %s%s\n' % (Colors.line,
727 list.append('%s %s%s\n' % (Colors.line,
728 textline.strip(),
728 textline.strip(),
729 Colors.Normal))
729 Colors.Normal))
730 if value.offset is not None:
730 if value.offset is not None:
731 s = ' '
731 s = ' '
732 for c in textline[i:value.offset - 1]:
732 for c in textline[i:value.offset - 1]:
733 if c.isspace():
733 if c.isspace():
734 s += c
734 s += c
735 else:
735 else:
736 s += ' '
736 s += ' '
737 list.append('%s%s^%s\n' % (Colors.caret, s,
737 list.append('%s%s^%s\n' % (Colors.caret, s,
738 Colors.Normal))
738 Colors.Normal))
739
739
740 try:
740 try:
741 s = value.msg
741 s = value.msg
742 except Exception:
742 except Exception:
743 s = self._some_str(value)
743 s = self._some_str(value)
744 if s:
744 if s:
745 list.append('%s%s:%s %s\n' % (stype, Colors.excName,
745 list.append('%s%s:%s %s\n' % (stype, Colors.excName,
746 Colors.Normal, s))
746 Colors.Normal, s))
747 else:
747 else:
748 list.append('%s\n' % stype)
748 list.append('%s\n' % stype)
749
749
750 # sync with user hooks
750 # sync with user hooks
751 if have_filedata:
751 if have_filedata:
752 ipinst = get_ipython()
752 ipinst = get_ipython()
753 if ipinst is not None:
753 if ipinst is not None:
754 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
754 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
755
755
756 return list
756 return list
757
757
758 def get_exception_only(self, etype, value):
758 def get_exception_only(self, etype, value):
759 """Only print the exception type and message, without a traceback.
759 """Only print the exception type and message, without a traceback.
760
760
761 Parameters
761 Parameters
762 ----------
762 ----------
763 etype : exception type
763 etype : exception type
764 value : exception value
764 value : exception value
765 """
765 """
766 return ListTB.structured_traceback(self, etype, value, [])
766 return ListTB.structured_traceback(self, etype, value, [])
767
767
768 def show_exception_only(self, etype, evalue):
768 def show_exception_only(self, etype, evalue):
769 """Only print the exception type and message, without a traceback.
769 """Only print the exception type and message, without a traceback.
770
770
771 Parameters
771 Parameters
772 ----------
772 ----------
773 etype : exception type
773 etype : exception type
774 value : exception value
774 value : exception value
775 """
775 """
776 # This method needs to use __call__ from *this* class, not the one from
776 # This method needs to use __call__ from *this* class, not the one from
777 # a subclass whose signature or behavior may be different
777 # a subclass whose signature or behavior may be different
778 ostream = self.ostream
778 ostream = self.ostream
779 ostream.flush()
779 ostream.flush()
780 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
780 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
781 ostream.flush()
781 ostream.flush()
782
782
783 def _some_str(self, value):
783 def _some_str(self, value):
784 # Lifted from traceback.py
784 # Lifted from traceback.py
785 try:
785 try:
786 return py3compat.cast_unicode(str(value))
786 return py3compat.cast_unicode(str(value))
787 except:
787 except:
788 return u'<unprintable %s object>' % type(value).__name__
788 return u'<unprintable %s object>' % type(value).__name__
789
789
790
790
791 #----------------------------------------------------------------------------
791 #----------------------------------------------------------------------------
792 class VerboseTB(TBTools):
792 class VerboseTB(TBTools):
793 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
793 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
794 of HTML. Requires inspect and pydoc. Crazy, man.
794 of HTML. Requires inspect and pydoc. Crazy, man.
795
795
796 Modified version which optionally strips the topmost entries from the
796 Modified version which optionally strips the topmost entries from the
797 traceback, to be used with alternate interpreters (because their own code
797 traceback, to be used with alternate interpreters (because their own code
798 would appear in the traceback)."""
798 would appear in the traceback)."""
799
799
800 def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None,
800 def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None,
801 tb_offset=0, long_header=False, include_vars=True,
801 tb_offset=0, long_header=False, include_vars=True,
802 check_cache=None, debugger_cls = None,
802 check_cache=None, debugger_cls = None,
803 parent=None, config=None):
803 parent=None, config=None):
804 """Specify traceback offset, headers and color scheme.
804 """Specify traceback offset, headers and color scheme.
805
805
806 Define how many frames to drop from the tracebacks. Calling it with
806 Define how many frames to drop from the tracebacks. Calling it with
807 tb_offset=1 allows use of this handler in interpreters which will have
807 tb_offset=1 allows use of this handler in interpreters which will have
808 their own code at the top of the traceback (VerboseTB will first
808 their own code at the top of the traceback (VerboseTB will first
809 remove that frame before printing the traceback info)."""
809 remove that frame before printing the traceback info)."""
810 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
810 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
811 ostream=ostream, parent=parent, config=config)
811 ostream=ostream, parent=parent, config=config)
812 self.tb_offset = tb_offset
812 self.tb_offset = tb_offset
813 self.long_header = long_header
813 self.long_header = long_header
814 self.include_vars = include_vars
814 self.include_vars = include_vars
815 # By default we use linecache.checkcache, but the user can provide a
815 # By default we use linecache.checkcache, but the user can provide a
816 # different check_cache implementation. This is used by the IPython
816 # different check_cache implementation. This is used by the IPython
817 # kernel to provide tracebacks for interactive code that is cached,
817 # kernel to provide tracebacks for interactive code that is cached,
818 # by a compiler instance that flushes the linecache but preserves its
818 # by a compiler instance that flushes the linecache but preserves its
819 # own code cache.
819 # own code cache.
820 if check_cache is None:
820 if check_cache is None:
821 check_cache = linecache.checkcache
821 check_cache = linecache.checkcache
822 self.check_cache = check_cache
822 self.check_cache = check_cache
823
823
824 self.debugger_cls = debugger_cls or debugger.Pdb
824 self.debugger_cls = debugger_cls or debugger.Pdb
825
825
826 def format_records(self, records, last_unique, recursion_repeat):
826 def format_records(self, records, last_unique, recursion_repeat):
827 """Format the stack frames of the traceback"""
827 """Format the stack frames of the traceback"""
828 frames = []
828 frames = []
829 for r in records[:last_unique+recursion_repeat+1]:
829 for r in records[:last_unique+recursion_repeat+1]:
830 #print '*** record:',file,lnum,func,lines,index # dbg
830 #print '*** record:',file,lnum,func,lines,index # dbg
831 frames.append(self.format_record(*r))
831 frames.append(self.format_record(*r))
832
832
833 if recursion_repeat:
833 if recursion_repeat:
834 frames.append('... last %d frames repeated, from the frame below ...\n' % recursion_repeat)
834 frames.append('... last %d frames repeated, from the frame below ...\n' % recursion_repeat)
835 frames.append(self.format_record(*records[last_unique+recursion_repeat+1]))
835 frames.append(self.format_record(*records[last_unique+recursion_repeat+1]))
836
836
837 return frames
837 return frames
838
838
839 def format_record(self, frame, file, lnum, func, lines, index):
839 def format_record(self, frame, file, lnum, func, lines, index):
840 """Format a single stack frame"""
840 """Format a single stack frame"""
841 Colors = self.Colors # just a shorthand + quicker name lookup
841 Colors = self.Colors # just a shorthand + quicker name lookup
842 ColorsNormal = Colors.Normal # used a lot
842 ColorsNormal = Colors.Normal # used a lot
843 col_scheme = self.color_scheme_table.active_scheme_name
843 col_scheme = self.color_scheme_table.active_scheme_name
844 indent = ' ' * INDENT_SIZE
844 indent = ' ' * INDENT_SIZE
845 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
845 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
846 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
846 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
847 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
847 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
848 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
848 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
849 ColorsNormal)
849 ColorsNormal)
850 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
850 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
851 (Colors.vName, Colors.valEm, ColorsNormal)
851 (Colors.vName, Colors.valEm, ColorsNormal)
852 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
852 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
853 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
853 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
854 Colors.vName, ColorsNormal)
854 Colors.vName, ColorsNormal)
855 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
855 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
856
856
857 if not file:
857 if not file:
858 file = '?'
858 file = '?'
859 elif file.startswith(str("<")) and file.endswith(str(">")):
859 elif file.startswith(str("<")) and file.endswith(str(">")):
860 # Not a real filename, no problem...
860 # Not a real filename, no problem...
861 pass
861 pass
862 elif not os.path.isabs(file):
862 elif not os.path.isabs(file):
863 # Try to make the filename absolute by trying all
863 # Try to make the filename absolute by trying all
864 # sys.path entries (which is also what linecache does)
864 # sys.path entries (which is also what linecache does)
865 for dirname in sys.path:
865 for dirname in sys.path:
866 try:
866 try:
867 fullname = os.path.join(dirname, file)
867 fullname = os.path.join(dirname, file)
868 if os.path.isfile(fullname):
868 if os.path.isfile(fullname):
869 file = os.path.abspath(fullname)
869 file = os.path.abspath(fullname)
870 break
870 break
871 except Exception:
871 except Exception:
872 # Just in case that sys.path contains very
872 # Just in case that sys.path contains very
873 # strange entries...
873 # strange entries...
874 pass
874 pass
875
875
876 file = py3compat.cast_unicode(file, util_path.fs_encoding)
876 file = py3compat.cast_unicode(file, util_path.fs_encoding)
877 link = tpl_link % util_path.compress_user(file)
877 link = tpl_link % util_path.compress_user(file)
878 args, varargs, varkw, locals_ = inspect.getargvalues(frame)
878 args, varargs, varkw, locals_ = inspect.getargvalues(frame)
879
879
880 if func == '?':
880 if func == '?':
881 call = ''
881 call = ''
882 elif func == '<module>':
882 elif func == '<module>':
883 call = tpl_call % (func, '')
883 call = tpl_call % (func, '')
884 else:
884 else:
885 # Decide whether to include variable details or not
885 # Decide whether to include variable details or not
886 var_repr = eqrepr if self.include_vars else nullrepr
886 var_repr = eqrepr if self.include_vars else nullrepr
887 try:
887 try:
888 call = tpl_call % (func, inspect.formatargvalues(args,
888 call = tpl_call % (func, inspect.formatargvalues(args,
889 varargs, varkw,
889 varargs, varkw,
890 locals_, formatvalue=var_repr))
890 locals_, formatvalue=var_repr))
891 except KeyError:
891 except KeyError:
892 # This happens in situations like errors inside generator
892 # This happens in situations like errors inside generator
893 # expressions, where local variables are listed in the
893 # expressions, where local variables are listed in the
894 # line, but can't be extracted from the frame. I'm not
894 # line, but can't be extracted from the frame. I'm not
895 # 100% sure this isn't actually a bug in inspect itself,
895 # 100% sure this isn't actually a bug in inspect itself,
896 # but since there's no info for us to compute with, the
896 # but since there's no info for us to compute with, the
897 # best we can do is report the failure and move on. Here
897 # best we can do is report the failure and move on. Here
898 # we must *not* call any traceback construction again,
898 # we must *not* call any traceback construction again,
899 # because that would mess up use of %debug later on. So we
899 # because that would mess up use of %debug later on. So we
900 # simply report the failure and move on. The only
900 # simply report the failure and move on. The only
901 # limitation will be that this frame won't have locals
901 # limitation will be that this frame won't have locals
902 # listed in the call signature. Quite subtle problem...
902 # listed in the call signature. Quite subtle problem...
903 # I can't think of a good way to validate this in a unit
903 # I can't think of a good way to validate this in a unit
904 # test, but running a script consisting of:
904 # test, but running a script consisting of:
905 # dict( (k,v.strip()) for (k,v) in range(10) )
905 # dict( (k,v.strip()) for (k,v) in range(10) )
906 # will illustrate the error, if this exception catch is
906 # will illustrate the error, if this exception catch is
907 # disabled.
907 # disabled.
908 call = tpl_call_fail % func
908 call = tpl_call_fail % func
909
909
910 # Don't attempt to tokenize binary files.
910 # Don't attempt to tokenize binary files.
911 if file.endswith(('.so', '.pyd', '.dll')):
911 if file.endswith(('.so', '.pyd', '.dll')):
912 return '%s %s\n' % (link, call)
912 return '%s %s\n' % (link, call)
913
913
914 elif file.endswith(('.pyc', '.pyo')):
914 elif file.endswith(('.pyc', '.pyo')):
915 # Look up the corresponding source file.
915 # Look up the corresponding source file.
916 try:
916 try:
917 file = source_from_cache(file)
917 file = source_from_cache(file)
918 except ValueError:
918 except ValueError:
919 # Failed to get the source file for some reason
919 # Failed to get the source file for some reason
920 # E.g. https://github.com/ipython/ipython/issues/9486
920 # E.g. https://github.com/ipython/ipython/issues/9486
921 return '%s %s\n' % (link, call)
921 return '%s %s\n' % (link, call)
922
922
923 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
923 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
924 line = getline(file, lnum[0])
924 line = getline(file, lnum[0])
925 lnum[0] += 1
925 lnum[0] += 1
926 return line
926 return line
927
927
928 # Build the list of names on this line of code where the exception
928 # Build the list of names on this line of code where the exception
929 # occurred.
929 # occurred.
930 try:
930 try:
931 names = []
931 names = []
932 name_cont = False
932 name_cont = False
933
933
934 for token_type, token, start, end, line in generate_tokens(linereader):
934 for token_type, token, start, end, line in generate_tokens(linereader):
935 # build composite names
935 # build composite names
936 if token_type == tokenize.NAME and token not in keyword.kwlist:
936 if token_type == tokenize.NAME and token not in keyword.kwlist:
937 if name_cont:
937 if name_cont:
938 # Continuation of a dotted name
938 # Continuation of a dotted name
939 try:
939 try:
940 names[-1].append(token)
940 names[-1].append(token)
941 except IndexError:
941 except IndexError:
942 names.append([token])
942 names.append([token])
943 name_cont = False
943 name_cont = False
944 else:
944 else:
945 # Regular new names. We append everything, the caller
945 # Regular new names. We append everything, the caller
946 # will be responsible for pruning the list later. It's
946 # will be responsible for pruning the list later. It's
947 # very tricky to try to prune as we go, b/c composite
947 # very tricky to try to prune as we go, b/c composite
948 # names can fool us. The pruning at the end is easy
948 # names can fool us. The pruning at the end is easy
949 # to do (or the caller can print a list with repeated
949 # to do (or the caller can print a list with repeated
950 # names if so desired.
950 # names if so desired.
951 names.append([token])
951 names.append([token])
952 elif token == '.':
952 elif token == '.':
953 name_cont = True
953 name_cont = True
954 elif token_type == tokenize.NEWLINE:
954 elif token_type == tokenize.NEWLINE:
955 break
955 break
956
956
957 except (IndexError, UnicodeDecodeError, SyntaxError):
957 except (IndexError, UnicodeDecodeError, SyntaxError):
958 # signals exit of tokenizer
958 # signals exit of tokenizer
959 # SyntaxError can occur if the file is not actually Python
959 # SyntaxError can occur if the file is not actually Python
960 # - see gh-6300
960 # - see gh-6300
961 pass
961 pass
962 except tokenize.TokenError as msg:
962 except tokenize.TokenError as msg:
963 # Tokenizing may fail for various reasons, many of which are
963 # Tokenizing may fail for various reasons, many of which are
964 # harmless. (A good example is when the line in question is the
964 # harmless. (A good example is when the line in question is the
965 # close of a triple-quoted string, cf gh-6864). We don't want to
965 # close of a triple-quoted string, cf gh-6864). We don't want to
966 # show this to users, but want make it available for debugging
966 # show this to users, but want make it available for debugging
967 # purposes.
967 # purposes.
968 _m = ("An unexpected error occurred while tokenizing input\n"
968 _m = ("An unexpected error occurred while tokenizing input\n"
969 "The following traceback may be corrupted or invalid\n"
969 "The following traceback may be corrupted or invalid\n"
970 "The error message is: %s\n" % msg)
970 "The error message is: %s\n" % msg)
971 debug(_m)
971 debug(_m)
972
972
973 # Join composite names (e.g. "dict.fromkeys")
973 # Join composite names (e.g. "dict.fromkeys")
974 names = ['.'.join(n) for n in names]
974 names = ['.'.join(n) for n in names]
975 # prune names list of duplicates, but keep the right order
975 # prune names list of duplicates, but keep the right order
976 unique_names = uniq_stable(names)
976 unique_names = uniq_stable(names)
977
977
978 # Start loop over vars
978 # Start loop over vars
979 lvals = ''
979 lvals = ''
980 lvals_list = []
980 lvals_list = []
981 if self.include_vars:
981 if self.include_vars:
982 for name_full in unique_names:
982 for name_full in unique_names:
983 name_base = name_full.split('.', 1)[0]
983 name_base = name_full.split('.', 1)[0]
984 if name_base in frame.f_code.co_varnames:
984 if name_base in frame.f_code.co_varnames:
985 if name_base in locals_:
985 if name_base in locals_:
986 try:
986 try:
987 value = repr(eval(name_full, locals_))
987 value = repr(eval(name_full, locals_))
988 except:
988 except:
989 value = undefined
989 value = undefined
990 else:
990 else:
991 value = undefined
991 value = undefined
992 name = tpl_local_var % name_full
992 name = tpl_local_var % name_full
993 else:
993 else:
994 if name_base in frame.f_globals:
994 if name_base in frame.f_globals:
995 try:
995 try:
996 value = repr(eval(name_full, frame.f_globals))
996 value = repr(eval(name_full, frame.f_globals))
997 except:
997 except:
998 value = undefined
998 value = undefined
999 else:
999 else:
1000 value = undefined
1000 value = undefined
1001 name = tpl_global_var % name_full
1001 name = tpl_global_var % name_full
1002 lvals_list.append(tpl_name_val % (name, value))
1002 lvals_list.append(tpl_name_val % (name, value))
1003 if lvals_list:
1003 if lvals_list:
1004 lvals = '%s%s' % (indent, em_normal.join(lvals_list))
1004 lvals = '%s%s' % (indent, em_normal.join(lvals_list))
1005
1005
1006 level = '%s %s\n' % (link, call)
1006 level = '%s %s\n' % (link, call)
1007
1007
1008 if index is None:
1008 if index is None:
1009 return level
1009 return level
1010 else:
1010 else:
1011 _line_format = PyColorize.Parser(style=col_scheme, parent=self).format2
1011 _line_format = PyColorize.Parser(style=col_scheme, parent=self).format2
1012 return '%s%s' % (level, ''.join(
1012 return '%s%s' % (level, ''.join(
1013 _format_traceback_lines(lnum, index, lines, Colors, lvals,
1013 _format_traceback_lines(lnum, index, lines, Colors, lvals,
1014 _line_format)))
1014 _line_format)))
1015
1015
1016 def prepare_chained_exception_message(self, cause):
1016 def prepare_chained_exception_message(self, cause):
1017 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
1017 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
1018 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
1018 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
1019
1019
1020 if cause:
1020 if cause:
1021 message = [[direct_cause]]
1021 message = [[direct_cause]]
1022 else:
1022 else:
1023 message = [[exception_during_handling]]
1023 message = [[exception_during_handling]]
1024 return message
1024 return message
1025
1025
1026 def prepare_header(self, etype, long_version=False):
1026 def prepare_header(self, etype, long_version=False):
1027 colors = self.Colors # just a shorthand + quicker name lookup
1027 colors = self.Colors # just a shorthand + quicker name lookup
1028 colorsnormal = colors.Normal # used a lot
1028 colorsnormal = colors.Normal # used a lot
1029 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
1029 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
1030 width = min(75, get_terminal_size()[0])
1030 width = min(75, get_terminal_size()[0])
1031 if long_version:
1031 if long_version:
1032 # Header with the exception type, python version, and date
1032 # Header with the exception type, python version, and date
1033 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
1033 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
1034 date = time.ctime(time.time())
1034 date = time.ctime(time.time())
1035
1035
1036 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * width, colorsnormal,
1036 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * width, colorsnormal,
1037 exc, ' ' * (width - len(str(etype)) - len(pyver)),
1037 exc, ' ' * (width - len(str(etype)) - len(pyver)),
1038 pyver, date.rjust(width) )
1038 pyver, date.rjust(width) )
1039 head += "\nA problem occurred executing Python code. Here is the sequence of function" \
1039 head += "\nA problem occurred executing Python code. Here is the sequence of function" \
1040 "\ncalls leading up to the error, with the most recent (innermost) call last."
1040 "\ncalls leading up to the error, with the most recent (innermost) call last."
1041 else:
1041 else:
1042 # Simplified header
1042 # Simplified header
1043 head = '%s%s' % (exc, 'Traceback (most recent call last)'. \
1043 head = '%s%s' % (exc, 'Traceback (most recent call last)'. \
1044 rjust(width - len(str(etype))) )
1044 rjust(width - len(str(etype))) )
1045
1045
1046 return head
1046 return head
1047
1047
1048 def format_exception(self, etype, evalue):
1048 def format_exception(self, etype, evalue):
1049 colors = self.Colors # just a shorthand + quicker name lookup
1049 colors = self.Colors # just a shorthand + quicker name lookup
1050 colorsnormal = colors.Normal # used a lot
1050 colorsnormal = colors.Normal # used a lot
1051 # Get (safely) a string form of the exception info
1051 # Get (safely) a string form of the exception info
1052 try:
1052 try:
1053 etype_str, evalue_str = map(str, (etype, evalue))
1053 etype_str, evalue_str = map(str, (etype, evalue))
1054 except:
1054 except:
1055 # User exception is improperly defined.
1055 # User exception is improperly defined.
1056 etype, evalue = str, sys.exc_info()[:2]
1056 etype, evalue = str, sys.exc_info()[:2]
1057 etype_str, evalue_str = map(str, (etype, evalue))
1057 etype_str, evalue_str = map(str, (etype, evalue))
1058 # ... and format it
1058 # ... and format it
1059 return ['%s%s%s: %s' % (colors.excName, etype_str,
1059 return ['%s%s%s: %s' % (colors.excName, etype_str,
1060 colorsnormal, py3compat.cast_unicode(evalue_str))]
1060 colorsnormal, py3compat.cast_unicode(evalue_str))]
1061
1061
1062 def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset):
1062 def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset):
1063 """Formats the header, traceback and exception message for a single exception.
1063 """Formats the header, traceback and exception message for a single exception.
1064
1064
1065 This may be called multiple times by Python 3 exception chaining
1065 This may be called multiple times by Python 3 exception chaining
1066 (PEP 3134).
1066 (PEP 3134).
1067 """
1067 """
1068 # some locals
1068 # some locals
1069 orig_etype = etype
1069 orig_etype = etype
1070 try:
1070 try:
1071 etype = etype.__name__
1071 etype = etype.__name__
1072 except AttributeError:
1072 except AttributeError:
1073 pass
1073 pass
1074
1074
1075 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1075 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1076 head = self.prepare_header(etype, self.long_header)
1076 head = self.prepare_header(etype, self.long_header)
1077 records = self.get_records(etb, number_of_lines_of_context, tb_offset)
1077 records = self.get_records(etb, number_of_lines_of_context, tb_offset)
1078
1078
1079 if records is None:
1079 if records is None:
1080 return ""
1080 return ""
1081
1081
1082 last_unique, recursion_repeat = find_recursion(orig_etype, evalue, records)
1082 last_unique, recursion_repeat = find_recursion(orig_etype, evalue, records)
1083
1083
1084 frames = self.format_records(records, last_unique, recursion_repeat)
1084 frames = self.format_records(records, last_unique, recursion_repeat)
1085
1085
1086 formatted_exception = self.format_exception(etype, evalue)
1086 formatted_exception = self.format_exception(etype, evalue)
1087 if records:
1087 if records:
1088 filepath, lnum = records[-1][1:3]
1088 filepath, lnum = records[-1][1:3]
1089 filepath = os.path.abspath(filepath)
1089 filepath = os.path.abspath(filepath)
1090 ipinst = get_ipython()
1090 ipinst = get_ipython()
1091 if ipinst is not None:
1091 if ipinst is not None:
1092 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
1092 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
1093
1093
1094 return [[head] + frames + [''.join(formatted_exception[0])]]
1094 return [[head] + frames + [''.join(formatted_exception[0])]]
1095
1095
1096 def get_records(self, etb, number_of_lines_of_context, tb_offset):
1096 def get_records(self, etb, number_of_lines_of_context, tb_offset):
1097 try:
1097 try:
1098 # Try the default getinnerframes and Alex's: Alex's fixes some
1098 # Try the default getinnerframes and Alex's: Alex's fixes some
1099 # problems, but it generates empty tracebacks for console errors
1099 # problems, but it generates empty tracebacks for console errors
1100 # (5 blanks lines) where none should be returned.
1100 # (5 blanks lines) where none should be returned.
1101 return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset)
1101 return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset)
1102 except UnicodeDecodeError:
1102 except UnicodeDecodeError:
1103 # This can occur if a file's encoding magic comment is wrong.
1103 # This can occur if a file's encoding magic comment is wrong.
1104 # I can't see a way to recover without duplicating a bunch of code
1104 # I can't see a way to recover without duplicating a bunch of code
1105 # from the stdlib traceback module. --TK
1105 # from the stdlib traceback module. --TK
1106 error('\nUnicodeDecodeError while processing traceback.\n')
1106 error('\nUnicodeDecodeError while processing traceback.\n')
1107 return None
1107 return None
1108 except:
1108 except:
1109 # FIXME: I've been getting many crash reports from python 2.3
1109 # FIXME: I've been getting many crash reports from python 2.3
1110 # users, traceable to inspect.py. If I can find a small test-case
1110 # users, traceable to inspect.py. If I can find a small test-case
1111 # to reproduce this, I should either write a better workaround or
1111 # to reproduce this, I should either write a better workaround or
1112 # file a bug report against inspect (if that's the real problem).
1112 # file a bug report against inspect (if that's the real problem).
1113 # So far, I haven't been able to find an isolated example to
1113 # So far, I haven't been able to find an isolated example to
1114 # reproduce the problem.
1114 # reproduce the problem.
1115 inspect_error()
1115 inspect_error()
1116 traceback.print_exc(file=self.ostream)
1116 traceback.print_exc(file=self.ostream)
1117 info('\nUnfortunately, your original traceback can not be constructed.\n')
1117 info('\nUnfortunately, your original traceback can not be constructed.\n')
1118 return None
1118 return None
1119
1119
1120 def get_parts_of_chained_exception(self, evalue):
1120 def get_parts_of_chained_exception(self, evalue):
1121 def get_chained_exception(exception_value):
1121 def get_chained_exception(exception_value):
1122 cause = getattr(exception_value, '__cause__', None)
1122 cause = getattr(exception_value, '__cause__', None)
1123 if cause:
1123 if cause:
1124 return cause
1124 return cause
1125 if getattr(exception_value, '__suppress_context__', False):
1125 if getattr(exception_value, '__suppress_context__', False):
1126 return None
1126 return None
1127 return getattr(exception_value, '__context__', None)
1127 return getattr(exception_value, '__context__', None)
1128
1128
1129 chained_evalue = get_chained_exception(evalue)
1129 chained_evalue = get_chained_exception(evalue)
1130
1130
1131 if chained_evalue:
1131 if chained_evalue:
1132 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
1132 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
1133
1133
1134 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
1134 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
1135 number_of_lines_of_context=5):
1135 number_of_lines_of_context=5):
1136 """Return a nice text document describing the traceback."""
1136 """Return a nice text document describing the traceback."""
1137
1137
1138 formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
1138 formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
1139 tb_offset)
1139 tb_offset)
1140
1140
1141 colors = self.Colors # just a shorthand + quicker name lookup
1141 colors = self.Colors # just a shorthand + quicker name lookup
1142 colorsnormal = colors.Normal # used a lot
1142 colorsnormal = colors.Normal # used a lot
1143 head = '%s%s%s' % (colors.topline, '-' * min(75, get_terminal_size()[0]), colorsnormal)
1143 head = '%s%s%s' % (colors.topline, '-' * min(75, get_terminal_size()[0]), colorsnormal)
1144 structured_traceback_parts = [head]
1144 structured_traceback_parts = [head]
1145 chained_exceptions_tb_offset = 0
1145 chained_exceptions_tb_offset = 0
1146 lines_of_context = 3
1146 lines_of_context = 3
1147 formatted_exceptions = formatted_exception
1147 formatted_exceptions = formatted_exception
1148 exception = self.get_parts_of_chained_exception(evalue)
1148 exception = self.get_parts_of_chained_exception(evalue)
1149 if exception:
1149 if exception:
1150 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1150 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1151 etype, evalue, etb = exception
1151 etype, evalue, etb = exception
1152 else:
1152 else:
1153 evalue = None
1153 evalue = None
1154 chained_exc_ids = set()
1154 chained_exc_ids = set()
1155 while evalue:
1155 while evalue:
1156 formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context,
1156 formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context,
1157 chained_exceptions_tb_offset)
1157 chained_exceptions_tb_offset)
1158 exception = self.get_parts_of_chained_exception(evalue)
1158 exception = self.get_parts_of_chained_exception(evalue)
1159
1159
1160 if exception and not id(exception[1]) in chained_exc_ids:
1160 if exception and not id(exception[1]) in chained_exc_ids:
1161 chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop
1161 chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop
1162 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1162 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1163 etype, evalue, etb = exception
1163 etype, evalue, etb = exception
1164 else:
1164 else:
1165 evalue = None
1165 evalue = None
1166
1166
1167 # we want to see exceptions in a reversed order:
1167 # we want to see exceptions in a reversed order:
1168 # the first exception should be on top
1168 # the first exception should be on top
1169 for formatted_exception in reversed(formatted_exceptions):
1169 for formatted_exception in reversed(formatted_exceptions):
1170 structured_traceback_parts += formatted_exception
1170 structured_traceback_parts += formatted_exception
1171
1171
1172 return structured_traceback_parts
1172 return structured_traceback_parts
1173
1173
1174 def debugger(self, force=False):
1174 def debugger(self, force=False):
1175 """Call up the pdb debugger if desired, always clean up the tb
1175 """Call up the pdb debugger if desired, always clean up the tb
1176 reference.
1176 reference.
1177
1177
1178 Keywords:
1178 Keywords:
1179
1179
1180 - force(False): by default, this routine checks the instance call_pdb
1180 - force(False): by default, this routine checks the instance call_pdb
1181 flag and does not actually invoke the debugger if the flag is false.
1181 flag and does not actually invoke the debugger if the flag is false.
1182 The 'force' option forces the debugger to activate even if the flag
1182 The 'force' option forces the debugger to activate even if the flag
1183 is false.
1183 is false.
1184
1184
1185 If the call_pdb flag is set, the pdb interactive debugger is
1185 If the call_pdb flag is set, the pdb interactive debugger is
1186 invoked. In all cases, the self.tb reference to the current traceback
1186 invoked. In all cases, the self.tb reference to the current traceback
1187 is deleted to prevent lingering references which hamper memory
1187 is deleted to prevent lingering references which hamper memory
1188 management.
1188 management.
1189
1189
1190 Note that each call to pdb() does an 'import readline', so if your app
1190 Note that each call to pdb() does an 'import readline', so if your app
1191 requires a special setup for the readline completers, you'll have to
1191 requires a special setup for the readline completers, you'll have to
1192 fix that by hand after invoking the exception handler."""
1192 fix that by hand after invoking the exception handler."""
1193
1193
1194 if force or self.call_pdb:
1194 if force or self.call_pdb:
1195 if self.pdb is None:
1195 if self.pdb is None:
1196 self.pdb = self.debugger_cls()
1196 self.pdb = self.debugger_cls()
1197 # the system displayhook may have changed, restore the original
1197 # the system displayhook may have changed, restore the original
1198 # for pdb
1198 # for pdb
1199 display_trap = DisplayTrap(hook=sys.__displayhook__)
1199 display_trap = DisplayTrap(hook=sys.__displayhook__)
1200 with display_trap:
1200 with display_trap:
1201 self.pdb.reset()
1201 self.pdb.reset()
1202 # Find the right frame so we don't pop up inside ipython itself
1202 # Find the right frame so we don't pop up inside ipython itself
1203 if hasattr(self, 'tb') and self.tb is not None:
1203 if hasattr(self, 'tb') and self.tb is not None:
1204 etb = self.tb
1204 etb = self.tb
1205 else:
1205 else:
1206 etb = self.tb = sys.last_traceback
1206 etb = self.tb = sys.last_traceback
1207 while self.tb is not None and self.tb.tb_next is not None:
1207 while self.tb is not None and self.tb.tb_next is not None:
1208 self.tb = self.tb.tb_next
1208 self.tb = self.tb.tb_next
1209 if etb and etb.tb_next:
1209 if etb and etb.tb_next:
1210 etb = etb.tb_next
1210 etb = etb.tb_next
1211 self.pdb.botframe = etb.tb_frame
1211 self.pdb.botframe = etb.tb_frame
1212 self.pdb.interaction(None, etb)
1212 self.pdb.interaction(None, etb)
1213
1213
1214 if hasattr(self, 'tb'):
1214 if hasattr(self, 'tb'):
1215 del self.tb
1215 del self.tb
1216
1216
1217 def handler(self, info=None):
1217 def handler(self, info=None):
1218 (etype, evalue, etb) = info or sys.exc_info()
1218 (etype, evalue, etb) = info or sys.exc_info()
1219 self.tb = etb
1219 self.tb = etb
1220 ostream = self.ostream
1220 ostream = self.ostream
1221 ostream.flush()
1221 ostream.flush()
1222 ostream.write(self.text(etype, evalue, etb))
1222 ostream.write(self.text(etype, evalue, etb))
1223 ostream.write('\n')
1223 ostream.write('\n')
1224 ostream.flush()
1224 ostream.flush()
1225
1225
1226 # Changed so an instance can just be called as VerboseTB_inst() and print
1226 # Changed so an instance can just be called as VerboseTB_inst() and print
1227 # out the right info on its own.
1227 # out the right info on its own.
1228 def __call__(self, etype=None, evalue=None, etb=None):
1228 def __call__(self, etype=None, evalue=None, etb=None):
1229 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1229 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1230 if etb is None:
1230 if etb is None:
1231 self.handler()
1231 self.handler()
1232 else:
1232 else:
1233 self.handler((etype, evalue, etb))
1233 self.handler((etype, evalue, etb))
1234 try:
1234 try:
1235 self.debugger()
1235 self.debugger()
1236 except KeyboardInterrupt:
1236 except KeyboardInterrupt:
1237 print("\nKeyboardInterrupt")
1237 print("\nKeyboardInterrupt")
1238
1238
1239
1239
1240 #----------------------------------------------------------------------------
1240 #----------------------------------------------------------------------------
1241 class FormattedTB(VerboseTB, ListTB):
1241 class FormattedTB(VerboseTB, ListTB):
1242 """Subclass ListTB but allow calling with a traceback.
1242 """Subclass ListTB but allow calling with a traceback.
1243
1243
1244 It can thus be used as a sys.excepthook for Python > 2.1.
1244 It can thus be used as a sys.excepthook for Python > 2.1.
1245
1245
1246 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1246 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1247
1247
1248 Allows a tb_offset to be specified. This is useful for situations where
1248 Allows a tb_offset to be specified. This is useful for situations where
1249 one needs to remove a number of topmost frames from the traceback (such as
1249 one needs to remove a number of topmost frames from the traceback (such as
1250 occurs with python programs that themselves execute other python code,
1250 occurs with python programs that themselves execute other python code,
1251 like Python shells). """
1251 like Python shells). """
1252
1252
1253 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1253 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1254 ostream=None,
1254 ostream=None,
1255 tb_offset=0, long_header=False, include_vars=False,
1255 tb_offset=0, long_header=False, include_vars=False,
1256 check_cache=None, debugger_cls=None,
1256 check_cache=None, debugger_cls=None,
1257 parent=None, config=None):
1257 parent=None, config=None):
1258
1258
1259 # NEVER change the order of this list. Put new modes at the end:
1259 # NEVER change the order of this list. Put new modes at the end:
1260 self.valid_modes = ['Plain', 'Context', 'Verbose', 'Minimal']
1260 self.valid_modes = ['Plain', 'Context', 'Verbose', 'Minimal']
1261 self.verbose_modes = self.valid_modes[1:3]
1261 self.verbose_modes = self.valid_modes[1:3]
1262
1262
1263 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1263 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1264 ostream=ostream, tb_offset=tb_offset,
1264 ostream=ostream, tb_offset=tb_offset,
1265 long_header=long_header, include_vars=include_vars,
1265 long_header=long_header, include_vars=include_vars,
1266 check_cache=check_cache, debugger_cls=debugger_cls,
1266 check_cache=check_cache, debugger_cls=debugger_cls,
1267 parent=parent, config=config)
1267 parent=parent, config=config)
1268
1268
1269 # Different types of tracebacks are joined with different separators to
1269 # Different types of tracebacks are joined with different separators to
1270 # form a single string. They are taken from this dict
1270 # form a single string. They are taken from this dict
1271 self._join_chars = dict(Plain='', Context='\n', Verbose='\n',
1271 self._join_chars = dict(Plain='', Context='\n', Verbose='\n',
1272 Minimal='')
1272 Minimal='')
1273 # set_mode also sets the tb_join_char attribute
1273 # set_mode also sets the tb_join_char attribute
1274 self.set_mode(mode)
1274 self.set_mode(mode)
1275
1275
1276 def _extract_tb(self, tb):
1276 def _extract_tb(self, tb):
1277 if tb:
1277 if tb:
1278 return traceback.extract_tb(tb)
1278 return traceback.extract_tb(tb)
1279 else:
1279 else:
1280 return None
1280 return None
1281
1281
1282 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
1282 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
1283 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1283 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1284 mode = self.mode
1284 mode = self.mode
1285 if mode in self.verbose_modes:
1285 if mode in self.verbose_modes:
1286 # Verbose modes need a full traceback
1286 # Verbose modes need a full traceback
1287 return VerboseTB.structured_traceback(
1287 return VerboseTB.structured_traceback(
1288 self, etype, value, tb, tb_offset, number_of_lines_of_context
1288 self, etype, value, tb, tb_offset, number_of_lines_of_context
1289 )
1289 )
1290 elif mode == 'Minimal':
1290 elif mode == 'Minimal':
1291 return ListTB.get_exception_only(self, etype, value)
1291 return ListTB.get_exception_only(self, etype, value)
1292 else:
1292 else:
1293 # We must check the source cache because otherwise we can print
1293 # We must check the source cache because otherwise we can print
1294 # out-of-date source code.
1294 # out-of-date source code.
1295 self.check_cache()
1295 self.check_cache()
1296 # Now we can extract and format the exception
1296 # Now we can extract and format the exception
1297 elist = self._extract_tb(tb)
1297 elist = self._extract_tb(tb)
1298 return ListTB.structured_traceback(
1298 return ListTB.structured_traceback(
1299 self, etype, value, elist, tb_offset, number_of_lines_of_context
1299 self, etype, value, elist, tb_offset, number_of_lines_of_context
1300 )
1300 )
1301
1301
1302 def stb2text(self, stb):
1302 def stb2text(self, stb):
1303 """Convert a structured traceback (a list) to a string."""
1303 """Convert a structured traceback (a list) to a string."""
1304 return self.tb_join_char.join(stb)
1304 return self.tb_join_char.join(stb)
1305
1305
1306
1306
1307 def set_mode(self, mode=None):
1307 def set_mode(self, mode=None):
1308 """Switch to the desired mode.
1308 """Switch to the desired mode.
1309
1309
1310 If mode is not specified, cycles through the available modes."""
1310 If mode is not specified, cycles through the available modes."""
1311
1311
1312 if not mode:
1312 if not mode:
1313 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
1313 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
1314 len(self.valid_modes)
1314 len(self.valid_modes)
1315 self.mode = self.valid_modes[new_idx]
1315 self.mode = self.valid_modes[new_idx]
1316 elif mode not in self.valid_modes:
1316 elif mode not in self.valid_modes:
1317 raise ValueError('Unrecognized mode in FormattedTB: <' + mode + '>\n'
1317 raise ValueError('Unrecognized mode in FormattedTB: <' + mode + '>\n'
1318 'Valid modes: ' + str(self.valid_modes))
1318 'Valid modes: ' + str(self.valid_modes))
1319 else:
1319 else:
1320 self.mode = mode
1320 self.mode = mode
1321 # include variable details only in 'Verbose' mode
1321 # include variable details only in 'Verbose' mode
1322 self.include_vars = (self.mode == self.valid_modes[2])
1322 self.include_vars = (self.mode == self.valid_modes[2])
1323 # Set the join character for generating text tracebacks
1323 # Set the join character for generating text tracebacks
1324 self.tb_join_char = self._join_chars[self.mode]
1324 self.tb_join_char = self._join_chars[self.mode]
1325
1325
1326 # some convenient shortcuts
1326 # some convenient shortcuts
1327 def plain(self):
1327 def plain(self):
1328 self.set_mode(self.valid_modes[0])
1328 self.set_mode(self.valid_modes[0])
1329
1329
1330 def context(self):
1330 def context(self):
1331 self.set_mode(self.valid_modes[1])
1331 self.set_mode(self.valid_modes[1])
1332
1332
1333 def verbose(self):
1333 def verbose(self):
1334 self.set_mode(self.valid_modes[2])
1334 self.set_mode(self.valid_modes[2])
1335
1335
1336 def minimal(self):
1336 def minimal(self):
1337 self.set_mode(self.valid_modes[3])
1337 self.set_mode(self.valid_modes[3])
1338
1338
1339
1339
1340 #----------------------------------------------------------------------------
1340 #----------------------------------------------------------------------------
1341 class AutoFormattedTB(FormattedTB):
1341 class AutoFormattedTB(FormattedTB):
1342 """A traceback printer which can be called on the fly.
1342 """A traceback printer which can be called on the fly.
1343
1343
1344 It will find out about exceptions by itself.
1344 It will find out about exceptions by itself.
1345
1345
1346 A brief example::
1346 A brief example::
1347
1347
1348 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1348 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1349 try:
1349 try:
1350 ...
1350 ...
1351 except:
1351 except:
1352 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1352 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1353 """
1353 """
1354
1354
1355 def __call__(self, etype=None, evalue=None, etb=None,
1355 def __call__(self, etype=None, evalue=None, etb=None,
1356 out=None, tb_offset=None):
1356 out=None, tb_offset=None):
1357 """Print out a formatted exception traceback.
1357 """Print out a formatted exception traceback.
1358
1358
1359 Optional arguments:
1359 Optional arguments:
1360 - out: an open file-like object to direct output to.
1360 - out: an open file-like object to direct output to.
1361
1361
1362 - tb_offset: the number of frames to skip over in the stack, on a
1362 - tb_offset: the number of frames to skip over in the stack, on a
1363 per-call basis (this overrides temporarily the instance's tb_offset
1363 per-call basis (this overrides temporarily the instance's tb_offset
1364 given at initialization time. """
1364 given at initialization time. """
1365
1365
1366 if out is None:
1366 if out is None:
1367 out = self.ostream
1367 out = self.ostream
1368 out.flush()
1368 out.flush()
1369 out.write(self.text(etype, evalue, etb, tb_offset))
1369 out.write(self.text(etype, evalue, etb, tb_offset))
1370 out.write('\n')
1370 out.write('\n')
1371 out.flush()
1371 out.flush()
1372 # FIXME: we should remove the auto pdb behavior from here and leave
1372 # FIXME: we should remove the auto pdb behavior from here and leave
1373 # that to the clients.
1373 # that to the clients.
1374 try:
1374 try:
1375 self.debugger()
1375 self.debugger()
1376 except KeyboardInterrupt:
1376 except KeyboardInterrupt:
1377 print("\nKeyboardInterrupt")
1377 print("\nKeyboardInterrupt")
1378
1378
1379 def structured_traceback(self, etype=None, value=None, tb=None,
1379 def structured_traceback(self, etype=None, value=None, tb=None,
1380 tb_offset=None, number_of_lines_of_context=5):
1380 tb_offset=None, number_of_lines_of_context=5):
1381 if etype is None:
1381 if etype is None:
1382 etype, value, tb = sys.exc_info()
1382 etype, value, tb = sys.exc_info()
1383 self.tb = tb
1383 self.tb = tb
1384 return FormattedTB.structured_traceback(
1384 return FormattedTB.structured_traceback(
1385 self, etype, value, tb, tb_offset, number_of_lines_of_context)
1385 self, etype, value, tb, tb_offset, number_of_lines_of_context)
1386
1386
1387
1387
1388 #---------------------------------------------------------------------------
1388 #---------------------------------------------------------------------------
1389
1389
1390 # A simple class to preserve Nathan's original functionality.
1390 # A simple class to preserve Nathan's original functionality.
1391 class ColorTB(FormattedTB):
1391 class ColorTB(FormattedTB):
1392 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1392 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1393
1393
1394 def __init__(self, color_scheme='Linux', call_pdb=0, **kwargs):
1394 def __init__(self, color_scheme='Linux', call_pdb=0, **kwargs):
1395 FormattedTB.__init__(self, color_scheme=color_scheme,
1395 FormattedTB.__init__(self, color_scheme=color_scheme,
1396 call_pdb=call_pdb, **kwargs)
1396 call_pdb=call_pdb, **kwargs)
1397
1397
1398
1398
1399 class SyntaxTB(ListTB):
1399 class SyntaxTB(ListTB):
1400 """Extension which holds some state: the last exception value"""
1400 """Extension which holds some state: the last exception value"""
1401
1401
1402 def __init__(self, color_scheme='NoColor', parent=None, config=None):
1402 def __init__(self, color_scheme='NoColor', parent=None, config=None):
1403 ListTB.__init__(self, color_scheme, parent=parent, config=config)
1403 ListTB.__init__(self, color_scheme, parent=parent, config=config)
1404 self.last_syntax_error = None
1404 self.last_syntax_error = None
1405
1405
1406 def __call__(self, etype, value, elist):
1406 def __call__(self, etype, value, elist):
1407 self.last_syntax_error = value
1407 self.last_syntax_error = value
1408
1408
1409 ListTB.__call__(self, etype, value, elist)
1409 ListTB.__call__(self, etype, value, elist)
1410
1410
1411 def structured_traceback(self, etype, value, elist, tb_offset=None,
1411 def structured_traceback(self, etype, value, elist, tb_offset=None,
1412 context=5):
1412 context=5):
1413 # If the source file has been edited, the line in the syntax error can
1413 # If the source file has been edited, the line in the syntax error can
1414 # be wrong (retrieved from an outdated cache). This replaces it with
1414 # be wrong (retrieved from an outdated cache). This replaces it with
1415 # the current value.
1415 # the current value.
1416 if isinstance(value, SyntaxError) \
1416 if isinstance(value, SyntaxError) \
1417 and isinstance(value.filename, str) \
1417 and isinstance(value.filename, str) \
1418 and isinstance(value.lineno, int):
1418 and isinstance(value.lineno, int):
1419 linecache.checkcache(value.filename)
1419 linecache.checkcache(value.filename)
1420 newtext = linecache.getline(value.filename, value.lineno)
1420 newtext = linecache.getline(value.filename, value.lineno)
1421 if newtext:
1421 if newtext:
1422 value.text = newtext
1422 value.text = newtext
1423 self.last_syntax_error = value
1423 self.last_syntax_error = value
1424 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1424 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1425 tb_offset=tb_offset, context=context)
1425 tb_offset=tb_offset, context=context)
1426
1426
1427 def clear_err_state(self):
1427 def clear_err_state(self):
1428 """Return the current error state and clear it"""
1428 """Return the current error state and clear it"""
1429 e = self.last_syntax_error
1429 e = self.last_syntax_error
1430 self.last_syntax_error = None
1430 self.last_syntax_error = None
1431 return e
1431 return e
1432
1432
1433 def stb2text(self, stb):
1433 def stb2text(self, stb):
1434 """Convert a structured traceback (a list) to a string."""
1434 """Convert a structured traceback (a list) to a string."""
1435 return ''.join(stb)
1435 return ''.join(stb)
1436
1436
1437
1437
1438 # some internal-use functions
1438 # some internal-use functions
1439 def text_repr(value):
1439 def text_repr(value):
1440 """Hopefully pretty robust repr equivalent."""
1440 """Hopefully pretty robust repr equivalent."""
1441 # this is pretty horrible but should always return *something*
1441 # this is pretty horrible but should always return *something*
1442 try:
1442 try:
1443 return pydoc.text.repr(value)
1443 return pydoc.text.repr(value)
1444 except KeyboardInterrupt:
1444 except KeyboardInterrupt:
1445 raise
1445 raise
1446 except:
1446 except:
1447 try:
1447 try:
1448 return repr(value)
1448 return repr(value)
1449 except KeyboardInterrupt:
1449 except KeyboardInterrupt:
1450 raise
1450 raise
1451 except:
1451 except:
1452 try:
1452 try:
1453 # all still in an except block so we catch
1453 # all still in an except block so we catch
1454 # getattr raising
1454 # getattr raising
1455 name = getattr(value, '__name__', None)
1455 name = getattr(value, '__name__', None)
1456 if name:
1456 if name:
1457 # ick, recursion
1457 # ick, recursion
1458 return text_repr(name)
1458 return text_repr(name)
1459 klass = getattr(value, '__class__', None)
1459 klass = getattr(value, '__class__', None)
1460 if klass:
1460 if klass:
1461 return '%s instance' % text_repr(klass)
1461 return '%s instance' % text_repr(klass)
1462 except KeyboardInterrupt:
1462 except KeyboardInterrupt:
1463 raise
1463 raise
1464 except:
1464 except:
1465 return 'UNRECOVERABLE REPR FAILURE'
1465 return 'UNRECOVERABLE REPR FAILURE'
1466
1466
1467
1467
1468 def eqrepr(value, repr=text_repr):
1468 def eqrepr(value, repr=text_repr):
1469 return '=%s' % repr(value)
1469 return '=%s' % repr(value)
1470
1470
1471
1471
1472 def nullrepr(value, repr=text_repr):
1472 def nullrepr(value, repr=text_repr):
1473 return ''
1473 return ''
@@ -1,32 +1,32 b''
1 """
1 """
2 **DEPRECATED**
2 **DEPRECATED**
3
3
4 A print function that pretty prints sympy Basic objects.
4 A print function that pretty prints sympy Basic objects.
5
5
6 :moduleauthor: Brian Granger
6 :moduleauthor: Brian Granger
7
7
8 Usage
8 Usage
9 =====
9 =====
10
10
11 Once the extension is loaded, Sympy Basic objects are automatically
11 Once the extension is loaded, Sympy Basic objects are automatically
12 pretty-printed.
12 pretty-printed.
13
13
14 As of SymPy 0.7.2, maintenance of this extension has moved to SymPy under
14 As of SymPy 0.7.2, maintenance of this extension has moved to SymPy under
15 sympy.interactive.ipythonprinting, any modifications to account for changes to
15 sympy.interactive.ipythonprinting, any modifications to account for changes to
16 SymPy should be submitted to SymPy rather than changed here. This module is
16 SymPy should be submitted to SymPy rather than changed here. This module is
17 maintained here for backwards compatablitiy with old SymPy versions.
17 maintained here for backwards compatibility with old SymPy versions.
18
18
19 """
19 """
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21 # Copyright (C) 2008 The IPython Development Team
21 # Copyright (C) 2008 The IPython Development Team
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23
23
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25 # Imports
25 # Imports
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
27
27
28 import warnings
28 import warnings
29
29
30 def load_ipython_extension(ip):
30 def load_ipython_extension(ip):
31 warnings.warn("The sympyprinting extension has moved to `sympy`, "
31 warnings.warn("The sympyprinting extension has moved to `sympy`, "
32 "use `from sympy import init_printing; init_printing()`")
32 "use `from sympy import init_printing; init_printing()`")
@@ -1,761 +1,761 b''
1 """Nose Plugin that supports IPython doctests.
1 """Nose Plugin that supports IPython doctests.
2
2
3 Limitations:
3 Limitations:
4
4
5 - When generating examples for use as doctests, make sure that you have
5 - When generating examples for use as doctests, make sure that you have
6 pretty-printing OFF. This can be done either by setting the
6 pretty-printing OFF. This can be done either by setting the
7 ``PlainTextFormatter.pprint`` option in your configuration file to False, or
7 ``PlainTextFormatter.pprint`` option in your configuration file to False, or
8 by interactively disabling it with %Pprint. This is required so that IPython
8 by interactively disabling it with %Pprint. This is required so that IPython
9 output matches that of normal Python, which is used by doctest for internal
9 output matches that of normal Python, which is used by doctest for internal
10 execution.
10 execution.
11
11
12 - Do not rely on specific prompt numbers for results (such as using
12 - Do not rely on specific prompt numbers for results (such as using
13 '_34==True', for example). For IPython tests run via an external process the
13 '_34==True', for example). For IPython tests run via an external process the
14 prompt numbers may be different, and IPython tests run as normal python code
14 prompt numbers may be different, and IPython tests run as normal python code
15 won't even have these special _NN variables set at all.
15 won't even have these special _NN variables set at all.
16 """
16 """
17
17
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19 # Module imports
19 # Module imports
20
20
21 # From the standard library
21 # From the standard library
22 import builtins as builtin_mod
22 import builtins as builtin_mod
23 import doctest
23 import doctest
24 import inspect
24 import inspect
25 import logging
25 import logging
26 import os
26 import os
27 import re
27 import re
28 import sys
28 import sys
29 from importlib import import_module
29 from importlib import import_module
30 from io import StringIO
30 from io import StringIO
31
31
32 from testpath import modified_env
32 from testpath import modified_env
33
33
34 from inspect import getmodule
34 from inspect import getmodule
35
35
36 # We are overriding the default doctest runner, so we need to import a few
36 # We are overriding the default doctest runner, so we need to import a few
37 # things from doctest directly
37 # things from doctest directly
38 from doctest import (REPORTING_FLAGS, REPORT_ONLY_FIRST_FAILURE,
38 from doctest import (REPORTING_FLAGS, REPORT_ONLY_FIRST_FAILURE,
39 _unittest_reportflags, DocTestRunner,
39 _unittest_reportflags, DocTestRunner,
40 _extract_future_flags, pdb, _OutputRedirectingPdb,
40 _extract_future_flags, pdb, _OutputRedirectingPdb,
41 _exception_traceback,
41 _exception_traceback,
42 linecache)
42 linecache)
43
43
44 # Third-party modules
44 # Third-party modules
45
45
46 from nose.plugins import doctests, Plugin
46 from nose.plugins import doctests, Plugin
47 from nose.util import anyp, tolist
47 from nose.util import anyp, tolist
48
48
49 #-----------------------------------------------------------------------------
49 #-----------------------------------------------------------------------------
50 # Module globals and other constants
50 # Module globals and other constants
51 #-----------------------------------------------------------------------------
51 #-----------------------------------------------------------------------------
52
52
53 log = logging.getLogger(__name__)
53 log = logging.getLogger(__name__)
54
54
55
55
56 #-----------------------------------------------------------------------------
56 #-----------------------------------------------------------------------------
57 # Classes and functions
57 # Classes and functions
58 #-----------------------------------------------------------------------------
58 #-----------------------------------------------------------------------------
59
59
60 def is_extension_module(filename):
60 def is_extension_module(filename):
61 """Return whether the given filename is an extension module.
61 """Return whether the given filename is an extension module.
62
62
63 This simply checks that the extension is either .so or .pyd.
63 This simply checks that the extension is either .so or .pyd.
64 """
64 """
65 return os.path.splitext(filename)[1].lower() in ('.so','.pyd')
65 return os.path.splitext(filename)[1].lower() in ('.so','.pyd')
66
66
67
67
68 class DocTestSkip(object):
68 class DocTestSkip(object):
69 """Object wrapper for doctests to be skipped."""
69 """Object wrapper for doctests to be skipped."""
70
70
71 ds_skip = """Doctest to skip.
71 ds_skip = """Doctest to skip.
72 >>> 1 #doctest: +SKIP
72 >>> 1 #doctest: +SKIP
73 """
73 """
74
74
75 def __init__(self,obj):
75 def __init__(self,obj):
76 self.obj = obj
76 self.obj = obj
77
77
78 def __getattribute__(self,key):
78 def __getattribute__(self,key):
79 if key == '__doc__':
79 if key == '__doc__':
80 return DocTestSkip.ds_skip
80 return DocTestSkip.ds_skip
81 else:
81 else:
82 return getattr(object.__getattribute__(self,'obj'),key)
82 return getattr(object.__getattribute__(self,'obj'),key)
83
83
84 # Modified version of the one in the stdlib, that fixes a python bug (doctests
84 # Modified version of the one in the stdlib, that fixes a python bug (doctests
85 # not found in extension modules, http://bugs.python.org/issue3158)
85 # not found in extension modules, http://bugs.python.org/issue3158)
86 class DocTestFinder(doctest.DocTestFinder):
86 class DocTestFinder(doctest.DocTestFinder):
87
87
88 def _from_module(self, module, object):
88 def _from_module(self, module, object):
89 """
89 """
90 Return true if the given object is defined in the given
90 Return true if the given object is defined in the given
91 module.
91 module.
92 """
92 """
93 if module is None:
93 if module is None:
94 return True
94 return True
95 elif inspect.isfunction(object):
95 elif inspect.isfunction(object):
96 return module.__dict__ is object.__globals__
96 return module.__dict__ is object.__globals__
97 elif inspect.isbuiltin(object):
97 elif inspect.isbuiltin(object):
98 return module.__name__ == object.__module__
98 return module.__name__ == object.__module__
99 elif inspect.isclass(object):
99 elif inspect.isclass(object):
100 return module.__name__ == object.__module__
100 return module.__name__ == object.__module__
101 elif inspect.ismethod(object):
101 elif inspect.ismethod(object):
102 # This one may be a bug in cython that fails to correctly set the
102 # This one may be a bug in cython that fails to correctly set the
103 # __module__ attribute of methods, but since the same error is easy
103 # __module__ attribute of methods, but since the same error is easy
104 # to make by extension code writers, having this safety in place
104 # to make by extension code writers, having this safety in place
105 # isn't such a bad idea
105 # isn't such a bad idea
106 return module.__name__ == object.__self__.__class__.__module__
106 return module.__name__ == object.__self__.__class__.__module__
107 elif inspect.getmodule(object) is not None:
107 elif inspect.getmodule(object) is not None:
108 return module is inspect.getmodule(object)
108 return module is inspect.getmodule(object)
109 elif hasattr(object, '__module__'):
109 elif hasattr(object, '__module__'):
110 return module.__name__ == object.__module__
110 return module.__name__ == object.__module__
111 elif isinstance(object, property):
111 elif isinstance(object, property):
112 return True # [XX] no way not be sure.
112 return True # [XX] no way not be sure.
113 elif inspect.ismethoddescriptor(object):
113 elif inspect.ismethoddescriptor(object):
114 # Unbound PyQt signals reach this point in Python 3.4b3, and we want
114 # Unbound PyQt signals reach this point in Python 3.4b3, and we want
115 # to avoid throwing an error. See also http://bugs.python.org/issue3158
115 # to avoid throwing an error. See also http://bugs.python.org/issue3158
116 return False
116 return False
117 else:
117 else:
118 raise ValueError("object must be a class or function, got %r" % object)
118 raise ValueError("object must be a class or function, got %r" % object)
119
119
120 def _find(self, tests, obj, name, module, source_lines, globs, seen):
120 def _find(self, tests, obj, name, module, source_lines, globs, seen):
121 """
121 """
122 Find tests for the given object and any contained objects, and
122 Find tests for the given object and any contained objects, and
123 add them to `tests`.
123 add them to `tests`.
124 """
124 """
125 print('_find for:', obj, name, module) # dbg
125 print('_find for:', obj, name, module) # dbg
126 if hasattr(obj,"skip_doctest"):
126 if hasattr(obj,"skip_doctest"):
127 #print 'SKIPPING DOCTEST FOR:',obj # dbg
127 #print 'SKIPPING DOCTEST FOR:',obj # dbg
128 obj = DocTestSkip(obj)
128 obj = DocTestSkip(obj)
129
129
130 doctest.DocTestFinder._find(self,tests, obj, name, module,
130 doctest.DocTestFinder._find(self,tests, obj, name, module,
131 source_lines, globs, seen)
131 source_lines, globs, seen)
132
132
133 # Below we re-run pieces of the above method with manual modifications,
133 # Below we re-run pieces of the above method with manual modifications,
134 # because the original code is buggy and fails to correctly identify
134 # because the original code is buggy and fails to correctly identify
135 # doctests in extension modules.
135 # doctests in extension modules.
136
136
137 # Local shorthands
137 # Local shorthands
138 from inspect import isroutine, isclass
138 from inspect import isroutine, isclass
139
139
140 # Look for tests in a module's contained objects.
140 # Look for tests in a module's contained objects.
141 if inspect.ismodule(obj) and self._recurse:
141 if inspect.ismodule(obj) and self._recurse:
142 for valname, val in obj.__dict__.items():
142 for valname, val in obj.__dict__.items():
143 valname1 = '%s.%s' % (name, valname)
143 valname1 = '%s.%s' % (name, valname)
144 if ( (isroutine(val) or isclass(val))
144 if ( (isroutine(val) or isclass(val))
145 and self._from_module(module, val) ):
145 and self._from_module(module, val) ):
146
146
147 self._find(tests, val, valname1, module, source_lines,
147 self._find(tests, val, valname1, module, source_lines,
148 globs, seen)
148 globs, seen)
149
149
150 # Look for tests in a class's contained objects.
150 # Look for tests in a class's contained objects.
151 if inspect.isclass(obj) and self._recurse:
151 if inspect.isclass(obj) and self._recurse:
152 #print 'RECURSE into class:',obj # dbg
152 #print 'RECURSE into class:',obj # dbg
153 for valname, val in obj.__dict__.items():
153 for valname, val in obj.__dict__.items():
154 # Special handling for staticmethod/classmethod.
154 # Special handling for staticmethod/classmethod.
155 if isinstance(val, staticmethod):
155 if isinstance(val, staticmethod):
156 val = getattr(obj, valname)
156 val = getattr(obj, valname)
157 if isinstance(val, classmethod):
157 if isinstance(val, classmethod):
158 val = getattr(obj, valname).__func__
158 val = getattr(obj, valname).__func__
159
159
160 # Recurse to methods, properties, and nested classes.
160 # Recurse to methods, properties, and nested classes.
161 if ((inspect.isfunction(val) or inspect.isclass(val) or
161 if ((inspect.isfunction(val) or inspect.isclass(val) or
162 inspect.ismethod(val) or
162 inspect.ismethod(val) or
163 isinstance(val, property)) and
163 isinstance(val, property)) and
164 self._from_module(module, val)):
164 self._from_module(module, val)):
165 valname = '%s.%s' % (name, valname)
165 valname = '%s.%s' % (name, valname)
166 self._find(tests, val, valname, module, source_lines,
166 self._find(tests, val, valname, module, source_lines,
167 globs, seen)
167 globs, seen)
168
168
169
169
170 class IPDoctestOutputChecker(doctest.OutputChecker):
170 class IPDoctestOutputChecker(doctest.OutputChecker):
171 """Second-chance checker with support for random tests.
171 """Second-chance checker with support for random tests.
172
172
173 If the default comparison doesn't pass, this checker looks in the expected
173 If the default comparison doesn't pass, this checker looks in the expected
174 output string for flags that tell us to ignore the output.
174 output string for flags that tell us to ignore the output.
175 """
175 """
176
176
177 random_re = re.compile(r'#\s*random\s+')
177 random_re = re.compile(r'#\s*random\s+')
178
178
179 def check_output(self, want, got, optionflags):
179 def check_output(self, want, got, optionflags):
180 """Check output, accepting special markers embedded in the output.
180 """Check output, accepting special markers embedded in the output.
181
181
182 If the output didn't pass the default validation but the special string
182 If the output didn't pass the default validation but the special string
183 '#random' is included, we accept it."""
183 '#random' is included, we accept it."""
184
184
185 # Let the original tester verify first, in case people have valid tests
185 # Let the original tester verify first, in case people have valid tests
186 # that happen to have a comment saying '#random' embedded in.
186 # that happen to have a comment saying '#random' embedded in.
187 ret = doctest.OutputChecker.check_output(self, want, got,
187 ret = doctest.OutputChecker.check_output(self, want, got,
188 optionflags)
188 optionflags)
189 if not ret and self.random_re.search(want):
189 if not ret and self.random_re.search(want):
190 #print >> sys.stderr, 'RANDOM OK:',want # dbg
190 #print >> sys.stderr, 'RANDOM OK:',want # dbg
191 return True
191 return True
192
192
193 return ret
193 return ret
194
194
195
195
196 class DocTestCase(doctests.DocTestCase):
196 class DocTestCase(doctests.DocTestCase):
197 """Proxy for DocTestCase: provides an address() method that
197 """Proxy for DocTestCase: provides an address() method that
198 returns the correct address for the doctest case. Otherwise
198 returns the correct address for the doctest case. Otherwise
199 acts as a proxy to the test case. To provide hints for address(),
199 acts as a proxy to the test case. To provide hints for address(),
200 an obj may also be passed -- this will be used as the test object
200 an obj may also be passed -- this will be used as the test object
201 for purposes of determining the test address, if it is provided.
201 for purposes of determining the test address, if it is provided.
202 """
202 """
203
203
204 # Note: this method was taken from numpy's nosetester module.
204 # Note: this method was taken from numpy's nosetester module.
205
205
206 # Subclass nose.plugins.doctests.DocTestCase to work around a bug in
206 # Subclass nose.plugins.doctests.DocTestCase to work around a bug in
207 # its constructor that blocks non-default arguments from being passed
207 # its constructor that blocks non-default arguments from being passed
208 # down into doctest.DocTestCase
208 # down into doctest.DocTestCase
209
209
210 def __init__(self, test, optionflags=0, setUp=None, tearDown=None,
210 def __init__(self, test, optionflags=0, setUp=None, tearDown=None,
211 checker=None, obj=None, result_var='_'):
211 checker=None, obj=None, result_var='_'):
212 self._result_var = result_var
212 self._result_var = result_var
213 doctests.DocTestCase.__init__(self, test,
213 doctests.DocTestCase.__init__(self, test,
214 optionflags=optionflags,
214 optionflags=optionflags,
215 setUp=setUp, tearDown=tearDown,
215 setUp=setUp, tearDown=tearDown,
216 checker=checker)
216 checker=checker)
217 # Now we must actually copy the original constructor from the stdlib
217 # Now we must actually copy the original constructor from the stdlib
218 # doctest class, because we can't call it directly and a bug in nose
218 # doctest class, because we can't call it directly and a bug in nose
219 # means it never gets passed the right arguments.
219 # means it never gets passed the right arguments.
220
220
221 self._dt_optionflags = optionflags
221 self._dt_optionflags = optionflags
222 self._dt_checker = checker
222 self._dt_checker = checker
223 self._dt_test = test
223 self._dt_test = test
224 self._dt_test_globs_ori = test.globs
224 self._dt_test_globs_ori = test.globs
225 self._dt_setUp = setUp
225 self._dt_setUp = setUp
226 self._dt_tearDown = tearDown
226 self._dt_tearDown = tearDown
227
227
228 # XXX - store this runner once in the object!
228 # XXX - store this runner once in the object!
229 runner = IPDocTestRunner(optionflags=optionflags,
229 runner = IPDocTestRunner(optionflags=optionflags,
230 checker=checker, verbose=False)
230 checker=checker, verbose=False)
231 self._dt_runner = runner
231 self._dt_runner = runner
232
232
233
233
234 # Each doctest should remember the directory it was loaded from, so
234 # Each doctest should remember the directory it was loaded from, so
235 # things like %run work without too many contortions
235 # things like %run work without too many contortions
236 self._ori_dir = os.path.dirname(test.filename)
236 self._ori_dir = os.path.dirname(test.filename)
237
237
238 # Modified runTest from the default stdlib
238 # Modified runTest from the default stdlib
239 def runTest(self):
239 def runTest(self):
240 test = self._dt_test
240 test = self._dt_test
241 runner = self._dt_runner
241 runner = self._dt_runner
242
242
243 old = sys.stdout
243 old = sys.stdout
244 new = StringIO()
244 new = StringIO()
245 optionflags = self._dt_optionflags
245 optionflags = self._dt_optionflags
246
246
247 if not (optionflags & REPORTING_FLAGS):
247 if not (optionflags & REPORTING_FLAGS):
248 # The option flags don't include any reporting flags,
248 # The option flags don't include any reporting flags,
249 # so add the default reporting flags
249 # so add the default reporting flags
250 optionflags |= _unittest_reportflags
250 optionflags |= _unittest_reportflags
251
251
252 try:
252 try:
253 # Save our current directory and switch out to the one where the
253 # Save our current directory and switch out to the one where the
254 # test was originally created, in case another doctest did a
254 # test was originally created, in case another doctest did a
255 # directory change. We'll restore this in the finally clause.
255 # directory change. We'll restore this in the finally clause.
256 curdir = os.getcwd()
256 curdir = os.getcwd()
257 #print 'runTest in dir:', self._ori_dir # dbg
257 #print 'runTest in dir:', self._ori_dir # dbg
258 os.chdir(self._ori_dir)
258 os.chdir(self._ori_dir)
259
259
260 runner.DIVIDER = "-"*70
260 runner.DIVIDER = "-"*70
261 failures, tries = runner.run(test,out=new.write,
261 failures, tries = runner.run(test,out=new.write,
262 clear_globs=False)
262 clear_globs=False)
263 finally:
263 finally:
264 sys.stdout = old
264 sys.stdout = old
265 os.chdir(curdir)
265 os.chdir(curdir)
266
266
267 if failures:
267 if failures:
268 raise self.failureException(self.format_failure(new.getvalue()))
268 raise self.failureException(self.format_failure(new.getvalue()))
269
269
270 def setUp(self):
270 def setUp(self):
271 """Modified test setup that syncs with ipython namespace"""
271 """Modified test setup that syncs with ipython namespace"""
272 #print "setUp test", self._dt_test.examples # dbg
272 #print "setUp test", self._dt_test.examples # dbg
273 if isinstance(self._dt_test.examples[0], IPExample):
273 if isinstance(self._dt_test.examples[0], IPExample):
274 # for IPython examples *only*, we swap the globals with the ipython
274 # for IPython examples *only*, we swap the globals with the ipython
275 # namespace, after updating it with the globals (which doctest
275 # namespace, after updating it with the globals (which doctest
276 # fills with the necessary info from the module being tested).
276 # fills with the necessary info from the module being tested).
277 self.user_ns_orig = {}
277 self.user_ns_orig = {}
278 self.user_ns_orig.update(_ip.user_ns)
278 self.user_ns_orig.update(_ip.user_ns)
279 _ip.user_ns.update(self._dt_test.globs)
279 _ip.user_ns.update(self._dt_test.globs)
280 # We must remove the _ key in the namespace, so that Python's
280 # We must remove the _ key in the namespace, so that Python's
281 # doctest code sets it naturally
281 # doctest code sets it naturally
282 _ip.user_ns.pop('_', None)
282 _ip.user_ns.pop('_', None)
283 _ip.user_ns['__builtins__'] = builtin_mod
283 _ip.user_ns['__builtins__'] = builtin_mod
284 self._dt_test.globs = _ip.user_ns
284 self._dt_test.globs = _ip.user_ns
285
285
286 super(DocTestCase, self).setUp()
286 super(DocTestCase, self).setUp()
287
287
288 def tearDown(self):
288 def tearDown(self):
289
289
290 # Undo the test.globs reassignment we made, so that the parent class
290 # Undo the test.globs reassignment we made, so that the parent class
291 # teardown doesn't destroy the ipython namespace
291 # teardown doesn't destroy the ipython namespace
292 if isinstance(self._dt_test.examples[0], IPExample):
292 if isinstance(self._dt_test.examples[0], IPExample):
293 self._dt_test.globs = self._dt_test_globs_ori
293 self._dt_test.globs = self._dt_test_globs_ori
294 _ip.user_ns.clear()
294 _ip.user_ns.clear()
295 _ip.user_ns.update(self.user_ns_orig)
295 _ip.user_ns.update(self.user_ns_orig)
296
296
297 # XXX - fperez: I am not sure if this is truly a bug in nose 0.11, but
297 # XXX - fperez: I am not sure if this is truly a bug in nose 0.11, but
298 # it does look like one to me: its tearDown method tries to run
298 # it does look like one to me: its tearDown method tries to run
299 #
299 #
300 # delattr(builtin_mod, self._result_var)
300 # delattr(builtin_mod, self._result_var)
301 #
301 #
302 # without checking that the attribute really is there; it implicitly
302 # without checking that the attribute really is there; it implicitly
303 # assumes it should have been set via displayhook. But if the
303 # assumes it should have been set via displayhook. But if the
304 # displayhook was never called, this doesn't necessarily happen. I
304 # displayhook was never called, this doesn't necessarily happen. I
305 # haven't been able to find a little self-contained example outside of
305 # haven't been able to find a little self-contained example outside of
306 # ipython that would show the problem so I can report it to the nose
306 # ipython that would show the problem so I can report it to the nose
307 # team, but it does happen a lot in our code.
307 # team, but it does happen a lot in our code.
308 #
308 #
309 # So here, we just protect as narrowly as possible by trapping an
309 # So here, we just protect as narrowly as possible by trapping an
310 # attribute error whose message would be the name of self._result_var,
310 # attribute error whose message would be the name of self._result_var,
311 # and letting any other error propagate.
311 # and letting any other error propagate.
312 try:
312 try:
313 super(DocTestCase, self).tearDown()
313 super(DocTestCase, self).tearDown()
314 except AttributeError as exc:
314 except AttributeError as exc:
315 if exc.args[0] != self._result_var:
315 if exc.args[0] != self._result_var:
316 raise
316 raise
317
317
318
318
319 # A simple subclassing of the original with a different class name, so we can
319 # A simple subclassing of the original with a different class name, so we can
320 # distinguish and treat differently IPython examples from pure python ones.
320 # distinguish and treat differently IPython examples from pure python ones.
321 class IPExample(doctest.Example): pass
321 class IPExample(doctest.Example): pass
322
322
323
323
324 class IPExternalExample(doctest.Example):
324 class IPExternalExample(doctest.Example):
325 """Doctest examples to be run in an external process."""
325 """Doctest examples to be run in an external process."""
326
326
327 def __init__(self, source, want, exc_msg=None, lineno=0, indent=0,
327 def __init__(self, source, want, exc_msg=None, lineno=0, indent=0,
328 options=None):
328 options=None):
329 # Parent constructor
329 # Parent constructor
330 doctest.Example.__init__(self,source,want,exc_msg,lineno,indent,options)
330 doctest.Example.__init__(self,source,want,exc_msg,lineno,indent,options)
331
331
332 # An EXTRA newline is needed to prevent pexpect hangs
332 # An EXTRA newline is needed to prevent pexpect hangs
333 self.source += '\n'
333 self.source += '\n'
334
334
335
335
336 class IPDocTestParser(doctest.DocTestParser):
336 class IPDocTestParser(doctest.DocTestParser):
337 """
337 """
338 A class used to parse strings containing doctest examples.
338 A class used to parse strings containing doctest examples.
339
339
340 Note: This is a version modified to properly recognize IPython input and
340 Note: This is a version modified to properly recognize IPython input and
341 convert any IPython examples into valid Python ones.
341 convert any IPython examples into valid Python ones.
342 """
342 """
343 # This regular expression is used to find doctest examples in a
343 # This regular expression is used to find doctest examples in a
344 # string. It defines three groups: `source` is the source code
344 # string. It defines three groups: `source` is the source code
345 # (including leading indentation and prompts); `indent` is the
345 # (including leading indentation and prompts); `indent` is the
346 # indentation of the first (PS1) line of the source code; and
346 # indentation of the first (PS1) line of the source code; and
347 # `want` is the expected output (including leading indentation).
347 # `want` is the expected output (including leading indentation).
348
348
349 # Classic Python prompts or default IPython ones
349 # Classic Python prompts or default IPython ones
350 _PS1_PY = r'>>>'
350 _PS1_PY = r'>>>'
351 _PS2_PY = r'\.\.\.'
351 _PS2_PY = r'\.\.\.'
352
352
353 _PS1_IP = r'In\ \[\d+\]:'
353 _PS1_IP = r'In\ \[\d+\]:'
354 _PS2_IP = r'\ \ \ \.\.\.+:'
354 _PS2_IP = r'\ \ \ \.\.\.+:'
355
355
356 _RE_TPL = r'''
356 _RE_TPL = r'''
357 # Source consists of a PS1 line followed by zero or more PS2 lines.
357 # Source consists of a PS1 line followed by zero or more PS2 lines.
358 (?P<source>
358 (?P<source>
359 (?:^(?P<indent> [ ]*) (?P<ps1> %s) .*) # PS1 line
359 (?:^(?P<indent> [ ]*) (?P<ps1> %s) .*) # PS1 line
360 (?:\n [ ]* (?P<ps2> %s) .*)*) # PS2 lines
360 (?:\n [ ]* (?P<ps2> %s) .*)*) # PS2 lines
361 \n? # a newline
361 \n? # a newline
362 # Want consists of any non-blank lines that do not start with PS1.
362 # Want consists of any non-blank lines that do not start with PS1.
363 (?P<want> (?:(?![ ]*$) # Not a blank line
363 (?P<want> (?:(?![ ]*$) # Not a blank line
364 (?![ ]*%s) # Not a line starting with PS1
364 (?![ ]*%s) # Not a line starting with PS1
365 (?![ ]*%s) # Not a line starting with PS2
365 (?![ ]*%s) # Not a line starting with PS2
366 .*$\n? # But any other line
366 .*$\n? # But any other line
367 )*)
367 )*)
368 '''
368 '''
369
369
370 _EXAMPLE_RE_PY = re.compile( _RE_TPL % (_PS1_PY,_PS2_PY,_PS1_PY,_PS2_PY),
370 _EXAMPLE_RE_PY = re.compile( _RE_TPL % (_PS1_PY,_PS2_PY,_PS1_PY,_PS2_PY),
371 re.MULTILINE | re.VERBOSE)
371 re.MULTILINE | re.VERBOSE)
372
372
373 _EXAMPLE_RE_IP = re.compile( _RE_TPL % (_PS1_IP,_PS2_IP,_PS1_IP,_PS2_IP),
373 _EXAMPLE_RE_IP = re.compile( _RE_TPL % (_PS1_IP,_PS2_IP,_PS1_IP,_PS2_IP),
374 re.MULTILINE | re.VERBOSE)
374 re.MULTILINE | re.VERBOSE)
375
375
376 # Mark a test as being fully random. In this case, we simply append the
376 # Mark a test as being fully random. In this case, we simply append the
377 # random marker ('#random') to each individual example's output. This way
377 # random marker ('#random') to each individual example's output. This way
378 # we don't need to modify any other code.
378 # we don't need to modify any other code.
379 _RANDOM_TEST = re.compile(r'#\s*all-random\s+')
379 _RANDOM_TEST = re.compile(r'#\s*all-random\s+')
380
380
381 # Mark tests to be executed in an external process - currently unsupported.
381 # Mark tests to be executed in an external process - currently unsupported.
382 _EXTERNAL_IP = re.compile(r'#\s*ipdoctest:\s*EXTERNAL')
382 _EXTERNAL_IP = re.compile(r'#\s*ipdoctest:\s*EXTERNAL')
383
383
384 def ip2py(self,source):
384 def ip2py(self,source):
385 """Convert input IPython source into valid Python."""
385 """Convert input IPython source into valid Python."""
386 block = _ip.input_transformer_manager.transform_cell(source)
386 block = _ip.input_transformer_manager.transform_cell(source)
387 if len(block.splitlines()) == 1:
387 if len(block.splitlines()) == 1:
388 return _ip.prefilter(block)
388 return _ip.prefilter(block)
389 else:
389 else:
390 return block
390 return block
391
391
392 def parse(self, string, name='<string>'):
392 def parse(self, string, name='<string>'):
393 """
393 """
394 Divide the given string into examples and intervening text,
394 Divide the given string into examples and intervening text,
395 and return them as a list of alternating Examples and strings.
395 and return them as a list of alternating Examples and strings.
396 Line numbers for the Examples are 0-based. The optional
396 Line numbers for the Examples are 0-based. The optional
397 argument `name` is a name identifying this string, and is only
397 argument `name` is a name identifying this string, and is only
398 used for error messages.
398 used for error messages.
399 """
399 """
400
400
401 #print 'Parse string:\n',string # dbg
401 #print 'Parse string:\n',string # dbg
402
402
403 string = string.expandtabs()
403 string = string.expandtabs()
404 # If all lines begin with the same indentation, then strip it.
404 # If all lines begin with the same indentation, then strip it.
405 min_indent = self._min_indent(string)
405 min_indent = self._min_indent(string)
406 if min_indent > 0:
406 if min_indent > 0:
407 string = '\n'.join([l[min_indent:] for l in string.split('\n')])
407 string = '\n'.join([l[min_indent:] for l in string.split('\n')])
408
408
409 output = []
409 output = []
410 charno, lineno = 0, 0
410 charno, lineno = 0, 0
411
411
412 # We make 'all random' tests by adding the '# random' mark to every
412 # We make 'all random' tests by adding the '# random' mark to every
413 # block of output in the test.
413 # block of output in the test.
414 if self._RANDOM_TEST.search(string):
414 if self._RANDOM_TEST.search(string):
415 random_marker = '\n# random'
415 random_marker = '\n# random'
416 else:
416 else:
417 random_marker = ''
417 random_marker = ''
418
418
419 # Whether to convert the input from ipython to python syntax
419 # Whether to convert the input from ipython to python syntax
420 ip2py = False
420 ip2py = False
421 # Find all doctest examples in the string. First, try them as Python
421 # Find all doctest examples in the string. First, try them as Python
422 # examples, then as IPython ones
422 # examples, then as IPython ones
423 terms = list(self._EXAMPLE_RE_PY.finditer(string))
423 terms = list(self._EXAMPLE_RE_PY.finditer(string))
424 if terms:
424 if terms:
425 # Normal Python example
425 # Normal Python example
426 #print '-'*70 # dbg
426 #print '-'*70 # dbg
427 #print 'PyExample, Source:\n',string # dbg
427 #print 'PyExample, Source:\n',string # dbg
428 #print '-'*70 # dbg
428 #print '-'*70 # dbg
429 Example = doctest.Example
429 Example = doctest.Example
430 else:
430 else:
431 # It's an ipython example. Note that IPExamples are run
431 # It's an ipython example. Note that IPExamples are run
432 # in-process, so their syntax must be turned into valid python.
432 # in-process, so their syntax must be turned into valid python.
433 # IPExternalExamples are run out-of-process (via pexpect) so they
433 # IPExternalExamples are run out-of-process (via pexpect) so they
434 # don't need any filtering (a real ipython will be executing them).
434 # don't need any filtering (a real ipython will be executing them).
435 terms = list(self._EXAMPLE_RE_IP.finditer(string))
435 terms = list(self._EXAMPLE_RE_IP.finditer(string))
436 if self._EXTERNAL_IP.search(string):
436 if self._EXTERNAL_IP.search(string):
437 #print '-'*70 # dbg
437 #print '-'*70 # dbg
438 #print 'IPExternalExample, Source:\n',string # dbg
438 #print 'IPExternalExample, Source:\n',string # dbg
439 #print '-'*70 # dbg
439 #print '-'*70 # dbg
440 Example = IPExternalExample
440 Example = IPExternalExample
441 else:
441 else:
442 #print '-'*70 # dbg
442 #print '-'*70 # dbg
443 #print 'IPExample, Source:\n',string # dbg
443 #print 'IPExample, Source:\n',string # dbg
444 #print '-'*70 # dbg
444 #print '-'*70 # dbg
445 Example = IPExample
445 Example = IPExample
446 ip2py = True
446 ip2py = True
447
447
448 for m in terms:
448 for m in terms:
449 # Add the pre-example text to `output`.
449 # Add the pre-example text to `output`.
450 output.append(string[charno:m.start()])
450 output.append(string[charno:m.start()])
451 # Update lineno (lines before this example)
451 # Update lineno (lines before this example)
452 lineno += string.count('\n', charno, m.start())
452 lineno += string.count('\n', charno, m.start())
453 # Extract info from the regexp match.
453 # Extract info from the regexp match.
454 (source, options, want, exc_msg) = \
454 (source, options, want, exc_msg) = \
455 self._parse_example(m, name, lineno,ip2py)
455 self._parse_example(m, name, lineno,ip2py)
456
456
457 # Append the random-output marker (it defaults to empty in most
457 # Append the random-output marker (it defaults to empty in most
458 # cases, it's only non-empty for 'all-random' tests):
458 # cases, it's only non-empty for 'all-random' tests):
459 want += random_marker
459 want += random_marker
460
460
461 if Example is IPExternalExample:
461 if Example is IPExternalExample:
462 options[doctest.NORMALIZE_WHITESPACE] = True
462 options[doctest.NORMALIZE_WHITESPACE] = True
463 want += '\n'
463 want += '\n'
464
464
465 # Create an Example, and add it to the list.
465 # Create an Example, and add it to the list.
466 if not self._IS_BLANK_OR_COMMENT(source):
466 if not self._IS_BLANK_OR_COMMENT(source):
467 output.append(Example(source, want, exc_msg,
467 output.append(Example(source, want, exc_msg,
468 lineno=lineno,
468 lineno=lineno,
469 indent=min_indent+len(m.group('indent')),
469 indent=min_indent+len(m.group('indent')),
470 options=options))
470 options=options))
471 # Update lineno (lines inside this example)
471 # Update lineno (lines inside this example)
472 lineno += string.count('\n', m.start(), m.end())
472 lineno += string.count('\n', m.start(), m.end())
473 # Update charno.
473 # Update charno.
474 charno = m.end()
474 charno = m.end()
475 # Add any remaining post-example text to `output`.
475 # Add any remaining post-example text to `output`.
476 output.append(string[charno:])
476 output.append(string[charno:])
477 return output
477 return output
478
478
479 def _parse_example(self, m, name, lineno,ip2py=False):
479 def _parse_example(self, m, name, lineno,ip2py=False):
480 """
480 """
481 Given a regular expression match from `_EXAMPLE_RE` (`m`),
481 Given a regular expression match from `_EXAMPLE_RE` (`m`),
482 return a pair `(source, want)`, where `source` is the matched
482 return a pair `(source, want)`, where `source` is the matched
483 example's source code (with prompts and indentation stripped);
483 example's source code (with prompts and indentation stripped);
484 and `want` is the example's expected output (with indentation
484 and `want` is the example's expected output (with indentation
485 stripped).
485 stripped).
486
486
487 `name` is the string's name, and `lineno` is the line number
487 `name` is the string's name, and `lineno` is the line number
488 where the example starts; both are used for error messages.
488 where the example starts; both are used for error messages.
489
489
490 Optional:
490 Optional:
491 `ip2py`: if true, filter the input via IPython to convert the syntax
491 `ip2py`: if true, filter the input via IPython to convert the syntax
492 into valid python.
492 into valid python.
493 """
493 """
494
494
495 # Get the example's indentation level.
495 # Get the example's indentation level.
496 indent = len(m.group('indent'))
496 indent = len(m.group('indent'))
497
497
498 # Divide source into lines; check that they're properly
498 # Divide source into lines; check that they're properly
499 # indented; and then strip their indentation & prompts.
499 # indented; and then strip their indentation & prompts.
500 source_lines = m.group('source').split('\n')
500 source_lines = m.group('source').split('\n')
501
501
502 # We're using variable-length input prompts
502 # We're using variable-length input prompts
503 ps1 = m.group('ps1')
503 ps1 = m.group('ps1')
504 ps2 = m.group('ps2')
504 ps2 = m.group('ps2')
505 ps1_len = len(ps1)
505 ps1_len = len(ps1)
506
506
507 self._check_prompt_blank(source_lines, indent, name, lineno,ps1_len)
507 self._check_prompt_blank(source_lines, indent, name, lineno,ps1_len)
508 if ps2:
508 if ps2:
509 self._check_prefix(source_lines[1:], ' '*indent + ps2, name, lineno)
509 self._check_prefix(source_lines[1:], ' '*indent + ps2, name, lineno)
510
510
511 source = '\n'.join([sl[indent+ps1_len+1:] for sl in source_lines])
511 source = '\n'.join([sl[indent+ps1_len+1:] for sl in source_lines])
512
512
513 if ip2py:
513 if ip2py:
514 # Convert source input from IPython into valid Python syntax
514 # Convert source input from IPython into valid Python syntax
515 source = self.ip2py(source)
515 source = self.ip2py(source)
516
516
517 # Divide want into lines; check that it's properly indented; and
517 # Divide want into lines; check that it's properly indented; and
518 # then strip the indentation. Spaces before the last newline should
518 # then strip the indentation. Spaces before the last newline should
519 # be preserved, so plain rstrip() isn't good enough.
519 # be preserved, so plain rstrip() isn't good enough.
520 want = m.group('want')
520 want = m.group('want')
521 want_lines = want.split('\n')
521 want_lines = want.split('\n')
522 if len(want_lines) > 1 and re.match(r' *$', want_lines[-1]):
522 if len(want_lines) > 1 and re.match(r' *$', want_lines[-1]):
523 del want_lines[-1] # forget final newline & spaces after it
523 del want_lines[-1] # forget final newline & spaces after it
524 self._check_prefix(want_lines, ' '*indent, name,
524 self._check_prefix(want_lines, ' '*indent, name,
525 lineno + len(source_lines))
525 lineno + len(source_lines))
526
526
527 # Remove ipython output prompt that might be present in the first line
527 # Remove ipython output prompt that might be present in the first line
528 want_lines[0] = re.sub(r'Out\[\d+\]: \s*?\n?','',want_lines[0])
528 want_lines[0] = re.sub(r'Out\[\d+\]: \s*?\n?','',want_lines[0])
529
529
530 want = '\n'.join([wl[indent:] for wl in want_lines])
530 want = '\n'.join([wl[indent:] for wl in want_lines])
531
531
532 # If `want` contains a traceback message, then extract it.
532 # If `want` contains a traceback message, then extract it.
533 m = self._EXCEPTION_RE.match(want)
533 m = self._EXCEPTION_RE.match(want)
534 if m:
534 if m:
535 exc_msg = m.group('msg')
535 exc_msg = m.group('msg')
536 else:
536 else:
537 exc_msg = None
537 exc_msg = None
538
538
539 # Extract options from the source.
539 # Extract options from the source.
540 options = self._find_options(source, name, lineno)
540 options = self._find_options(source, name, lineno)
541
541
542 return source, options, want, exc_msg
542 return source, options, want, exc_msg
543
543
544 def _check_prompt_blank(self, lines, indent, name, lineno, ps1_len):
544 def _check_prompt_blank(self, lines, indent, name, lineno, ps1_len):
545 """
545 """
546 Given the lines of a source string (including prompts and
546 Given the lines of a source string (including prompts and
547 leading indentation), check to make sure that every prompt is
547 leading indentation), check to make sure that every prompt is
548 followed by a space character. If any line is not followed by
548 followed by a space character. If any line is not followed by
549 a space character, then raise ValueError.
549 a space character, then raise ValueError.
550
550
551 Note: IPython-modified version which takes the input prompt length as a
551 Note: IPython-modified version which takes the input prompt length as a
552 parameter, so that prompts of variable length can be dealt with.
552 parameter, so that prompts of variable length can be dealt with.
553 """
553 """
554 space_idx = indent+ps1_len
554 space_idx = indent+ps1_len
555 min_len = space_idx+1
555 min_len = space_idx+1
556 for i, line in enumerate(lines):
556 for i, line in enumerate(lines):
557 if len(line) >= min_len and line[space_idx] != ' ':
557 if len(line) >= min_len and line[space_idx] != ' ':
558 raise ValueError('line %r of the docstring for %s '
558 raise ValueError('line %r of the docstring for %s '
559 'lacks blank after %s: %r' %
559 'lacks blank after %s: %r' %
560 (lineno+i+1, name,
560 (lineno+i+1, name,
561 line[indent:space_idx], line))
561 line[indent:space_idx], line))
562
562
563
563
564 SKIP = doctest.register_optionflag('SKIP')
564 SKIP = doctest.register_optionflag('SKIP')
565
565
566
566
567 class IPDocTestRunner(doctest.DocTestRunner,object):
567 class IPDocTestRunner(doctest.DocTestRunner,object):
568 """Test runner that synchronizes the IPython namespace with test globals.
568 """Test runner that synchronizes the IPython namespace with test globals.
569 """
569 """
570
570
571 def run(self, test, compileflags=None, out=None, clear_globs=True):
571 def run(self, test, compileflags=None, out=None, clear_globs=True):
572
572
573 # Hack: ipython needs access to the execution context of the example,
573 # Hack: ipython needs access to the execution context of the example,
574 # so that it can propagate user variables loaded by %run into
574 # so that it can propagate user variables loaded by %run into
575 # test.globs. We put them here into our modified %run as a function
575 # test.globs. We put them here into our modified %run as a function
576 # attribute. Our new %run will then only make the namespace update
576 # attribute. Our new %run will then only make the namespace update
577 # when called (rather than unconconditionally updating test.globs here
577 # when called (rather than unconditionally updating test.globs here
578 # for all examples, most of which won't be calling %run anyway).
578 # for all examples, most of which won't be calling %run anyway).
579 #_ip._ipdoctest_test_globs = test.globs
579 #_ip._ipdoctest_test_globs = test.globs
580 #_ip._ipdoctest_test_filename = test.filename
580 #_ip._ipdoctest_test_filename = test.filename
581
581
582 test.globs.update(_ip.user_ns)
582 test.globs.update(_ip.user_ns)
583
583
584 # Override terminal size to standardise traceback format
584 # Override terminal size to standardise traceback format
585 with modified_env({'COLUMNS': '80', 'LINES': '24'}):
585 with modified_env({'COLUMNS': '80', 'LINES': '24'}):
586 return super(IPDocTestRunner,self).run(test,
586 return super(IPDocTestRunner,self).run(test,
587 compileflags,out,clear_globs)
587 compileflags,out,clear_globs)
588
588
589
589
590 class DocFileCase(doctest.DocFileCase):
590 class DocFileCase(doctest.DocFileCase):
591 """Overrides to provide filename
591 """Overrides to provide filename
592 """
592 """
593 def address(self):
593 def address(self):
594 return (self._dt_test.filename, None, None)
594 return (self._dt_test.filename, None, None)
595
595
596
596
597 class ExtensionDoctest(doctests.Doctest):
597 class ExtensionDoctest(doctests.Doctest):
598 """Nose Plugin that supports doctests in extension modules.
598 """Nose Plugin that supports doctests in extension modules.
599 """
599 """
600 name = 'extdoctest' # call nosetests with --with-extdoctest
600 name = 'extdoctest' # call nosetests with --with-extdoctest
601 enabled = True
601 enabled = True
602
602
603 def options(self, parser, env=os.environ):
603 def options(self, parser, env=os.environ):
604 Plugin.options(self, parser, env)
604 Plugin.options(self, parser, env)
605 parser.add_option('--doctest-tests', action='store_true',
605 parser.add_option('--doctest-tests', action='store_true',
606 dest='doctest_tests',
606 dest='doctest_tests',
607 default=env.get('NOSE_DOCTEST_TESTS',True),
607 default=env.get('NOSE_DOCTEST_TESTS',True),
608 help="Also look for doctests in test modules. "
608 help="Also look for doctests in test modules. "
609 "Note that classes, methods and functions should "
609 "Note that classes, methods and functions should "
610 "have either doctests or non-doctest tests, "
610 "have either doctests or non-doctest tests, "
611 "not both. [NOSE_DOCTEST_TESTS]")
611 "not both. [NOSE_DOCTEST_TESTS]")
612 parser.add_option('--doctest-extension', action="append",
612 parser.add_option('--doctest-extension', action="append",
613 dest="doctestExtension",
613 dest="doctestExtension",
614 help="Also look for doctests in files with "
614 help="Also look for doctests in files with "
615 "this extension [NOSE_DOCTEST_EXTENSION]")
615 "this extension [NOSE_DOCTEST_EXTENSION]")
616 # Set the default as a list, if given in env; otherwise
616 # Set the default as a list, if given in env; otherwise
617 # an additional value set on the command line will cause
617 # an additional value set on the command line will cause
618 # an error.
618 # an error.
619 env_setting = env.get('NOSE_DOCTEST_EXTENSION')
619 env_setting = env.get('NOSE_DOCTEST_EXTENSION')
620 if env_setting is not None:
620 if env_setting is not None:
621 parser.set_defaults(doctestExtension=tolist(env_setting))
621 parser.set_defaults(doctestExtension=tolist(env_setting))
622
622
623
623
624 def configure(self, options, config):
624 def configure(self, options, config):
625 Plugin.configure(self, options, config)
625 Plugin.configure(self, options, config)
626 # Pull standard doctest plugin out of config; we will do doctesting
626 # Pull standard doctest plugin out of config; we will do doctesting
627 config.plugins.plugins = [p for p in config.plugins.plugins
627 config.plugins.plugins = [p for p in config.plugins.plugins
628 if p.name != 'doctest']
628 if p.name != 'doctest']
629 self.doctest_tests = options.doctest_tests
629 self.doctest_tests = options.doctest_tests
630 self.extension = tolist(options.doctestExtension)
630 self.extension = tolist(options.doctestExtension)
631
631
632 self.parser = doctest.DocTestParser()
632 self.parser = doctest.DocTestParser()
633 self.finder = DocTestFinder()
633 self.finder = DocTestFinder()
634 self.checker = IPDoctestOutputChecker()
634 self.checker = IPDoctestOutputChecker()
635 self.globs = None
635 self.globs = None
636 self.extraglobs = None
636 self.extraglobs = None
637
637
638
638
639 def loadTestsFromExtensionModule(self,filename):
639 def loadTestsFromExtensionModule(self,filename):
640 bpath,mod = os.path.split(filename)
640 bpath,mod = os.path.split(filename)
641 modname = os.path.splitext(mod)[0]
641 modname = os.path.splitext(mod)[0]
642 try:
642 try:
643 sys.path.append(bpath)
643 sys.path.append(bpath)
644 module = import_module(modname)
644 module = import_module(modname)
645 tests = list(self.loadTestsFromModule(module))
645 tests = list(self.loadTestsFromModule(module))
646 finally:
646 finally:
647 sys.path.pop()
647 sys.path.pop()
648 return tests
648 return tests
649
649
650 # NOTE: the method below is almost a copy of the original one in nose, with
650 # NOTE: the method below is almost a copy of the original one in nose, with
651 # a few modifications to control output checking.
651 # a few modifications to control output checking.
652
652
653 def loadTestsFromModule(self, module):
653 def loadTestsFromModule(self, module):
654 #print '*** ipdoctest - lTM',module # dbg
654 #print '*** ipdoctest - lTM',module # dbg
655
655
656 if not self.matches(module.__name__):
656 if not self.matches(module.__name__):
657 log.debug("Doctest doesn't want module %s", module)
657 log.debug("Doctest doesn't want module %s", module)
658 return
658 return
659
659
660 tests = self.finder.find(module,globs=self.globs,
660 tests = self.finder.find(module,globs=self.globs,
661 extraglobs=self.extraglobs)
661 extraglobs=self.extraglobs)
662 if not tests:
662 if not tests:
663 return
663 return
664
664
665 # always use whitespace and ellipsis options
665 # always use whitespace and ellipsis options
666 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
666 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
667
667
668 tests.sort()
668 tests.sort()
669 module_file = module.__file__
669 module_file = module.__file__
670 if module_file[-4:] in ('.pyc', '.pyo'):
670 if module_file[-4:] in ('.pyc', '.pyo'):
671 module_file = module_file[:-1]
671 module_file = module_file[:-1]
672 for test in tests:
672 for test in tests:
673 if not test.examples:
673 if not test.examples:
674 continue
674 continue
675 if not test.filename:
675 if not test.filename:
676 test.filename = module_file
676 test.filename = module_file
677
677
678 yield DocTestCase(test,
678 yield DocTestCase(test,
679 optionflags=optionflags,
679 optionflags=optionflags,
680 checker=self.checker)
680 checker=self.checker)
681
681
682
682
683 def loadTestsFromFile(self, filename):
683 def loadTestsFromFile(self, filename):
684 #print "ipdoctest - from file", filename # dbg
684 #print "ipdoctest - from file", filename # dbg
685 if is_extension_module(filename):
685 if is_extension_module(filename):
686 for t in self.loadTestsFromExtensionModule(filename):
686 for t in self.loadTestsFromExtensionModule(filename):
687 yield t
687 yield t
688 else:
688 else:
689 if self.extension and anyp(filename.endswith, self.extension):
689 if self.extension and anyp(filename.endswith, self.extension):
690 name = os.path.basename(filename)
690 name = os.path.basename(filename)
691 with open(filename) as dh:
691 with open(filename) as dh:
692 doc = dh.read()
692 doc = dh.read()
693 test = self.parser.get_doctest(
693 test = self.parser.get_doctest(
694 doc, globs={'__file__': filename}, name=name,
694 doc, globs={'__file__': filename}, name=name,
695 filename=filename, lineno=0)
695 filename=filename, lineno=0)
696 if test.examples:
696 if test.examples:
697 #print 'FileCase:',test.examples # dbg
697 #print 'FileCase:',test.examples # dbg
698 yield DocFileCase(test)
698 yield DocFileCase(test)
699 else:
699 else:
700 yield False # no tests to load
700 yield False # no tests to load
701
701
702
702
703 class IPythonDoctest(ExtensionDoctest):
703 class IPythonDoctest(ExtensionDoctest):
704 """Nose Plugin that supports doctests in extension modules.
704 """Nose Plugin that supports doctests in extension modules.
705 """
705 """
706 name = 'ipdoctest' # call nosetests with --with-ipdoctest
706 name = 'ipdoctest' # call nosetests with --with-ipdoctest
707 enabled = True
707 enabled = True
708
708
709 def makeTest(self, obj, parent):
709 def makeTest(self, obj, parent):
710 """Look for doctests in the given object, which will be a
710 """Look for doctests in the given object, which will be a
711 function, method or class.
711 function, method or class.
712 """
712 """
713 #print 'Plugin analyzing:', obj, parent # dbg
713 #print 'Plugin analyzing:', obj, parent # dbg
714 # always use whitespace and ellipsis options
714 # always use whitespace and ellipsis options
715 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
715 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
716
716
717 doctests = self.finder.find(obj, module=getmodule(parent))
717 doctests = self.finder.find(obj, module=getmodule(parent))
718 if doctests:
718 if doctests:
719 for test in doctests:
719 for test in doctests:
720 if len(test.examples) == 0:
720 if len(test.examples) == 0:
721 continue
721 continue
722
722
723 yield DocTestCase(test, obj=obj,
723 yield DocTestCase(test, obj=obj,
724 optionflags=optionflags,
724 optionflags=optionflags,
725 checker=self.checker)
725 checker=self.checker)
726
726
727 def options(self, parser, env=os.environ):
727 def options(self, parser, env=os.environ):
728 #print "Options for nose plugin:", self.name # dbg
728 #print "Options for nose plugin:", self.name # dbg
729 Plugin.options(self, parser, env)
729 Plugin.options(self, parser, env)
730 parser.add_option('--ipdoctest-tests', action='store_true',
730 parser.add_option('--ipdoctest-tests', action='store_true',
731 dest='ipdoctest_tests',
731 dest='ipdoctest_tests',
732 default=env.get('NOSE_IPDOCTEST_TESTS',True),
732 default=env.get('NOSE_IPDOCTEST_TESTS',True),
733 help="Also look for doctests in test modules. "
733 help="Also look for doctests in test modules. "
734 "Note that classes, methods and functions should "
734 "Note that classes, methods and functions should "
735 "have either doctests or non-doctest tests, "
735 "have either doctests or non-doctest tests, "
736 "not both. [NOSE_IPDOCTEST_TESTS]")
736 "not both. [NOSE_IPDOCTEST_TESTS]")
737 parser.add_option('--ipdoctest-extension', action="append",
737 parser.add_option('--ipdoctest-extension', action="append",
738 dest="ipdoctest_extension",
738 dest="ipdoctest_extension",
739 help="Also look for doctests in files with "
739 help="Also look for doctests in files with "
740 "this extension [NOSE_IPDOCTEST_EXTENSION]")
740 "this extension [NOSE_IPDOCTEST_EXTENSION]")
741 # Set the default as a list, if given in env; otherwise
741 # Set the default as a list, if given in env; otherwise
742 # an additional value set on the command line will cause
742 # an additional value set on the command line will cause
743 # an error.
743 # an error.
744 env_setting = env.get('NOSE_IPDOCTEST_EXTENSION')
744 env_setting = env.get('NOSE_IPDOCTEST_EXTENSION')
745 if env_setting is not None:
745 if env_setting is not None:
746 parser.set_defaults(ipdoctest_extension=tolist(env_setting))
746 parser.set_defaults(ipdoctest_extension=tolist(env_setting))
747
747
748 def configure(self, options, config):
748 def configure(self, options, config):
749 #print "Configuring nose plugin:", self.name # dbg
749 #print "Configuring nose plugin:", self.name # dbg
750 Plugin.configure(self, options, config)
750 Plugin.configure(self, options, config)
751 # Pull standard doctest plugin out of config; we will do doctesting
751 # Pull standard doctest plugin out of config; we will do doctesting
752 config.plugins.plugins = [p for p in config.plugins.plugins
752 config.plugins.plugins = [p for p in config.plugins.plugins
753 if p.name != 'doctest']
753 if p.name != 'doctest']
754 self.doctest_tests = options.ipdoctest_tests
754 self.doctest_tests = options.ipdoctest_tests
755 self.extension = tolist(options.ipdoctest_extension)
755 self.extension = tolist(options.ipdoctest_extension)
756
756
757 self.parser = IPDocTestParser()
757 self.parser = IPDocTestParser()
758 self.finder = DocTestFinder(parser=self.parser)
758 self.finder = DocTestFinder(parser=self.parser)
759 self.checker = IPDoctestOutputChecker()
759 self.checker = IPDoctestOutputChecker()
760 self.globs = None
760 self.globs = None
761 self.extraglobs = None
761 self.extraglobs = None
@@ -1,765 +1,765 b''
1 =============
1 =============
2 0.11 Series
2 0.11 Series
3 =============
3 =============
4
4
5 Release 0.11
5 Release 0.11
6 ============
6 ============
7
7
8 IPython 0.11 is a *major* overhaul of IPython, two years in the making. Most
8 IPython 0.11 is a *major* overhaul of IPython, two years in the making. Most
9 of the code base has been rewritten or at least reorganized, breaking backward
9 of the code base has been rewritten or at least reorganized, breaking backward
10 compatibility with several APIs in previous versions. It is the first major
10 compatibility with several APIs in previous versions. It is the first major
11 release in two years, and probably the most significant change to IPython since
11 release in two years, and probably the most significant change to IPython since
12 its inception. We plan to have a relatively quick succession of releases, as
12 its inception. We plan to have a relatively quick succession of releases, as
13 people discover new bugs and regressions. Once we iron out any significant
13 people discover new bugs and regressions. Once we iron out any significant
14 bugs in this process and settle down the new APIs, this series will become
14 bugs in this process and settle down the new APIs, this series will become
15 IPython 1.0. We encourage feedback now on the core APIs, which we hope to
15 IPython 1.0. We encourage feedback now on the core APIs, which we hope to
16 maintain stable during the 1.0 series.
16 maintain stable during the 1.0 series.
17
17
18 Since the internal APIs have changed so much, projects using IPython as a
18 Since the internal APIs have changed so much, projects using IPython as a
19 library (as opposed to end-users of the application) are the most likely to
19 library (as opposed to end-users of the application) are the most likely to
20 encounter regressions or changes that break their existing use patterns. We
20 encounter regressions or changes that break their existing use patterns. We
21 will make every effort to provide updated versions of the APIs to facilitate
21 will make every effort to provide updated versions of the APIs to facilitate
22 the transition, and we encourage you to contact us on the `development mailing
22 the transition, and we encourage you to contact us on the `development mailing
23 list`__ with questions and feedback.
23 list`__ with questions and feedback.
24
24
25 .. __: http://mail.scipy.org/mailman/listinfo/ipython-dev
25 .. __: http://mail.scipy.org/mailman/listinfo/ipython-dev
26
26
27 Chris Fonnesbeck recently wrote an `excellent post`__ that highlights some of
27 Chris Fonnesbeck recently wrote an `excellent post`__ that highlights some of
28 our major new features, with examples and screenshots. We encourage you to
28 our major new features, with examples and screenshots. We encourage you to
29 read it as it provides an illustrated, high-level overview complementing the
29 read it as it provides an illustrated, high-level overview complementing the
30 detailed feature breakdown in this document.
30 detailed feature breakdown in this document.
31
31
32 .. __: http://stronginference.com/post/innovations-in-ipython
32 .. __: http://stronginference.com/post/innovations-in-ipython
33
33
34 A quick summary of the major changes (see below for details):
34 A quick summary of the major changes (see below for details):
35
35
36 * **Standalone Qt console**: a new rich console has been added to IPython,
36 * **Standalone Qt console**: a new rich console has been added to IPython,
37 started with `ipython qtconsole`. In this application we have tried to
37 started with `ipython qtconsole`. In this application we have tried to
38 retain the feel of a terminal for fast and efficient workflows, while adding
38 retain the feel of a terminal for fast and efficient workflows, while adding
39 many features that a line-oriented terminal simply can not support, such as
39 many features that a line-oriented terminal simply can not support, such as
40 inline figures, full multiline editing with syntax highlighting, graphical
40 inline figures, full multiline editing with syntax highlighting, graphical
41 tooltips for function calls and much more. This development was sponsored by
41 tooltips for function calls and much more. This development was sponsored by
42 `Enthought Inc.`__. See :ref:`below <qtconsole_011>` for details.
42 `Enthought Inc.`__. See :ref:`below <qtconsole_011>` for details.
43
43
44 .. __: http://enthought.com
44 .. __: http://enthought.com
45
45
46 * **High-level parallel computing with ZeroMQ**. Using the same architecture
46 * **High-level parallel computing with ZeroMQ**. Using the same architecture
47 that our Qt console is based on, we have completely rewritten our high-level
47 that our Qt console is based on, we have completely rewritten our high-level
48 parallel computing machinery that in prior versions used the Twisted
48 parallel computing machinery that in prior versions used the Twisted
49 networking framework. While this change will require users to update their
49 networking framework. While this change will require users to update their
50 codes, the improvements in performance, memory control and internal
50 codes, the improvements in performance, memory control and internal
51 consistency across our codebase convinced us it was a price worth paying. We
51 consistency across our codebase convinced us it was a price worth paying. We
52 have tried to explain how to best proceed with this update, and will be happy
52 have tried to explain how to best proceed with this update, and will be happy
53 to answer questions that may arise. A full tutorial describing these
53 to answer questions that may arise. A full tutorial describing these
54 features `was presented at SciPy'11`__, more details :ref:`below
54 features `was presented at SciPy'11`__, more details :ref:`below
55 <parallel_011>`.
55 <parallel_011>`.
56
56
57 .. __: http://minrk.github.com/scipy-tutorial-2011
57 .. __: http://minrk.github.com/scipy-tutorial-2011
58
58
59 * **New model for GUI/plotting support in the terminal**. Now instead of the
59 * **New model for GUI/plotting support in the terminal**. Now instead of the
60 various `-Xthread` flags we had before, GUI support is provided without the
60 various `-Xthread` flags we had before, GUI support is provided without the
61 use of any threads, by directly integrating GUI event loops with Python's
61 use of any threads, by directly integrating GUI event loops with Python's
62 `PyOS_InputHook` API. A new command-line flag `--gui` controls GUI support,
62 `PyOS_InputHook` API. A new command-line flag `--gui` controls GUI support,
63 and it can also be enabled after IPython startup via the new `%gui` magic.
63 and it can also be enabled after IPython startup via the new `%gui` magic.
64 This requires some changes if you want to execute GUI-using scripts inside
64 This requires some changes if you want to execute GUI-using scripts inside
65 IPython, see :ref:`the GUI support section <gui_support>` for more details.
65 IPython, see :ref:`the GUI support section <gui_support>` for more details.
66
66
67 * **A two-process architecture.** The Qt console is the first use of a new
67 * **A two-process architecture.** The Qt console is the first use of a new
68 model that splits IPython between a kernel process where code is executed and
68 model that splits IPython between a kernel process where code is executed and
69 a client that handles user interaction. We plan on also providing terminal
69 a client that handles user interaction. We plan on also providing terminal
70 and web-browser based clients using this infrastructure in future releases.
70 and web-browser based clients using this infrastructure in future releases.
71 This model allows multiple clients to interact with an IPython process
71 This model allows multiple clients to interact with an IPython process
72 through a :ref:`well-documented messaging protocol <messaging>` using the
72 through a :ref:`well-documented messaging protocol <messaging>` using the
73 ZeroMQ networking library.
73 ZeroMQ networking library.
74
74
75 * **Refactoring.** the entire codebase has been refactored, in order to make it
75 * **Refactoring.** the entire codebase has been refactored, in order to make it
76 more modular and easier to contribute to. IPython has traditionally been a
76 more modular and easier to contribute to. IPython has traditionally been a
77 hard project to participate because the old codebase was very monolithic. We
77 hard project to participate because the old codebase was very monolithic. We
78 hope this (ongoing) restructuring will make it easier for new developers to
78 hope this (ongoing) restructuring will make it easier for new developers to
79 join us.
79 join us.
80
80
81 * **Vim integration**. Vim can be configured to seamlessly control an IPython
81 * **Vim integration**. Vim can be configured to seamlessly control an IPython
82 kernel, see the files in :file:`docs/examples/vim` for the full details.
82 kernel, see the files in :file:`docs/examples/vim` for the full details.
83 This work was done by Paul Ivanov, who prepared a nice `video
83 This work was done by Paul Ivanov, who prepared a nice `video
84 demonstration`__ of the features it provides.
84 demonstration`__ of the features it provides.
85
85
86 .. __: http://pirsquared.org/blog/2011/07/28/vim-ipython/
86 .. __: http://pirsquared.org/blog/2011/07/28/vim-ipython/
87
87
88 * **Integration into Microsoft Visual Studio**. Thanks to the work of the
88 * **Integration into Microsoft Visual Studio**. Thanks to the work of the
89 Microsoft `Python Tools for Visual Studio`__ team, this version of IPython
89 Microsoft `Python Tools for Visual Studio`__ team, this version of IPython
90 has been integrated into Microsoft Visual Studio's Python tools open source
90 has been integrated into Microsoft Visual Studio's Python tools open source
91 plug-in. `Details below`_
91 plug-in. `Details below`_
92
92
93 .. __: http://pytools.codeplex.com
93 .. __: http://pytools.codeplex.com
94 .. _details below: ms_visual_studio_011_
94 .. _details below: ms_visual_studio_011_
95
95
96 * **Improved unicode support**. We closed many bugs related to unicode input.
96 * **Improved unicode support**. We closed many bugs related to unicode input.
97
97
98 * **Python 3**. IPython now runs on Python 3.x. See :ref:`python3_011` for
98 * **Python 3**. IPython now runs on Python 3.x. See :ref:`python3_011` for
99 details.
99 details.
100
100
101 * **New profile model**. Profiles are now directories that contain all relevant
101 * **New profile model**. Profiles are now directories that contain all relevant
102 information for that session, and thus better isolate IPython use-cases.
102 information for that session, and thus better isolate IPython use-cases.
103
103
104 * **SQLite storage for history**. All history is now stored in a SQLite
104 * **SQLite storage for history**. All history is now stored in a SQLite
105 database, providing support for multiple simultaneous sessions that won't
105 database, providing support for multiple simultaneous sessions that won't
106 clobber each other as well as the ability to perform queries on all stored
106 clobber each other as well as the ability to perform queries on all stored
107 data.
107 data.
108
108
109 * **New configuration system**. All parts of IPython are now configured via a
109 * **New configuration system**. All parts of IPython are now configured via a
110 mechanism inspired by the Enthought Traits library. Any configurable element
110 mechanism inspired by the Enthought Traits library. Any configurable element
111 can have its attributes set either via files that now use real Python syntax
111 can have its attributes set either via files that now use real Python syntax
112 or from the command-line.
112 or from the command-line.
113
113
114 * **Pasting of code with prompts**. IPython now intelligently strips out input
114 * **Pasting of code with prompts**. IPython now intelligently strips out input
115 prompts , be they plain Python ones (``>>>`` and ``...``) or IPython ones
115 prompts , be they plain Python ones (``>>>`` and ``...``) or IPython ones
116 (``In [N]:`` and ``...:``). More details :ref:`here <pasting_with_prompts>`.
116 (``In [N]:`` and ``...:``). More details :ref:`here <pasting_with_prompts>`.
117
117
118
118
119 Authors and support
119 Authors and support
120 -------------------
120 -------------------
121
121
122 Over 60 separate authors have contributed to this release, see :ref:`below
122 Over 60 separate authors have contributed to this release, see :ref:`below
123 <credits_011>` for a full list. In particular, we want to highlight the
123 <credits_011>` for a full list. In particular, we want to highlight the
124 extremely active participation of two new core team members: Evan Patterson
124 extremely active participation of two new core team members: Evan Patterson
125 implemented the Qt console, and Thomas Kluyver started with our Python 3 port
125 implemented the Qt console, and Thomas Kluyver started with our Python 3 port
126 and by now has made major contributions to just about every area of IPython.
126 and by now has made major contributions to just about every area of IPython.
127
127
128 We are also grateful for the support we have received during this development
128 We are also grateful for the support we have received during this development
129 cycle from several institutions:
129 cycle from several institutions:
130
130
131 - `Enthought Inc`__ funded the development of our new Qt console, an effort that
131 - `Enthought Inc`__ funded the development of our new Qt console, an effort that
132 required developing major pieces of underlying infrastructure, which now
132 required developing major pieces of underlying infrastructure, which now
133 power not only the Qt console but also our new parallel machinery. We'd like
133 power not only the Qt console but also our new parallel machinery. We'd like
134 to thank Eric Jones and Travis Oliphant for their support, as well as Ilan
134 to thank Eric Jones and Travis Oliphant for their support, as well as Ilan
135 Schnell for his tireless work integrating and testing IPython in the
135 Schnell for his tireless work integrating and testing IPython in the
136 `Enthought Python Distribution`_.
136 `Enthought Python Distribution`_.
137
137
138 .. __: http://enthought.com
138 .. __: http://enthought.com
139 .. _Enthought Python Distribution: http://www.enthought.com/products/epd.php
139 .. _Enthought Python Distribution: http://www.enthought.com/products/epd.php
140
140
141 - Nipy/NIH: funding via the `NiPy project`__ (NIH grant 5R01MH081909-02) helped
141 - Nipy/NIH: funding via the `NiPy project`__ (NIH grant 5R01MH081909-02) helped
142 us jumpstart the development of this series by restructuring the entire
142 us jumpstart the development of this series by restructuring the entire
143 codebase two years ago in a way that would make modular development and
143 codebase two years ago in a way that would make modular development and
144 testing more approachable. Without this initial groundwork, all the new
144 testing more approachable. Without this initial groundwork, all the new
145 features we have added would have been impossible to develop.
145 features we have added would have been impossible to develop.
146
146
147 .. __: http://nipy.org
147 .. __: http://nipy.org
148
148
149 - Sage/NSF: funding via the grant `Sage: Unifying Mathematical Software for
149 - Sage/NSF: funding via the grant `Sage: Unifying Mathematical Software for
150 Scientists, Engineers, and Mathematicians`__ (NSF grant DMS-1015114)
150 Scientists, Engineers, and Mathematicians`__ (NSF grant DMS-1015114)
151 supported a meeting in spring 2011 of several of the core IPython developers
151 supported a meeting in spring 2011 of several of the core IPython developers
152 where major progress was made integrating the last key pieces leading to this
152 where major progress was made integrating the last key pieces leading to this
153 release.
153 release.
154
154
155 .. __: http://modular.math.washington.edu/grants/compmath09
155 .. __: http://modular.math.washington.edu/grants/compmath09
156
156
157 - Microsoft's team working on `Python Tools for Visual Studio`__ developed the
157 - Microsoft's team working on `Python Tools for Visual Studio`__ developed the
158 integraton of IPython into the Python plugin for Visual Studio 2010.
158 integraton of IPython into the Python plugin for Visual Studio 2010.
159
159
160 .. __: http://pytools.codeplex.com
160 .. __: http://pytools.codeplex.com
161
161
162 - Google Summer of Code: in 2010, we had two students developing prototypes of
162 - Google Summer of Code: in 2010, we had two students developing prototypes of
163 the new machinery that is now maturing in this release: `Omar Zapata`_ and
163 the new machinery that is now maturing in this release: `Omar Zapata`_ and
164 `Gerardo GutiΓ©rrez`_.
164 `Gerardo GutiΓ©rrez`_.
165
165
166 .. _Omar Zapata: http://ipythonzmq.blogspot.com/2010/08/ipython-zmq-status.html
166 .. _Omar Zapata: http://ipythonzmq.blogspot.com/2010/08/ipython-zmq-status.html
167 .. _Gerardo GutiΓ©rrez: http://ipythonqt.blogspot.com/2010/04/ipython-qt-interface-gsoc-2010-proposal.html>
167 .. _Gerardo GutiΓ©rrez: http://ipythonqt.blogspot.com/2010/04/ipython-qt-interface-gsoc-2010-proposal.html>
168
168
169
169
170 Development summary: moving to Git and Github
170 Development summary: moving to Git and Github
171 ---------------------------------------------
171 ---------------------------------------------
172
172
173 In April 2010, after `one breakage too many with bzr`__, we decided to move our
173 In April 2010, after `one breakage too many with bzr`__, we decided to move our
174 entire development process to Git and Github.com. This has proven to be one of
174 entire development process to Git and Github.com. This has proven to be one of
175 the best decisions in the project's history, as the combination of git and
175 the best decisions in the project's history, as the combination of git and
176 github have made us far, far more productive than we could be with our previous
176 github have made us far, far more productive than we could be with our previous
177 tools. We first converted our bzr repo to a git one without losing history,
177 tools. We first converted our bzr repo to a git one without losing history,
178 and a few weeks later ported all open Launchpad bugs to github issues with
178 and a few weeks later ported all open Launchpad bugs to github issues with
179 their comments mostly intact (modulo some formatting changes). This ensured a
179 their comments mostly intact (modulo some formatting changes). This ensured a
180 smooth transition where no development history or submitted bugs were lost.
180 smooth transition where no development history or submitted bugs were lost.
181 Feel free to use our little Launchpad to Github issues `porting script`_ if you
181 Feel free to use our little Launchpad to Github issues `porting script`_ if you
182 need to make a similar transition.
182 need to make a similar transition.
183
183
184 .. __: http://mail.scipy.org/pipermail/ipython-dev/2010-April/005944.html
184 .. __: http://mail.scipy.org/pipermail/ipython-dev/2010-April/005944.html
185 .. _porting script: https://gist.github.com/835577
185 .. _porting script: https://gist.github.com/835577
186
186
187 These simple statistics show how much work has been done on the new release, by
187 These simple statistics show how much work has been done on the new release, by
188 comparing the current code to the last point it had in common with the 0.10
188 comparing the current code to the last point it had in common with the 0.10
189 series. A huge diff and ~2200 commits make up this cycle::
189 series. A huge diff and ~2200 commits make up this cycle::
190
190
191 git diff $(git merge-base 0.10.2 HEAD) | wc -l
191 git diff $(git merge-base 0.10.2 HEAD) | wc -l
192 288019
192 288019
193
193
194 git log $(git merge-base 0.10.2 HEAD)..HEAD --oneline | wc -l
194 git log $(git merge-base 0.10.2 HEAD)..HEAD --oneline | wc -l
195 2200
195 2200
196
196
197 Since our move to github, 511 issues were closed, 226 of which were pull
197 Since our move to github, 511 issues were closed, 226 of which were pull
198 requests and 285 regular issues (:ref:`a full list with links
198 requests and 285 regular issues (:ref:`a full list with links
199 <issues_list_011>` is available for those interested in the details). Github's
199 <issues_list_011>` is available for those interested in the details). Github's
200 pull requests are a fantastic mechanism for reviewing code and building a
200 pull requests are a fantastic mechanism for reviewing code and building a
201 shared ownership of the project, and we are making enthusiastic use of it.
201 shared ownership of the project, and we are making enthusiastic use of it.
202
202
203 .. Note::
203 .. Note::
204
204
205 This undercounts the number of issues closed in this development cycle,
205 This undercounts the number of issues closed in this development cycle,
206 since we only moved to github for issue tracking in May 2010, but we have no
206 since we only moved to github for issue tracking in May 2010, but we have no
207 way of collecting statistics on the number of issues closed in the old
207 way of collecting statistics on the number of issues closed in the old
208 Launchpad bug tracker prior to that.
208 Launchpad bug tracker prior to that.
209
209
210
210
211 .. _qtconsole_011:
211 .. _qtconsole_011:
212
212
213 Qt Console
213 Qt Console
214 ----------
214 ----------
215
215
216 IPython now ships with a Qt application that feels very much like a terminal,
216 IPython now ships with a Qt application that feels very much like a terminal,
217 but is in fact a rich GUI that runs an IPython client but supports inline
217 but is in fact a rich GUI that runs an IPython client but supports inline
218 figures, saving sessions to PDF and HTML, multiline editing with syntax
218 figures, saving sessions to PDF and HTML, multiline editing with syntax
219 highlighting, graphical calltips and much more:
219 highlighting, graphical calltips and much more:
220
220
221 .. figure:: ../_images/qtconsole.png
221 .. figure:: ../_images/qtconsole.png
222 :width: 400px
222 :width: 400px
223 :alt: IPython Qt console with embedded plots
223 :alt: IPython Qt console with embedded plots
224 :align: center
224 :align: center
225 :target: ../_images/qtconsole.png
225 :target: ../_images/qtconsole.png
226
226
227 The Qt console for IPython, using inline matplotlib plots.
227 The Qt console for IPython, using inline matplotlib plots.
228
228
229 We hope that many projects will embed this widget, which we've kept
229 We hope that many projects will embed this widget, which we've kept
230 deliberately very lightweight, into their own environments. In the future we
230 deliberately very lightweight, into their own environments. In the future we
231 may also offer a slightly more featureful application (with menus and other GUI
231 may also offer a slightly more featureful application (with menus and other GUI
232 elements), but we remain committed to always shipping this easy to embed
232 elements), but we remain committed to always shipping this easy to embed
233 widget.
233 widget.
234
234
235 See the `Jupyter Qt Console site <https://jupyter.org/qtconsole>`_ for a detailed
235 See the `Jupyter Qt Console site <https://jupyter.org/qtconsole>`_ for a detailed
236 description of the console's features and use.
236 description of the console's features and use.
237
237
238
238
239 .. _parallel_011:
239 .. _parallel_011:
240
240
241 High-level parallel computing with ZeroMQ
241 High-level parallel computing with ZeroMQ
242 -----------------------------------------
242 -----------------------------------------
243
243
244 We have completely rewritten the Twisted-based code for high-level parallel
244 We have completely rewritten the Twisted-based code for high-level parallel
245 computing to work atop our new ZeroMQ architecture. While we realize this will
245 computing to work atop our new ZeroMQ architecture. While we realize this will
246 break compatibility for a number of users, we hope to make the transition as
246 break compatibility for a number of users, we hope to make the transition as
247 easy as possible with our docs, and we are convinced the change is worth it.
247 easy as possible with our docs, and we are convinced the change is worth it.
248 ZeroMQ provides us with much tighter control over memory, higher performance,
248 ZeroMQ provides us with much tighter control over memory, higher performance,
249 and its communications are impervious to the Python Global Interpreter Lock
249 and its communications are impervious to the Python Global Interpreter Lock
250 because they take place in a system-level C++ thread. The impact of the GIL in
250 because they take place in a system-level C++ thread. The impact of the GIL in
251 our previous code was something we could simply not work around, given that
251 our previous code was something we could simply not work around, given that
252 Twisted is itself a Python library. So while Twisted is a very capable
252 Twisted is itself a Python library. So while Twisted is a very capable
253 framework, we think ZeroMQ fits our needs much better and we hope you will find
253 framework, we think ZeroMQ fits our needs much better and we hope you will find
254 the change to be a significant improvement in the long run.
254 the change to be a significant improvement in the long run.
255
255
256 Our manual contains a full description of how to use IPython for parallel
256 Our manual contains a full description of how to use IPython for parallel
257 computing, and the `tutorial`__ presented by Min
257 computing, and the `tutorial`__ presented by Min
258 Ragan-Kelley at the SciPy 2011 conference provides a hands-on complement to the
258 Ragan-Kelley at the SciPy 2011 conference provides a hands-on complement to the
259 reference docs.
259 reference docs.
260
260
261 .. __: http://minrk.github.com/scipy-tutorial-2011
261 .. __: http://minrk.github.com/scipy-tutorial-2011
262
262
263
263
264 Refactoring
264 Refactoring
265 -----------
265 -----------
266
266
267 As of this release, a signifiant portion of IPython has been refactored. This
267 As of this release, a significant portion of IPython has been refactored. This
268 refactoring is founded on a number of new abstractions. The main new classes
268 refactoring is founded on a number of new abstractions. The main new classes
269 that implement these abstractions are:
269 that implement these abstractions are:
270
270
271 * :class:`traitlets.HasTraits`.
271 * :class:`traitlets.HasTraits`.
272 * :class:`traitlets.config.configurable.Configurable`.
272 * :class:`traitlets.config.configurable.Configurable`.
273 * :class:`traitlets.config.application.Application`.
273 * :class:`traitlets.config.application.Application`.
274 * :class:`traitlets.config.loader.ConfigLoader`.
274 * :class:`traitlets.config.loader.ConfigLoader`.
275 * :class:`traitlets.config.loader.Config`
275 * :class:`traitlets.config.loader.Config`
276
276
277 We are still in the process of writing developer focused documentation about
277 We are still in the process of writing developer focused documentation about
278 these classes, but for now our :ref:`configuration documentation
278 these classes, but for now our :ref:`configuration documentation
279 <config_overview>` contains a high level overview of the concepts that these
279 <config_overview>` contains a high level overview of the concepts that these
280 classes express.
280 classes express.
281
281
282 The biggest user-visible change is likely the move to using the config system
282 The biggest user-visible change is likely the move to using the config system
283 to determine the command-line arguments for IPython applications. The benefit
283 to determine the command-line arguments for IPython applications. The benefit
284 of this is that *all* configurable values in IPython are exposed on the
284 of this is that *all* configurable values in IPython are exposed on the
285 command-line, but the syntax for specifying values has changed. The gist is
285 command-line, but the syntax for specifying values has changed. The gist is
286 that assigning values is pure Python assignment. Simple flags exist for
286 that assigning values is pure Python assignment. Simple flags exist for
287 commonly used options, these are always prefixed with '--'.
287 commonly used options, these are always prefixed with '--'.
288
288
289 The IPython command-line help has the details of all the options (via
289 The IPython command-line help has the details of all the options (via
290 ``ipython --help``), but a simple example should clarify things; the ``pylab``
290 ``ipython --help``), but a simple example should clarify things; the ``pylab``
291 flag can be used to start in pylab mode with the qt4 backend::
291 flag can be used to start in pylab mode with the qt4 backend::
292
292
293 ipython --pylab=qt
293 ipython --pylab=qt
294
294
295 which is equivalent to using the fully qualified form::
295 which is equivalent to using the fully qualified form::
296
296
297 ipython --TerminalIPythonApp.pylab=qt
297 ipython --TerminalIPythonApp.pylab=qt
298
298
299 The long-form options can be listed via ``ipython --help-all``.
299 The long-form options can be listed via ``ipython --help-all``.
300
300
301
301
302 ZeroMQ architecture
302 ZeroMQ architecture
303 -------------------
303 -------------------
304
304
305 There is a new GUI framework for IPython, based on a client-server model in
305 There is a new GUI framework for IPython, based on a client-server model in
306 which multiple clients can communicate with one IPython kernel, using the
306 which multiple clients can communicate with one IPython kernel, using the
307 ZeroMQ messaging framework. There is already a Qt console client, which can
307 ZeroMQ messaging framework. There is already a Qt console client, which can
308 be started by calling ``ipython qtconsole``. The protocol is :ref:`documented
308 be started by calling ``ipython qtconsole``. The protocol is :ref:`documented
309 <messaging>`.
309 <messaging>`.
310
310
311 The parallel computing framework has also been rewritten using ZMQ. The
311 The parallel computing framework has also been rewritten using ZMQ. The
312 protocol is described :ref:`here <parallel_messages>`, and the code is in the
312 protocol is described :ref:`here <parallel_messages>`, and the code is in the
313 new :mod:`IPython.parallel` module.
313 new :mod:`IPython.parallel` module.
314
314
315 .. _python3_011:
315 .. _python3_011:
316
316
317 Python 3 support
317 Python 3 support
318 ----------------
318 ----------------
319
319
320 A Python 3 version of IPython has been prepared. For the time being, this is
320 A Python 3 version of IPython has been prepared. For the time being, this is
321 maintained separately and updated from the main codebase. Its code can be found
321 maintained separately and updated from the main codebase. Its code can be found
322 `here <https://github.com/ipython/ipython-py3k>`_. The parallel computing
322 `here <https://github.com/ipython/ipython-py3k>`_. The parallel computing
323 components are not perfect on Python3, but most functionality appears to be
323 components are not perfect on Python3, but most functionality appears to be
324 working. As this work is evolving quickly, the best place to find updated
324 working. As this work is evolving quickly, the best place to find updated
325 information about it is our `Python 3 wiki page`__.
325 information about it is our `Python 3 wiki page`__.
326
326
327 .. __: http://wiki.ipython.org/index.php?title=Python_3
327 .. __: http://wiki.ipython.org/index.php?title=Python_3
328
328
329
329
330 Unicode
330 Unicode
331 -------
331 -------
332
332
333 Entering non-ascii characters in unicode literals (``u"€ø"``) now works
333 Entering non-ascii characters in unicode literals (``u"€ø"``) now works
334 properly on all platforms. However, entering these in byte/string literals
334 properly on all platforms. However, entering these in byte/string literals
335 (``"€ø"``) will not work as expected on Windows (or any platform where the
335 (``"€ø"``) will not work as expected on Windows (or any platform where the
336 terminal encoding is not UTF-8, as it typically is for Linux & Mac OS X). You
336 terminal encoding is not UTF-8, as it typically is for Linux & Mac OS X). You
337 can use escape sequences (``"\xe9\x82"``) to get bytes above 128, or use
337 can use escape sequences (``"\xe9\x82"``) to get bytes above 128, or use
338 unicode literals and encode them. This is a limitation of Python 2 which we
338 unicode literals and encode them. This is a limitation of Python 2 which we
339 cannot easily work around.
339 cannot easily work around.
340
340
341 .. _ms_visual_studio_011:
341 .. _ms_visual_studio_011:
342
342
343 Integration with Microsoft Visual Studio
343 Integration with Microsoft Visual Studio
344 ----------------------------------------
344 ----------------------------------------
345
345
346 IPython can be used as the interactive shell in the `Python plugin for
346 IPython can be used as the interactive shell in the `Python plugin for
347 Microsoft Visual Studio`__, as seen here:
347 Microsoft Visual Studio`__, as seen here:
348
348
349 .. figure:: ../_images/ms_visual_studio.png
349 .. figure:: ../_images/ms_visual_studio.png
350 :width: 500px
350 :width: 500px
351 :alt: IPython console embedded in Microsoft Visual Studio.
351 :alt: IPython console embedded in Microsoft Visual Studio.
352 :align: center
352 :align: center
353 :target: ../_images/ms_visual_studio.png
353 :target: ../_images/ms_visual_studio.png
354
354
355 IPython console embedded in Microsoft Visual Studio.
355 IPython console embedded in Microsoft Visual Studio.
356
356
357 The Microsoft team developing this currently has a release candidate out using
357 The Microsoft team developing this currently has a release candidate out using
358 IPython 0.11. We will continue to collaborate with them to ensure that as they
358 IPython 0.11. We will continue to collaborate with them to ensure that as they
359 approach their final release date, the integration with IPython remains smooth.
359 approach their final release date, the integration with IPython remains smooth.
360 We'd like to thank Dino Viehland and Shahrokh Mortazavi for the work they have
360 We'd like to thank Dino Viehland and Shahrokh Mortazavi for the work they have
361 done towards this feature, as well as Wenming Ye for his support of our WinHPC
361 done towards this feature, as well as Wenming Ye for his support of our WinHPC
362 capabilities.
362 capabilities.
363
363
364 .. __: http://pytools.codeplex.com
364 .. __: http://pytools.codeplex.com
365
365
366
366
367 Additional new features
367 Additional new features
368 -----------------------
368 -----------------------
369
369
370 * Added ``Bytes`` traitlet, removing ``Str``. All 'string' traitlets should
370 * Added ``Bytes`` traitlet, removing ``Str``. All 'string' traitlets should
371 either be ``Unicode`` if a real string, or ``Bytes`` if a C-string. This
371 either be ``Unicode`` if a real string, or ``Bytes`` if a C-string. This
372 removes ambiguity and helps the Python 3 transition.
372 removes ambiguity and helps the Python 3 transition.
373
373
374 * New magic ``%loadpy`` loads a python file from disk or web URL into
374 * New magic ``%loadpy`` loads a python file from disk or web URL into
375 the current input buffer.
375 the current input buffer.
376
376
377 * New magic ``%pastebin`` for sharing code via the 'Lodge it' pastebin.
377 * New magic ``%pastebin`` for sharing code via the 'Lodge it' pastebin.
378
378
379 * New magic ``%precision`` for controlling float and numpy pretty printing.
379 * New magic ``%precision`` for controlling float and numpy pretty printing.
380
380
381 * IPython applications initiate logging, so any object can gain access to
381 * IPython applications initiate logging, so any object can gain access to
382 a the logger of the currently running Application with:
382 a the logger of the currently running Application with:
383
383
384 .. sourcecode:: python
384 .. sourcecode:: python
385
385
386 from traitlets.config.application import Application
386 from traitlets.config.application import Application
387 logger = Application.instance().log
387 logger = Application.instance().log
388
388
389 * You can now get help on an object halfway through typing a command. For
389 * You can now get help on an object halfway through typing a command. For
390 instance, typing ``a = zip?`` shows the details of :func:`zip`. It also
390 instance, typing ``a = zip?`` shows the details of :func:`zip`. It also
391 leaves the command at the next prompt so you can carry on with it.
391 leaves the command at the next prompt so you can carry on with it.
392
392
393 * The input history is now written to an SQLite database. The API for
393 * The input history is now written to an SQLite database. The API for
394 retrieving items from the history has also been redesigned.
394 retrieving items from the history has also been redesigned.
395
395
396 * The :mod:`IPython.extensions.pretty` extension has been moved out of
396 * The :mod:`IPython.extensions.pretty` extension has been moved out of
397 quarantine and fully updated to the new extension API.
397 quarantine and fully updated to the new extension API.
398
398
399 * New magics for loading/unloading/reloading extensions have been added:
399 * New magics for loading/unloading/reloading extensions have been added:
400 ``%load_ext``, ``%unload_ext`` and ``%reload_ext``.
400 ``%load_ext``, ``%unload_ext`` and ``%reload_ext``.
401
401
402 * The configuration system and configuration files are brand new. See the
402 * The configuration system and configuration files are brand new. See the
403 configuration system :ref:`documentation <config_index>` for more details.
403 configuration system :ref:`documentation <config_index>` for more details.
404
404
405 * The :class:`~IPython.core.interactiveshell.InteractiveShell` class is now a
405 * The :class:`~IPython.core.interactiveshell.InteractiveShell` class is now a
406 :class:`~traitlets.config.configurable.Configurable` subclass and has traitlets
406 :class:`~traitlets.config.configurable.Configurable` subclass and has traitlets
407 that determine the defaults and runtime environment. The ``__init__`` method
407 that determine the defaults and runtime environment. The ``__init__`` method
408 has also been refactored so this class can be instantiated and run without
408 has also been refactored so this class can be instantiated and run without
409 the old :mod:`ipmaker` module.
409 the old :mod:`ipmaker` module.
410
410
411 * The methods of :class:`~IPython.core.interactiveshell.InteractiveShell` have
411 * The methods of :class:`~IPython.core.interactiveshell.InteractiveShell` have
412 been organized into sections to make it easier to turn more sections
412 been organized into sections to make it easier to turn more sections
413 of functionality into components.
413 of functionality into components.
414
414
415 * The embedded shell has been refactored into a truly standalone subclass of
415 * The embedded shell has been refactored into a truly standalone subclass of
416 :class:`InteractiveShell` called :class:`InteractiveShellEmbed`. All
416 :class:`InteractiveShell` called :class:`InteractiveShellEmbed`. All
417 embedding logic has been taken out of the base class and put into the
417 embedding logic has been taken out of the base class and put into the
418 embedded subclass.
418 embedded subclass.
419
419
420 * Added methods of :class:`~IPython.core.interactiveshell.InteractiveShell` to
420 * Added methods of :class:`~IPython.core.interactiveshell.InteractiveShell` to
421 help it cleanup after itself. The :meth:`cleanup` method controls this. We
421 help it cleanup after itself. The :meth:`cleanup` method controls this. We
422 couldn't do this in :meth:`__del__` because we have cycles in our object
422 couldn't do this in :meth:`__del__` because we have cycles in our object
423 graph that prevent it from being called.
423 graph that prevent it from being called.
424
424
425 * Created a new module :mod:`IPython.utils.importstring` for resolving
425 * Created a new module :mod:`IPython.utils.importstring` for resolving
426 strings like ``foo.bar.Bar`` to the actual class.
426 strings like ``foo.bar.Bar`` to the actual class.
427
427
428 * Completely refactored the :mod:`IPython.core.prefilter` module into
428 * Completely refactored the :mod:`IPython.core.prefilter` module into
429 :class:`~traitlets.config.configurable.Configurable` subclasses. Added a new
429 :class:`~traitlets.config.configurable.Configurable` subclasses. Added a new
430 layer into the prefilter system, called "transformations" that all new
430 layer into the prefilter system, called "transformations" that all new
431 prefilter logic should use (rather than the older "checker/handler"
431 prefilter logic should use (rather than the older "checker/handler"
432 approach).
432 approach).
433
433
434 * Aliases are now components (:mod:`IPython.core.alias`).
434 * Aliases are now components (:mod:`IPython.core.alias`).
435
435
436 * New top level :func:`~IPython.frontend.terminal.embed.embed` function that can
436 * New top level :func:`~IPython.frontend.terminal.embed.embed` function that can
437 be called to embed IPython at any place in user's code. On the first call it
437 be called to embed IPython at any place in user's code. On the first call it
438 will create an :class:`~IPython.frontend.terminal.embed.InteractiveShellEmbed`
438 will create an :class:`~IPython.frontend.terminal.embed.InteractiveShellEmbed`
439 instance and call it. In later calls, it just calls the previously created
439 instance and call it. In later calls, it just calls the previously created
440 :class:`~IPython.frontend.terminal.embed.InteractiveShellEmbed`.
440 :class:`~IPython.frontend.terminal.embed.InteractiveShellEmbed`.
441
441
442 * Created a configuration system (:mod:`traitlets.config.configurable`) that is
442 * Created a configuration system (:mod:`traitlets.config.configurable`) that is
443 based on :mod:`traitlets`. Configurables are arranged into a
443 based on :mod:`traitlets`. Configurables are arranged into a
444 runtime containment tree (not inheritance) that i) automatically propagates
444 runtime containment tree (not inheritance) that i) automatically propagates
445 configuration information and ii) allows singletons to discover each other in
445 configuration information and ii) allows singletons to discover each other in
446 a loosely coupled manner. In the future all parts of IPython will be
446 a loosely coupled manner. In the future all parts of IPython will be
447 subclasses of :class:`~traitlets.config.configurable.Configurable`. All IPython
447 subclasses of :class:`~traitlets.config.configurable.Configurable`. All IPython
448 developers should become familiar with the config system.
448 developers should become familiar with the config system.
449
449
450 * Created a new :class:`~traitlets.config.loader.Config` for holding
450 * Created a new :class:`~traitlets.config.loader.Config` for holding
451 configuration information. This is a dict like class with a few extras: i)
451 configuration information. This is a dict like class with a few extras: i)
452 it supports attribute style access, ii) it has a merge function that merges
452 it supports attribute style access, ii) it has a merge function that merges
453 two :class:`~traitlets.config.loader.Config` instances recursively and iii) it
453 two :class:`~traitlets.config.loader.Config` instances recursively and iii) it
454 will automatically create sub-:class:`~traitlets.config.loader.Config`
454 will automatically create sub-:class:`~traitlets.config.loader.Config`
455 instances for attributes that start with an uppercase character.
455 instances for attributes that start with an uppercase character.
456
456
457 * Created new configuration loaders in :mod:`traitlets.config.loader`. These
457 * Created new configuration loaders in :mod:`traitlets.config.loader`. These
458 loaders provide a unified loading interface for all configuration
458 loaders provide a unified loading interface for all configuration
459 information including command line arguments and configuration files. We
459 information including command line arguments and configuration files. We
460 have two default implementations based on :mod:`argparse` and plain python
460 have two default implementations based on :mod:`argparse` and plain python
461 files. These are used to implement the new configuration system.
461 files. These are used to implement the new configuration system.
462
462
463 * Created a top-level :class:`Application` class in
463 * Created a top-level :class:`Application` class in
464 :mod:`IPython.core.application` that is designed to encapsulate the starting
464 :mod:`IPython.core.application` that is designed to encapsulate the starting
465 of any basic Python program. An application loads and merges all the
465 of any basic Python program. An application loads and merges all the
466 configuration objects, constructs the main application, configures and
466 configuration objects, constructs the main application, configures and
467 initiates logging, and creates and configures any :class:`Configurable`
467 initiates logging, and creates and configures any :class:`Configurable`
468 instances and then starts the application running. An extended
468 instances and then starts the application running. An extended
469 :class:`BaseIPythonApplication` class adds logic for handling the
469 :class:`BaseIPythonApplication` class adds logic for handling the
470 IPython directory as well as profiles, and all IPython entry points
470 IPython directory as well as profiles, and all IPython entry points
471 extend it.
471 extend it.
472
472
473 * The :class:`Type` and :class:`Instance` traitlets now handle classes given
473 * The :class:`Type` and :class:`Instance` traitlets now handle classes given
474 as strings, like ``foo.bar.Bar``. This is needed for forward declarations.
474 as strings, like ``foo.bar.Bar``. This is needed for forward declarations.
475 But, this was implemented in a careful way so that string to class
475 But, this was implemented in a careful way so that string to class
476 resolution is done at a single point, when the parent
476 resolution is done at a single point, when the parent
477 :class:`~traitlets.HasTraitlets` is instantiated.
477 :class:`~traitlets.HasTraitlets` is instantiated.
478
478
479 * :mod:`IPython.utils.ipstruct` has been refactored to be a subclass of
479 * :mod:`IPython.utils.ipstruct` has been refactored to be a subclass of
480 dict. It also now has full docstrings and doctests.
480 dict. It also now has full docstrings and doctests.
481
481
482 * Created a Traits like implementation in :mod:`traitlets`. This
482 * Created a Traits like implementation in :mod:`traitlets`. This
483 is a pure Python, lightweight version of a library that is similar to
483 is a pure Python, lightweight version of a library that is similar to
484 Enthought's Traits project, but has no dependencies on Enthought's code. We
484 Enthought's Traits project, but has no dependencies on Enthought's code. We
485 are using this for validation, defaults and notification in our new component
485 are using this for validation, defaults and notification in our new component
486 system. Although it is not 100% API compatible with Enthought's Traits, we
486 system. Although it is not 100% API compatible with Enthought's Traits, we
487 plan on moving in this direction so that eventually our implementation could
487 plan on moving in this direction so that eventually our implementation could
488 be replaced by a (yet to exist) pure Python version of Enthought Traits.
488 be replaced by a (yet to exist) pure Python version of Enthought Traits.
489
489
490 * Added a new module :mod:`IPython.lib.inputhook` to manage the integration
490 * Added a new module :mod:`IPython.lib.inputhook` to manage the integration
491 with GUI event loops using `PyOS_InputHook`. See the docstrings in this
491 with GUI event loops using `PyOS_InputHook`. See the docstrings in this
492 module or the main IPython docs for details.
492 module or the main IPython docs for details.
493
493
494 * For users, GUI event loop integration is now handled through the new
494 * For users, GUI event loop integration is now handled through the new
495 :command:`%gui` magic command. Type ``%gui?`` at an IPython prompt for
495 :command:`%gui` magic command. Type ``%gui?`` at an IPython prompt for
496 documentation.
496 documentation.
497
497
498 * For developers :mod:`IPython.lib.inputhook` provides a simple interface
498 * For developers :mod:`IPython.lib.inputhook` provides a simple interface
499 for managing the event loops in their interactive GUI applications.
499 for managing the event loops in their interactive GUI applications.
500 Examples can be found in our :file:`examples/lib` directory.
500 Examples can be found in our :file:`examples/lib` directory.
501
501
502 Backwards incompatible changes
502 Backwards incompatible changes
503 ------------------------------
503 ------------------------------
504
504
505 * The Twisted-based :mod:`IPython.kernel` has been removed, and completely
505 * The Twisted-based :mod:`IPython.kernel` has been removed, and completely
506 rewritten as :mod:`IPython.parallel`, using ZeroMQ.
506 rewritten as :mod:`IPython.parallel`, using ZeroMQ.
507
507
508 * Profiles are now directories. Instead of a profile being a single config file,
508 * Profiles are now directories. Instead of a profile being a single config file,
509 profiles are now self-contained directories. By default, profiles get their
509 profiles are now self-contained directories. By default, profiles get their
510 own IPython history, log files, and everything. To create a new profile, do
510 own IPython history, log files, and everything. To create a new profile, do
511 ``ipython profile create <name>``.
511 ``ipython profile create <name>``.
512
512
513 * All IPython applications have been rewritten to use
513 * All IPython applications have been rewritten to use
514 :class:`~traitlets.config.loader.KeyValueConfigLoader`. This means that
514 :class:`~traitlets.config.loader.KeyValueConfigLoader`. This means that
515 command-line options have changed. Now, all configurable values are accessible
515 command-line options have changed. Now, all configurable values are accessible
516 from the command-line with the same syntax as in a configuration file.
516 from the command-line with the same syntax as in a configuration file.
517
517
518 * The command line options ``-wthread``, ``-qthread`` and
518 * The command line options ``-wthread``, ``-qthread`` and
519 ``-gthread`` have been removed. Use ``--gui=wx``, ``--gui=qt``, ``--gui=gtk``
519 ``-gthread`` have been removed. Use ``--gui=wx``, ``--gui=qt``, ``--gui=gtk``
520 instead.
520 instead.
521
521
522 * The extension loading functions have been renamed to
522 * The extension loading functions have been renamed to
523 :func:`load_ipython_extension` and :func:`unload_ipython_extension`.
523 :func:`load_ipython_extension` and :func:`unload_ipython_extension`.
524
524
525 * :class:`~IPython.core.interactiveshell.InteractiveShell` no longer takes an
525 * :class:`~IPython.core.interactiveshell.InteractiveShell` no longer takes an
526 ``embedded`` argument. Instead just use the
526 ``embedded`` argument. Instead just use the
527 :class:`~IPython.core.interactiveshell.InteractiveShellEmbed` class.
527 :class:`~IPython.core.interactiveshell.InteractiveShellEmbed` class.
528
528
529 * ``__IPYTHON__`` is no longer injected into ``__builtin__``.
529 * ``__IPYTHON__`` is no longer injected into ``__builtin__``.
530
530
531 * :meth:`Struct.__init__` no longer takes `None` as its first argument. It
531 * :meth:`Struct.__init__` no longer takes `None` as its first argument. It
532 must be a :class:`dict` or :class:`Struct`.
532 must be a :class:`dict` or :class:`Struct`.
533
533
534 * :meth:`~IPython.core.interactiveshell.InteractiveShell.ipmagic` has been
534 * :meth:`~IPython.core.interactiveshell.InteractiveShell.ipmagic` has been
535 renamed :meth:`~IPython.core.interactiveshell.InteractiveShell.magic.`
535 renamed :meth:`~IPython.core.interactiveshell.InteractiveShell.magic.`
536
536
537 * The functions :func:`ipmagic` and :func:`ipalias` have been removed from
537 * The functions :func:`ipmagic` and :func:`ipalias` have been removed from
538 :mod:`__builtins__`.
538 :mod:`__builtins__`.
539
539
540 * The references to the global
540 * The references to the global
541 :class:`~IPython.core.interactivehell.InteractiveShell` instance (``_ip``, and
541 :class:`~IPython.core.interactivehell.InteractiveShell` instance (``_ip``, and
542 ``__IP``) have been removed from the user's namespace. They are replaced by a
542 ``__IP``) have been removed from the user's namespace. They are replaced by a
543 new function called :func:`get_ipython` that returns the current
543 new function called :func:`get_ipython` that returns the current
544 :class:`~IPython.core.interactiveshell.InteractiveShell` instance. This
544 :class:`~IPython.core.interactiveshell.InteractiveShell` instance. This
545 function is injected into the user's namespace and is now the main way of
545 function is injected into the user's namespace and is now the main way of
546 accessing the running IPython.
546 accessing the running IPython.
547
547
548 * Old style configuration files :file:`ipythonrc` and :file:`ipy_user_conf.py`
548 * Old style configuration files :file:`ipythonrc` and :file:`ipy_user_conf.py`
549 are no longer supported. Users should migrate there configuration files to
549 are no longer supported. Users should migrate there configuration files to
550 the new format described :doc:`here </config/intro>` and
550 the new format described :doc:`here </config/intro>` and
551 :ref:`here <config_overview>`.
551 :ref:`here <config_overview>`.
552
552
553 * The old IPython extension API that relied on :func:`ipapi` has been
553 * The old IPython extension API that relied on :func:`ipapi` has been
554 completely removed. The new extension API is described :ref:`here
554 completely removed. The new extension API is described :ref:`here
555 <extensions_overview>`.
555 <extensions_overview>`.
556
556
557 * Support for ``qt3`` has been dropped. Users who need this should use
557 * Support for ``qt3`` has been dropped. Users who need this should use
558 previous versions of IPython.
558 previous versions of IPython.
559
559
560 * Removed :mod:`shellglobals` as it was obsolete.
560 * Removed :mod:`shellglobals` as it was obsolete.
561
561
562 * Removed all the threaded shells in :mod:`IPython.core.shell`. These are no
562 * Removed all the threaded shells in :mod:`IPython.core.shell`. These are no
563 longer needed because of the new capabilities in
563 longer needed because of the new capabilities in
564 :mod:`IPython.lib.inputhook`.
564 :mod:`IPython.lib.inputhook`.
565
565
566 * New top-level sub-packages have been created: :mod:`IPython.core`,
566 * New top-level sub-packages have been created: :mod:`IPython.core`,
567 :mod:`IPython.lib`, :mod:`IPython.utils`, :mod:`IPython.deathrow`,
567 :mod:`IPython.lib`, :mod:`IPython.utils`, :mod:`IPython.deathrow`,
568 :mod:`IPython.quarantine`. All existing top-level modules have been
568 :mod:`IPython.quarantine`. All existing top-level modules have been
569 moved to appropriate sub-packages. All internal import statements
569 moved to appropriate sub-packages. All internal import statements
570 have been updated and tests have been added. The build system (setup.py
570 have been updated and tests have been added. The build system (setup.py
571 and friends) have been updated. See :doc:`/api/index` for details of these
571 and friends) have been updated. See :doc:`/api/index` for details of these
572 new sub-packages.
572 new sub-packages.
573
573
574 * :mod:`IPython.ipapi` has been moved to :mod:`IPython.core.ipapi`.
574 * :mod:`IPython.ipapi` has been moved to :mod:`IPython.core.ipapi`.
575 :mod:`IPython.Shell` and :mod:`IPython.iplib` have been split and removed as
575 :mod:`IPython.Shell` and :mod:`IPython.iplib` have been split and removed as
576 part of the refactor.
576 part of the refactor.
577
577
578 * :mod:`Extensions` has been moved to :mod:`extensions` and all existing
578 * :mod:`Extensions` has been moved to :mod:`extensions` and all existing
579 extensions have been moved to either :mod:`IPython.quarantine` or
579 extensions have been moved to either :mod:`IPython.quarantine` or
580 :mod:`IPython.deathrow`. :mod:`IPython.quarantine` contains modules that we
580 :mod:`IPython.deathrow`. :mod:`IPython.quarantine` contains modules that we
581 plan on keeping but that need to be updated. :mod:`IPython.deathrow` contains
581 plan on keeping but that need to be updated. :mod:`IPython.deathrow` contains
582 modules that are either dead or that should be maintained as third party
582 modules that are either dead or that should be maintained as third party
583 libraries.
583 libraries.
584
584
585 * Previous IPython GUIs in :mod:`IPython.frontend` and :mod:`IPython.gui` are
585 * Previous IPython GUIs in :mod:`IPython.frontend` and :mod:`IPython.gui` are
586 likely broken, and have been removed to :mod:`IPython.deathrow` because of the
586 likely broken, and have been removed to :mod:`IPython.deathrow` because of the
587 refactoring in the core. With proper updates, these should still work.
587 refactoring in the core. With proper updates, these should still work.
588
588
589
589
590 Known Regressions
590 Known Regressions
591 -----------------
591 -----------------
592
592
593 We do our best to improve IPython, but there are some known regressions in 0.11
593 We do our best to improve IPython, but there are some known regressions in 0.11
594 relative to 0.10.2. First of all, there are features that have yet to be
594 relative to 0.10.2. First of all, there are features that have yet to be
595 ported to the new APIs, and in order to ensure that all of the installed code
595 ported to the new APIs, and in order to ensure that all of the installed code
596 runs for our users, we have moved them to two separate directories in the
596 runs for our users, we have moved them to two separate directories in the
597 source distribution, `quarantine` and `deathrow`. Finally, we have some other
597 source distribution, `quarantine` and `deathrow`. Finally, we have some other
598 miscellaneous regressions that we hope to fix as soon as possible. We now
598 miscellaneous regressions that we hope to fix as soon as possible. We now
599 describe all of these in more detail.
599 describe all of these in more detail.
600
600
601 Quarantine
601 Quarantine
602 ~~~~~~~~~~
602 ~~~~~~~~~~
603
603
604 These are tools and extensions that we consider relatively easy to update to
604 These are tools and extensions that we consider relatively easy to update to
605 the new classes and APIs, but that we simply haven't had time for. Any user
605 the new classes and APIs, but that we simply haven't had time for. Any user
606 who is interested in one of these is encouraged to help us by porting it and
606 who is interested in one of these is encouraged to help us by porting it and
607 submitting a pull request on our `development site`_.
607 submitting a pull request on our `development site`_.
608
608
609 .. _development site: http://github.com/ipython/ipython
609 .. _development site: http://github.com/ipython/ipython
610
610
611 Currently, the quarantine directory contains::
611 Currently, the quarantine directory contains::
612
612
613 clearcmd.py ipy_fsops.py ipy_signals.py
613 clearcmd.py ipy_fsops.py ipy_signals.py
614 envpersist.py ipy_gnuglobal.py ipy_synchronize_with.py
614 envpersist.py ipy_gnuglobal.py ipy_synchronize_with.py
615 ext_rescapture.py ipy_greedycompleter.py ipy_system_conf.py
615 ext_rescapture.py ipy_greedycompleter.py ipy_system_conf.py
616 InterpreterExec.py ipy_jot.py ipy_which.py
616 InterpreterExec.py ipy_jot.py ipy_which.py
617 ipy_app_completers.py ipy_lookfor.py ipy_winpdb.py
617 ipy_app_completers.py ipy_lookfor.py ipy_winpdb.py
618 ipy_autoreload.py ipy_profile_doctest.py ipy_workdir.py
618 ipy_autoreload.py ipy_profile_doctest.py ipy_workdir.py
619 ipy_completers.py ipy_pydb.py jobctrl.py
619 ipy_completers.py ipy_pydb.py jobctrl.py
620 ipy_editors.py ipy_rehashdir.py ledit.py
620 ipy_editors.py ipy_rehashdir.py ledit.py
621 ipy_exportdb.py ipy_render.py pspersistence.py
621 ipy_exportdb.py ipy_render.py pspersistence.py
622 ipy_extutil.py ipy_server.py win32clip.py
622 ipy_extutil.py ipy_server.py win32clip.py
623
623
624 Deathrow
624 Deathrow
625 ~~~~~~~~
625 ~~~~~~~~
626
626
627 These packages may be harder to update or make most sense as third-party
627 These packages may be harder to update or make most sense as third-party
628 libraries. Some of them are completely obsolete and have been already replaced
628 libraries. Some of them are completely obsolete and have been already replaced
629 by better functionality (we simply haven't had the time to carefully weed them
629 by better functionality (we simply haven't had the time to carefully weed them
630 out so they are kept here for now). Others simply require fixes to code that
630 out so they are kept here for now). Others simply require fixes to code that
631 the current core team may not be familiar with. If a tool you were used to is
631 the current core team may not be familiar with. If a tool you were used to is
632 included here, we encourage you to contact the dev list and we can discuss
632 included here, we encourage you to contact the dev list and we can discuss
633 whether it makes sense to keep it in IPython (if it can be maintained).
633 whether it makes sense to keep it in IPython (if it can be maintained).
634
634
635 Currently, the deathrow directory contains::
635 Currently, the deathrow directory contains::
636
636
637 astyle.py ipy_defaults.py ipy_vimserver.py
637 astyle.py ipy_defaults.py ipy_vimserver.py
638 dtutils.py ipy_kitcfg.py numeric_formats.py
638 dtutils.py ipy_kitcfg.py numeric_formats.py
639 Gnuplot2.py ipy_legacy.py numutils.py
639 Gnuplot2.py ipy_legacy.py numutils.py
640 GnuplotInteractive.py ipy_p4.py outputtrap.py
640 GnuplotInteractive.py ipy_p4.py outputtrap.py
641 GnuplotRuntime.py ipy_profile_none.py PhysicalQInput.py
641 GnuplotRuntime.py ipy_profile_none.py PhysicalQInput.py
642 ibrowse.py ipy_profile_numpy.py PhysicalQInteractive.py
642 ibrowse.py ipy_profile_numpy.py PhysicalQInteractive.py
643 igrid.py ipy_profile_scipy.py quitter.py*
643 igrid.py ipy_profile_scipy.py quitter.py*
644 ipipe.py ipy_profile_sh.py scitedirector.py
644 ipipe.py ipy_profile_sh.py scitedirector.py
645 iplib.py ipy_profile_zope.py Shell.py
645 iplib.py ipy_profile_zope.py Shell.py
646 ipy_constants.py ipy_traits_completer.py twshell.py
646 ipy_constants.py ipy_traits_completer.py twshell.py
647
647
648
648
649 Other regressions
649 Other regressions
650 ~~~~~~~~~~~~~~~~~
650 ~~~~~~~~~~~~~~~~~
651
651
652 * The machinery that adds functionality to the 'sh' profile for using IPython
652 * The machinery that adds functionality to the 'sh' profile for using IPython
653 as your system shell has not been updated to use the new APIs. As a result,
653 as your system shell has not been updated to use the new APIs. As a result,
654 only the aesthetic (prompt) changes are still implemented. We intend to fix
654 only the aesthetic (prompt) changes are still implemented. We intend to fix
655 this by 0.12. Tracked as issue 547_.
655 this by 0.12. Tracked as issue 547_.
656
656
657 .. _547: https://github.com/ipython/ipython/issues/547
657 .. _547: https://github.com/ipython/ipython/issues/547
658
658
659 * The installation of scripts on Windows was broken without setuptools, so we
659 * The installation of scripts on Windows was broken without setuptools, so we
660 now depend on setuptools on Windows. We hope to fix setuptools-less
660 now depend on setuptools on Windows. We hope to fix setuptools-less
661 installation, and then remove the setuptools dependency. Issue 539_.
661 installation, and then remove the setuptools dependency. Issue 539_.
662
662
663 .. _539: https://github.com/ipython/ipython/issues/539
663 .. _539: https://github.com/ipython/ipython/issues/539
664
664
665 * The directory history `_dh` is not saved between sessions. Issue 634_.
665 * The directory history `_dh` is not saved between sessions. Issue 634_.
666
666
667 .. _634: https://github.com/ipython/ipython/issues/634
667 .. _634: https://github.com/ipython/ipython/issues/634
668
668
669
669
670 Removed Features
670 Removed Features
671 ----------------
671 ----------------
672
672
673 As part of the updating of IPython, we have removed a few features for the
673 As part of the updating of IPython, we have removed a few features for the
674 purposes of cleaning up the codebase and interfaces. These removals are
674 purposes of cleaning up the codebase and interfaces. These removals are
675 permanent, but for any item listed below, equivalent functionality is
675 permanent, but for any item listed below, equivalent functionality is
676 available.
676 available.
677
677
678 * The magics Exit and Quit have been dropped as ways to exit IPython. Instead,
678 * The magics Exit and Quit have been dropped as ways to exit IPython. Instead,
679 the lowercase forms of both work either as a bare name (``exit``) or a
679 the lowercase forms of both work either as a bare name (``exit``) or a
680 function call (``exit()``). You can assign these to other names using
680 function call (``exit()``). You can assign these to other names using
681 exec_lines in the config file.
681 exec_lines in the config file.
682
682
683
683
684 .. _credits_011:
684 .. _credits_011:
685
685
686 Credits
686 Credits
687 -------
687 -------
688
688
689 Many users and developers contributed code, features, bug reports and ideas to
689 Many users and developers contributed code, features, bug reports and ideas to
690 this release. Please do not hesitate in contacting us if we've failed to
690 this release. Please do not hesitate in contacting us if we've failed to
691 acknowledge your contribution here. In particular, for this release we have
691 acknowledge your contribution here. In particular, for this release we have
692 contribution from the following people, a mix of new and regular names (in
692 contribution from the following people, a mix of new and regular names (in
693 alphabetical order by first name):
693 alphabetical order by first name):
694
694
695 * Aenugu Sai Kiran Reddy <saikrn08-at-gmail.com>
695 * Aenugu Sai Kiran Reddy <saikrn08-at-gmail.com>
696 * andy wilson <wilson.andrew.j+github-at-gmail.com>
696 * andy wilson <wilson.andrew.j+github-at-gmail.com>
697 * Antonio Cuni <antocuni>
697 * Antonio Cuni <antocuni>
698 * Barry Wark <barrywark-at-gmail.com>
698 * Barry Wark <barrywark-at-gmail.com>
699 * Beetoju Anuradha <anu.beethoju-at-gmail.com>
699 * Beetoju Anuradha <anu.beethoju-at-gmail.com>
700 * Benjamin Ragan-Kelley <minrk-at-Mercury.local>
700 * Benjamin Ragan-Kelley <minrk-at-Mercury.local>
701 * Brad Reisfeld
701 * Brad Reisfeld
702 * Brian E. Granger <ellisonbg-at-gmail.com>
702 * Brian E. Granger <ellisonbg-at-gmail.com>
703 * Christoph Gohlke <cgohlke-at-uci.edu>
703 * Christoph Gohlke <cgohlke-at-uci.edu>
704 * Cody Precord
704 * Cody Precord
705 * dan.milstein
705 * dan.milstein
706 * Darren Dale <dsdale24-at-gmail.com>
706 * Darren Dale <dsdale24-at-gmail.com>
707 * Dav Clark <davclark-at-berkeley.edu>
707 * Dav Clark <davclark-at-berkeley.edu>
708 * David Warde-Farley <wardefar-at-iro.umontreal.ca>
708 * David Warde-Farley <wardefar-at-iro.umontreal.ca>
709 * epatters <ejpatters-at-gmail.com>
709 * epatters <ejpatters-at-gmail.com>
710 * epatters <epatters-at-caltech.edu>
710 * epatters <epatters-at-caltech.edu>
711 * epatters <epatters-at-enthought.com>
711 * epatters <epatters-at-enthought.com>
712 * Eric Firing <efiring-at-hawaii.edu>
712 * Eric Firing <efiring-at-hawaii.edu>
713 * Erik Tollerud <erik.tollerud-at-gmail.com>
713 * Erik Tollerud <erik.tollerud-at-gmail.com>
714 * Evan Patterson <epatters-at-enthought.com>
714 * Evan Patterson <epatters-at-enthought.com>
715 * Fernando Perez <Fernando.Perez-at-berkeley.edu>
715 * Fernando Perez <Fernando.Perez-at-berkeley.edu>
716 * Gael Varoquaux <gael.varoquaux-at-normalesup.org>
716 * Gael Varoquaux <gael.varoquaux-at-normalesup.org>
717 * Gerardo <muzgash-at-Muzpelheim>
717 * Gerardo <muzgash-at-Muzpelheim>
718 * Jason Grout <jason.grout-at-drake.edu>
718 * Jason Grout <jason.grout-at-drake.edu>
719 * John Hunter <jdh2358-at-gmail.com>
719 * John Hunter <jdh2358-at-gmail.com>
720 * Jens Hedegaard Nielsen <jenshnielsen-at-gmail.com>
720 * Jens Hedegaard Nielsen <jenshnielsen-at-gmail.com>
721 * Johann Cohen-Tanugi <johann.cohentanugi-at-gmail.com>
721 * Johann Cohen-Tanugi <johann.cohentanugi-at-gmail.com>
722 * JΓΆrgen Stenarson <jorgen.stenarson-at-bostream.nu>
722 * JΓΆrgen Stenarson <jorgen.stenarson-at-bostream.nu>
723 * Justin Riley <justin.t.riley-at-gmail.com>
723 * Justin Riley <justin.t.riley-at-gmail.com>
724 * Kiorky
724 * Kiorky
725 * Laurent Dufrechou <laurent.dufrechou-at-gmail.com>
725 * Laurent Dufrechou <laurent.dufrechou-at-gmail.com>
726 * Luis Pedro Coelho <lpc-at-cmu.edu>
726 * Luis Pedro Coelho <lpc-at-cmu.edu>
727 * Mani chandra <mchandra-at-iitk.ac.in>
727 * Mani chandra <mchandra-at-iitk.ac.in>
728 * Mark E. Smith
728 * Mark E. Smith
729 * Mark Voorhies <mark.voorhies-at-ucsf.edu>
729 * Mark Voorhies <mark.voorhies-at-ucsf.edu>
730 * Martin Spacek <git-at-mspacek.mm.st>
730 * Martin Spacek <git-at-mspacek.mm.st>
731 * Michael Droettboom <mdroe-at-stsci.edu>
731 * Michael Droettboom <mdroe-at-stsci.edu>
732 * MinRK <benjaminrk-at-gmail.com>
732 * MinRK <benjaminrk-at-gmail.com>
733 * muzuiget <muzuiget-at-gmail.com>
733 * muzuiget <muzuiget-at-gmail.com>
734 * Nick Tarleton <nick-at-quixey.com>
734 * Nick Tarleton <nick-at-quixey.com>
735 * Nicolas Rougier <Nicolas.rougier-at-inria.fr>
735 * Nicolas Rougier <Nicolas.rougier-at-inria.fr>
736 * Omar Andres Zapata Mesa <andresete.chaos-at-gmail.com>
736 * Omar Andres Zapata Mesa <andresete.chaos-at-gmail.com>
737 * Paul Ivanov <pivanov314-at-gmail.com>
737 * Paul Ivanov <pivanov314-at-gmail.com>
738 * Pauli Virtanen <pauli.virtanen-at-iki.fi>
738 * Pauli Virtanen <pauli.virtanen-at-iki.fi>
739 * Prabhu Ramachandran
739 * Prabhu Ramachandran
740 * Ramana <sramana9-at-gmail.com>
740 * Ramana <sramana9-at-gmail.com>
741 * Robert Kern <robert.kern-at-gmail.com>
741 * Robert Kern <robert.kern-at-gmail.com>
742 * Sathesh Chandra <satheshchandra88-at-gmail.com>
742 * Sathesh Chandra <satheshchandra88-at-gmail.com>
743 * Satrajit Ghosh <satra-at-mit.edu>
743 * Satrajit Ghosh <satra-at-mit.edu>
744 * Sebastian Busch
744 * Sebastian Busch
745 * Skipper Seabold <jsseabold-at-gmail.com>
745 * Skipper Seabold <jsseabold-at-gmail.com>
746 * Stefan van der Walt <bzr-at-mentat.za.net>
746 * Stefan van der Walt <bzr-at-mentat.za.net>
747 * Stephan Peijnik <debian-at-sp.or.at>
747 * Stephan Peijnik <debian-at-sp.or.at>
748 * Steven Bethard
748 * Steven Bethard
749 * Thomas Kluyver <takowl-at-gmail.com>
749 * Thomas Kluyver <takowl-at-gmail.com>
750 * Thomas Spura <tomspur-at-fedoraproject.org>
750 * Thomas Spura <tomspur-at-fedoraproject.org>
751 * Tom Fetherston <tfetherston-at-aol.com>
751 * Tom Fetherston <tfetherston-at-aol.com>
752 * Tom MacWright
752 * Tom MacWright
753 * tzanko
753 * tzanko
754 * vankayala sowjanya <hai.sowjanya-at-gmail.com>
754 * vankayala sowjanya <hai.sowjanya-at-gmail.com>
755 * Vivian De Smedt <vds2212-at-VIVIAN>
755 * Vivian De Smedt <vds2212-at-VIVIAN>
756 * Ville M. Vainio <vivainio-at-gmail.com>
756 * Ville M. Vainio <vivainio-at-gmail.com>
757 * Vishal Vatsa <vishal.vatsa-at-gmail.com>
757 * Vishal Vatsa <vishal.vatsa-at-gmail.com>
758 * Vishnu S G <sgvishnu777-at-gmail.com>
758 * Vishnu S G <sgvishnu777-at-gmail.com>
759 * Walter Doerwald <walter-at-livinglogic.de>
759 * Walter Doerwald <walter-at-livinglogic.de>
760
760
761 .. note::
761 .. note::
762
762
763 This list was generated with the output of
763 This list was generated with the output of
764 ``git log dev-0.11 HEAD --format='* %aN <%aE>' | sed 's/@/\-at\-/' | sed 's/<>//' | sort -u``
764 ``git log dev-0.11 HEAD --format='* %aN <%aE>' | sed 's/@/\-at\-/' | sed 's/<>//' | sort -u``
765 after some cleanup. If you should be on this list, please add yourself.
765 after some cleanup. If you should be on this list, please add yourself.
@@ -1,145 +1,145 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 """An example of how to embed an IPython shell into a running program.
2 """An example of how to embed an IPython shell into a running program.
3
3
4 Please see the documentation in the IPython.Shell module for more details.
4 Please see the documentation in the IPython.Shell module for more details.
5
5
6 The accompanying file embed_class_short.py has quick code fragments for
6 The accompanying file embed_class_short.py has quick code fragments for
7 embedding which you can cut and paste in your code once you understand how
7 embedding which you can cut and paste in your code once you understand how
8 things work.
8 things work.
9
9
10 The code in this file is deliberately extra-verbose, meant for learning."""
10 The code in this file is deliberately extra-verbose, meant for learning."""
11
11
12 # The basics to get you going:
12 # The basics to get you going:
13
13
14 # IPython injects get_ipython into builtins, so you can know if you have nested
14 # IPython injects get_ipython into builtins, so you can know if you have nested
15 # copies running.
15 # copies running.
16
16
17 # Try running this code both at the command line and from inside IPython (with
17 # Try running this code both at the command line and from inside IPython (with
18 # %run example-embed.py)
18 # %run example-embed.py)
19
19
20 from IPython.terminal.prompts import Prompts, Token
20 from IPython.terminal.prompts import Prompts, Token
21
21
22 class CustomPrompt(Prompts):
22 class CustomPrompt(Prompts):
23
23
24 def in_prompt_tokens(self, cli=None):
24 def in_prompt_tokens(self, cli=None):
25
25
26 return [
26 return [
27 (Token.Prompt, 'In <'),
27 (Token.Prompt, 'In <'),
28 (Token.PromptNum, str(self.shell.execution_count)),
28 (Token.PromptNum, str(self.shell.execution_count)),
29 (Token.Prompt, '>: '),
29 (Token.Prompt, '>: '),
30 ]
30 ]
31
31
32 def out_prompt_tokens(self):
32 def out_prompt_tokens(self):
33 return [
33 return [
34 (Token.OutPrompt, 'Out<'),
34 (Token.OutPrompt, 'Out<'),
35 (Token.OutPromptNum, str(self.shell.execution_count)),
35 (Token.OutPromptNum, str(self.shell.execution_count)),
36 (Token.OutPrompt, '>: '),
36 (Token.OutPrompt, '>: '),
37 ]
37 ]
38
38
39
39
40 from traitlets.config.loader import Config
40 from traitlets.config.loader import Config
41 try:
41 try:
42 get_ipython
42 get_ipython
43 except NameError:
43 except NameError:
44 nested = 0
44 nested = 0
45 cfg = Config()
45 cfg = Config()
46 cfg.TerminalInteractiveShell.prompts_class=CustomPrompt
46 cfg.TerminalInteractiveShell.prompts_class=CustomPrompt
47 else:
47 else:
48 print("Running nested copies of IPython.")
48 print("Running nested copies of IPython.")
49 print("The prompts for the nested copy have been modified")
49 print("The prompts for the nested copy have been modified")
50 cfg = Config()
50 cfg = Config()
51 nested = 1
51 nested = 1
52
52
53 # First import the embeddable shell class
53 # First import the embeddable shell class
54 from IPython.terminal.embed import InteractiveShellEmbed
54 from IPython.terminal.embed import InteractiveShellEmbed
55
55
56 # Now create an instance of the embeddable shell. The first argument is a
56 # Now create an instance of the embeddable shell. The first argument is a
57 # string with options exactly as you would type them if you were starting
57 # string with options exactly as you would type them if you were starting
58 # IPython at the system command line. Any parameters you want to define for
58 # IPython at the system command line. Any parameters you want to define for
59 # configuration can thus be specified here.
59 # configuration can thus be specified here.
60 ipshell = InteractiveShellEmbed(config=cfg,
60 ipshell = InteractiveShellEmbed(config=cfg,
61 banner1 = 'Dropping into IPython',
61 banner1 = 'Dropping into IPython',
62 exit_msg = 'Leaving Interpreter, back to program.')
62 exit_msg = 'Leaving Interpreter, back to program.')
63
63
64 # Make a second instance, you can have as many as you want.
64 # Make a second instance, you can have as many as you want.
65 ipshell2 = InteractiveShellEmbed(config=cfg,
65 ipshell2 = InteractiveShellEmbed(config=cfg,
66 banner1 = 'Second IPython instance.')
66 banner1 = 'Second IPython instance.')
67
67
68 print('\nHello. This is printed from the main controller program.\n')
68 print('\nHello. This is printed from the main controller program.\n')
69
69
70 # You can then call ipshell() anywhere you need it (with an optional
70 # You can then call ipshell() anywhere you need it (with an optional
71 # message):
71 # message):
72 ipshell('***Called from top level. '
72 ipshell('***Called from top level. '
73 'Hit Ctrl-D to exit interpreter and continue program.\n'
73 'Hit Ctrl-D to exit interpreter and continue program.\n'
74 'Note that if you use %kill_embedded, you can fully deactivate\n'
74 'Note that if you use %kill_embedded, you can fully deactivate\n'
75 'This embedded instance so it will never turn on again')
75 'This embedded instance so it will never turn on again')
76
76
77 print('\nBack in caller program, moving along...\n')
77 print('\nBack in caller program, moving along...\n')
78
78
79 #---------------------------------------------------------------------------
79 #---------------------------------------------------------------------------
80 # More details:
80 # More details:
81
81
82 # InteractiveShellEmbed instances don't print the standard system banner and
82 # InteractiveShellEmbed instances don't print the standard system banner and
83 # messages. The IPython banner (which actually may contain initialization
83 # messages. The IPython banner (which actually may contain initialization
84 # messages) is available as get_ipython().banner in case you want it.
84 # messages) is available as get_ipython().banner in case you want it.
85
85
86 # InteractiveShellEmbed instances print the following information everytime they
86 # InteractiveShellEmbed instances print the following information every time they
87 # start:
87 # start:
88
88
89 # - A global startup banner.
89 # - A global startup banner.
90
90
91 # - A call-specific header string, which you can use to indicate where in the
91 # - A call-specific header string, which you can use to indicate where in the
92 # execution flow the shell is starting.
92 # execution flow the shell is starting.
93
93
94 # They also print an exit message every time they exit.
94 # They also print an exit message every time they exit.
95
95
96 # Both the startup banner and the exit message default to None, and can be set
96 # Both the startup banner and the exit message default to None, and can be set
97 # either at the instance constructor or at any other time with the
97 # either at the instance constructor or at any other time with the
98 # by setting the banner and exit_msg attributes.
98 # by setting the banner and exit_msg attributes.
99
99
100 # The shell instance can be also put in 'dummy' mode globally or on a per-call
100 # The shell instance can be also put in 'dummy' mode globally or on a per-call
101 # basis. This gives you fine control for debugging without having to change
101 # basis. This gives you fine control for debugging without having to change
102 # code all over the place.
102 # code all over the place.
103
103
104 # The code below illustrates all this.
104 # The code below illustrates all this.
105
105
106
106
107 # This is how the global banner and exit_msg can be reset at any point
107 # This is how the global banner and exit_msg can be reset at any point
108 ipshell.banner2 = 'Entering interpreter - New Banner'
108 ipshell.banner2 = 'Entering interpreter - New Banner'
109 ipshell.exit_msg = 'Leaving interpreter - New exit_msg'
109 ipshell.exit_msg = 'Leaving interpreter - New exit_msg'
110
110
111 def foo(m):
111 def foo(m):
112 s = 'spam'
112 s = 'spam'
113 ipshell('***In foo(). Try %whos, or print s or m:')
113 ipshell('***In foo(). Try %whos, or print s or m:')
114 print('foo says m = ',m)
114 print('foo says m = ',m)
115
115
116 def bar(n):
116 def bar(n):
117 s = 'eggs'
117 s = 'eggs'
118 ipshell('***In bar(). Try %whos, or print s or n:')
118 ipshell('***In bar(). Try %whos, or print s or n:')
119 print('bar says n = ',n)
119 print('bar says n = ',n)
120
120
121 # Some calls to the above functions which will trigger IPython:
121 # Some calls to the above functions which will trigger IPython:
122 print('Main program calling foo("eggs")\n')
122 print('Main program calling foo("eggs")\n')
123 foo('eggs')
123 foo('eggs')
124
124
125 # The shell can be put in 'dummy' mode where calls to it silently return. This
125 # The shell can be put in 'dummy' mode where calls to it silently return. This
126 # allows you, for example, to globally turn off debugging for a program with a
126 # allows you, for example, to globally turn off debugging for a program with a
127 # single call.
127 # single call.
128 ipshell.dummy_mode = True
128 ipshell.dummy_mode = True
129 print('\nTrying to call IPython which is now "dummy":')
129 print('\nTrying to call IPython which is now "dummy":')
130 ipshell()
130 ipshell()
131 print('Nothing happened...')
131 print('Nothing happened...')
132 # The global 'dummy' mode can still be overridden for a single call
132 # The global 'dummy' mode can still be overridden for a single call
133 print('\nOverriding dummy mode manually:')
133 print('\nOverriding dummy mode manually:')
134 ipshell(dummy=False)
134 ipshell(dummy=False)
135
135
136 # Reactivate the IPython shell
136 # Reactivate the IPython shell
137 ipshell.dummy_mode = False
137 ipshell.dummy_mode = False
138
138
139 print('You can even have multiple embedded instances:')
139 print('You can even have multiple embedded instances:')
140 ipshell2()
140 ipshell2()
141
141
142 print('\nMain program calling bar("spam")\n')
142 print('\nMain program calling bar("spam")\n')
143 bar('spam')
143 bar('spam')
144
144
145 print('Main program finished. Bye!')
145 print('Main program finished. Bye!')
General Comments 0
You need to be logged in to leave comments. Login now