##// END OF EJS Templates
remove unused imports
Srinivas Reddy Thatiparthy -
Show More
@@ -1,454 +1,453 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 IPython.utils import py3compat
30 from traitlets import (
29 from traitlets import (
31 List, Unicode, Type, Bool, Dict, Set, Instance, Undefined,
30 List, Unicode, Type, Bool, Dict, Set, Instance, Undefined,
32 default, observe,
31 default, observe,
33 )
32 )
34
33
35 if os.name == 'nt':
34 if os.name == 'nt':
36 programdata = os.environ.get('PROGRAMDATA', None)
35 programdata = os.environ.get('PROGRAMDATA', None)
37 if programdata:
36 if programdata:
38 SYSTEM_CONFIG_DIRS = [os.path.join(programdata, 'ipython')]
37 SYSTEM_CONFIG_DIRS = [os.path.join(programdata, 'ipython')]
39 else: # PROGRAMDATA is not defined by default on XP.
38 else: # PROGRAMDATA is not defined by default on XP.
40 SYSTEM_CONFIG_DIRS = []
39 SYSTEM_CONFIG_DIRS = []
41 else:
40 else:
42 SYSTEM_CONFIG_DIRS = [
41 SYSTEM_CONFIG_DIRS = [
43 "/usr/local/etc/ipython",
42 "/usr/local/etc/ipython",
44 "/etc/ipython",
43 "/etc/ipython",
45 ]
44 ]
46
45
47 _envvar = os.environ.get('IPYTHON_SUPPRESS_CONFIG_ERRORS')
46 _envvar = os.environ.get('IPYTHON_SUPPRESS_CONFIG_ERRORS')
48 if _envvar in {None, ''}:
47 if _envvar in {None, ''}:
49 IPYTHON_SUPPRESS_CONFIG_ERRORS = None
48 IPYTHON_SUPPRESS_CONFIG_ERRORS = None
50 else:
49 else:
51 if _envvar.lower() in {'1','true'}:
50 if _envvar.lower() in {'1','true'}:
52 IPYTHON_SUPPRESS_CONFIG_ERRORS = True
51 IPYTHON_SUPPRESS_CONFIG_ERRORS = True
53 elif _envvar.lower() in {'0','false'} :
52 elif _envvar.lower() in {'0','false'} :
54 IPYTHON_SUPPRESS_CONFIG_ERRORS = False
53 IPYTHON_SUPPRESS_CONFIG_ERRORS = False
55 else:
54 else:
56 sys.exit("Unsupported value for environment variable: 'IPYTHON_SUPPRESS_CONFIG_ERRORS' is set to '%s' which is none of {'0', '1', 'false', 'true', ''}."% _envvar )
55 sys.exit("Unsupported value for environment variable: 'IPYTHON_SUPPRESS_CONFIG_ERRORS' is set to '%s' which is none of {'0', '1', 'false', 'true', ''}."% _envvar )
57
56
58 # aliases and flags
57 # aliases and flags
59
58
60 base_aliases = {
59 base_aliases = {
61 'profile-dir' : 'ProfileDir.location',
60 'profile-dir' : 'ProfileDir.location',
62 'profile' : 'BaseIPythonApplication.profile',
61 'profile' : 'BaseIPythonApplication.profile',
63 'ipython-dir' : 'BaseIPythonApplication.ipython_dir',
62 'ipython-dir' : 'BaseIPythonApplication.ipython_dir',
64 'log-level' : 'Application.log_level',
63 'log-level' : 'Application.log_level',
65 'config' : 'BaseIPythonApplication.extra_config_file',
64 'config' : 'BaseIPythonApplication.extra_config_file',
66 }
65 }
67
66
68 base_flags = dict(
67 base_flags = dict(
69 debug = ({'Application' : {'log_level' : logging.DEBUG}},
68 debug = ({'Application' : {'log_level' : logging.DEBUG}},
70 "set log level to logging.DEBUG (maximize logging output)"),
69 "set log level to logging.DEBUG (maximize logging output)"),
71 quiet = ({'Application' : {'log_level' : logging.CRITICAL}},
70 quiet = ({'Application' : {'log_level' : logging.CRITICAL}},
72 "set log level to logging.CRITICAL (minimize logging output)"),
71 "set log level to logging.CRITICAL (minimize logging output)"),
73 init = ({'BaseIPythonApplication' : {
72 init = ({'BaseIPythonApplication' : {
74 'copy_config_files' : True,
73 'copy_config_files' : True,
75 'auto_create' : True}
74 'auto_create' : True}
76 }, """Initialize profile with default config files. This is equivalent
75 }, """Initialize profile with default config files. This is equivalent
77 to running `ipython profile create <profile>` prior to startup.
76 to running `ipython profile create <profile>` prior to startup.
78 """)
77 """)
79 )
78 )
80
79
81 class ProfileAwareConfigLoader(PyFileConfigLoader):
80 class ProfileAwareConfigLoader(PyFileConfigLoader):
82 """A Python file config loader that is aware of IPython profiles."""
81 """A Python file config loader that is aware of IPython profiles."""
83 def load_subconfig(self, fname, path=None, profile=None):
82 def load_subconfig(self, fname, path=None, profile=None):
84 if profile is not None:
83 if profile is not None:
85 try:
84 try:
86 profile_dir = ProfileDir.find_profile_dir_by_name(
85 profile_dir = ProfileDir.find_profile_dir_by_name(
87 get_ipython_dir(),
86 get_ipython_dir(),
88 profile,
87 profile,
89 )
88 )
90 except ProfileDirError:
89 except ProfileDirError:
91 return
90 return
92 path = profile_dir.location
91 path = profile_dir.location
93 return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path)
92 return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path)
94
93
95 class BaseIPythonApplication(Application):
94 class BaseIPythonApplication(Application):
96
95
97 name = Unicode(u'ipython')
96 name = Unicode(u'ipython')
98 description = Unicode(u'IPython: an enhanced interactive Python shell.')
97 description = Unicode(u'IPython: an enhanced interactive Python shell.')
99 version = Unicode(release.version)
98 version = Unicode(release.version)
100
99
101 aliases = Dict(base_aliases)
100 aliases = Dict(base_aliases)
102 flags = Dict(base_flags)
101 flags = Dict(base_flags)
103 classes = List([ProfileDir])
102 classes = List([ProfileDir])
104
103
105 # enable `load_subconfig('cfg.py', profile='name')`
104 # enable `load_subconfig('cfg.py', profile='name')`
106 python_config_loader_class = ProfileAwareConfigLoader
105 python_config_loader_class = ProfileAwareConfigLoader
107
106
108 # Track whether the config_file has changed,
107 # Track whether the config_file has changed,
109 # because some logic happens only if we aren't using the default.
108 # because some logic happens only if we aren't using the default.
110 config_file_specified = Set()
109 config_file_specified = Set()
111
110
112 config_file_name = Unicode()
111 config_file_name = Unicode()
113 @default('config_file_name')
112 @default('config_file_name')
114 def _config_file_name_default(self):
113 def _config_file_name_default(self):
115 return self.name.replace('-','_') + u'_config.py'
114 return self.name.replace('-','_') + u'_config.py'
116 @observe('config_file_name')
115 @observe('config_file_name')
117 def _config_file_name_changed(self, change):
116 def _config_file_name_changed(self, change):
118 if change['new'] != change['old']:
117 if change['new'] != change['old']:
119 self.config_file_specified.add(change['new'])
118 self.config_file_specified.add(change['new'])
120
119
121 # The directory that contains IPython's builtin profiles.
120 # The directory that contains IPython's builtin profiles.
122 builtin_profile_dir = Unicode(
121 builtin_profile_dir = Unicode(
123 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
122 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
124 )
123 )
125
124
126 config_file_paths = List(Unicode())
125 config_file_paths = List(Unicode())
127 @default('config_file_paths')
126 @default('config_file_paths')
128 def _config_file_paths_default(self):
127 def _config_file_paths_default(self):
129 return [os.getcwd()]
128 return [os.getcwd()]
130
129
131 extra_config_file = Unicode(
130 extra_config_file = Unicode(
132 help="""Path to an extra config file to load.
131 help="""Path to an extra config file to load.
133
132
134 If specified, load this config file in addition to any other IPython config.
133 If specified, load this config file in addition to any other IPython config.
135 """).tag(config=True)
134 """).tag(config=True)
136 @observe('extra_config_file')
135 @observe('extra_config_file')
137 def _extra_config_file_changed(self, change):
136 def _extra_config_file_changed(self, change):
138 old = change['old']
137 old = change['old']
139 new = change['new']
138 new = change['new']
140 try:
139 try:
141 self.config_files.remove(old)
140 self.config_files.remove(old)
142 except ValueError:
141 except ValueError:
143 pass
142 pass
144 self.config_file_specified.add(new)
143 self.config_file_specified.add(new)
145 self.config_files.append(new)
144 self.config_files.append(new)
146
145
147 profile = Unicode(u'default',
146 profile = Unicode(u'default',
148 help="""The IPython profile to use."""
147 help="""The IPython profile to use."""
149 ).tag(config=True)
148 ).tag(config=True)
150
149
151 @observe('profile')
150 @observe('profile')
152 def _profile_changed(self, change):
151 def _profile_changed(self, change):
153 self.builtin_profile_dir = os.path.join(
152 self.builtin_profile_dir = os.path.join(
154 get_ipython_package_dir(), u'config', u'profile', change['new']
153 get_ipython_package_dir(), u'config', u'profile', change['new']
155 )
154 )
156
155
157 ipython_dir = Unicode(
156 ipython_dir = Unicode(
158 help="""
157 help="""
159 The name of the IPython directory. This directory is used for logging
158 The name of the IPython directory. This directory is used for logging
160 configuration (through profiles), history storage, etc. The default
159 configuration (through profiles), history storage, etc. The default
161 is usually $HOME/.ipython. This option can also be specified through
160 is usually $HOME/.ipython. This option can also be specified through
162 the environment variable IPYTHONDIR.
161 the environment variable IPYTHONDIR.
163 """
162 """
164 ).tag(config=True)
163 ).tag(config=True)
165 @default('ipython_dir')
164 @default('ipython_dir')
166 def _ipython_dir_default(self):
165 def _ipython_dir_default(self):
167 d = get_ipython_dir()
166 d = get_ipython_dir()
168 self._ipython_dir_changed({
167 self._ipython_dir_changed({
169 'name': 'ipython_dir',
168 'name': 'ipython_dir',
170 'old': d,
169 'old': d,
171 'new': d,
170 'new': d,
172 })
171 })
173 return d
172 return d
174
173
175 _in_init_profile_dir = False
174 _in_init_profile_dir = False
176 profile_dir = Instance(ProfileDir, allow_none=True)
175 profile_dir = Instance(ProfileDir, allow_none=True)
177 @default('profile_dir')
176 @default('profile_dir')
178 def _profile_dir_default(self):
177 def _profile_dir_default(self):
179 # avoid recursion
178 # avoid recursion
180 if self._in_init_profile_dir:
179 if self._in_init_profile_dir:
181 return
180 return
182 # profile_dir requested early, force initialization
181 # profile_dir requested early, force initialization
183 self.init_profile_dir()
182 self.init_profile_dir()
184 return self.profile_dir
183 return self.profile_dir
185
184
186 overwrite = Bool(False,
185 overwrite = Bool(False,
187 help="""Whether to overwrite existing config files when copying"""
186 help="""Whether to overwrite existing config files when copying"""
188 ).tag(config=True)
187 ).tag(config=True)
189 auto_create = Bool(False,
188 auto_create = Bool(False,
190 help="""Whether to create profile dir if it doesn't exist"""
189 help="""Whether to create profile dir if it doesn't exist"""
191 ).tag(config=True)
190 ).tag(config=True)
192
191
193 config_files = List(Unicode())
192 config_files = List(Unicode())
194 @default('config_files')
193 @default('config_files')
195 def _config_files_default(self):
194 def _config_files_default(self):
196 return [self.config_file_name]
195 return [self.config_file_name]
197
196
198 copy_config_files = Bool(False,
197 copy_config_files = Bool(False,
199 help="""Whether to install the default config files into the profile dir.
198 help="""Whether to install the default config files into the profile dir.
200 If a new profile is being created, and IPython contains config files for that
199 If a new profile is being created, and IPython contains config files for that
201 profile, then they will be staged into the new directory. Otherwise,
200 profile, then they will be staged into the new directory. Otherwise,
202 default config files will be automatically generated.
201 default config files will be automatically generated.
203 """).tag(config=True)
202 """).tag(config=True)
204
203
205 verbose_crash = Bool(False,
204 verbose_crash = Bool(False,
206 help="""Create a massive crash report when IPython encounters what may be an
205 help="""Create a massive crash report when IPython encounters what may be an
207 internal error. The default is to append a short message to the
206 internal error. The default is to append a short message to the
208 usual traceback""").tag(config=True)
207 usual traceback""").tag(config=True)
209
208
210 # The class to use as the crash handler.
209 # The class to use as the crash handler.
211 crash_handler_class = Type(crashhandler.CrashHandler)
210 crash_handler_class = Type(crashhandler.CrashHandler)
212
211
213 @catch_config_error
212 @catch_config_error
214 def __init__(self, **kwargs):
213 def __init__(self, **kwargs):
215 super(BaseIPythonApplication, self).__init__(**kwargs)
214 super(BaseIPythonApplication, self).__init__(**kwargs)
216 # ensure current working directory exists
215 # ensure current working directory exists
217 try:
216 try:
218 os.getcwd()
217 os.getcwd()
219 except:
218 except:
220 # exit if cwd doesn't exist
219 # exit if cwd doesn't exist
221 self.log.error("Current working directory doesn't exist.")
220 self.log.error("Current working directory doesn't exist.")
222 self.exit(1)
221 self.exit(1)
223
222
224 #-------------------------------------------------------------------------
223 #-------------------------------------------------------------------------
225 # Various stages of Application creation
224 # Various stages of Application creation
226 #-------------------------------------------------------------------------
225 #-------------------------------------------------------------------------
227
226
228 deprecated_subcommands = {}
227 deprecated_subcommands = {}
229
228
230 def initialize_subcommand(self, subc, argv=None):
229 def initialize_subcommand(self, subc, argv=None):
231 if subc in self.deprecated_subcommands:
230 if subc in self.deprecated_subcommands:
232 self.log.warning("Subcommand `ipython {sub}` is deprecated and will be removed "
231 self.log.warning("Subcommand `ipython {sub}` is deprecated and will be removed "
233 "in future versions.".format(sub=subc))
232 "in future versions.".format(sub=subc))
234 self.log.warning("You likely want to use `jupyter {sub}` in the "
233 self.log.warning("You likely want to use `jupyter {sub}` in the "
235 "future".format(sub=subc))
234 "future".format(sub=subc))
236 return super(BaseIPythonApplication, self).initialize_subcommand(subc, argv)
235 return super(BaseIPythonApplication, self).initialize_subcommand(subc, argv)
237
236
238 def init_crash_handler(self):
237 def init_crash_handler(self):
239 """Create a crash handler, typically setting sys.excepthook to it."""
238 """Create a crash handler, typically setting sys.excepthook to it."""
240 self.crash_handler = self.crash_handler_class(self)
239 self.crash_handler = self.crash_handler_class(self)
241 sys.excepthook = self.excepthook
240 sys.excepthook = self.excepthook
242 def unset_crashhandler():
241 def unset_crashhandler():
243 sys.excepthook = sys.__excepthook__
242 sys.excepthook = sys.__excepthook__
244 atexit.register(unset_crashhandler)
243 atexit.register(unset_crashhandler)
245
244
246 def excepthook(self, etype, evalue, tb):
245 def excepthook(self, etype, evalue, tb):
247 """this is sys.excepthook after init_crashhandler
246 """this is sys.excepthook after init_crashhandler
248
247
249 set self.verbose_crash=True to use our full crashhandler, instead of
248 set self.verbose_crash=True to use our full crashhandler, instead of
250 a regular traceback with a short message (crash_handler_lite)
249 a regular traceback with a short message (crash_handler_lite)
251 """
250 """
252
251
253 if self.verbose_crash:
252 if self.verbose_crash:
254 return self.crash_handler(etype, evalue, tb)
253 return self.crash_handler(etype, evalue, tb)
255 else:
254 else:
256 return crashhandler.crash_handler_lite(etype, evalue, tb)
255 return crashhandler.crash_handler_lite(etype, evalue, tb)
257
256
258 @observe('ipython_dir')
257 @observe('ipython_dir')
259 def _ipython_dir_changed(self, change):
258 def _ipython_dir_changed(self, change):
260 old = change['old']
259 old = change['old']
261 new = change['new']
260 new = change['new']
262 if old is not Undefined:
261 if old is not Undefined:
263 str_old = os.path.abspath(old)
262 str_old = os.path.abspath(old)
264 if str_old in sys.path:
263 if str_old in sys.path:
265 sys.path.remove(str_old)
264 sys.path.remove(str_old)
266 str_path = os.path.abspath(new)
265 str_path = os.path.abspath(new)
267 sys.path.append(str_path)
266 sys.path.append(str_path)
268 ensure_dir_exists(new)
267 ensure_dir_exists(new)
269 readme = os.path.join(new, 'README')
268 readme = os.path.join(new, 'README')
270 readme_src = os.path.join(get_ipython_package_dir(), u'config', u'profile', 'README')
269 readme_src = os.path.join(get_ipython_package_dir(), u'config', u'profile', 'README')
271 if not os.path.exists(readme) and os.path.exists(readme_src):
270 if not os.path.exists(readme) and os.path.exists(readme_src):
272 shutil.copy(readme_src, readme)
271 shutil.copy(readme_src, readme)
273 for d in ('extensions', 'nbextensions'):
272 for d in ('extensions', 'nbextensions'):
274 path = os.path.join(new, d)
273 path = os.path.join(new, d)
275 try:
274 try:
276 ensure_dir_exists(path)
275 ensure_dir_exists(path)
277 except OSError as e:
276 except OSError as e:
278 # this will not be EEXIST
277 # this will not be EEXIST
279 self.log.error("couldn't create path %s: %s", path, e)
278 self.log.error("couldn't create path %s: %s", path, e)
280 self.log.debug("IPYTHONDIR set to: %s" % new)
279 self.log.debug("IPYTHONDIR set to: %s" % new)
281
280
282 def load_config_file(self, suppress_errors=IPYTHON_SUPPRESS_CONFIG_ERRORS):
281 def load_config_file(self, suppress_errors=IPYTHON_SUPPRESS_CONFIG_ERRORS):
283 """Load the config file.
282 """Load the config file.
284
283
285 By default, errors in loading config are handled, and a warning
284 By default, errors in loading config are handled, and a warning
286 printed on screen. For testing, the suppress_errors option is set
285 printed on screen. For testing, the suppress_errors option is set
287 to False, so errors will make tests fail.
286 to False, so errors will make tests fail.
288
287
289 `supress_errors` default value is to be `None` in which case the
288 `supress_errors` default value is to be `None` in which case the
290 behavior default to the one of `traitlets.Application`.
289 behavior default to the one of `traitlets.Application`.
291
290
292 The default value can be set :
291 The default value can be set :
293 - to `False` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '0', or 'false' (case insensitive).
292 - to `False` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '0', or 'false' (case insensitive).
294 - to `True` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '1' or 'true' (case insensitive).
293 - to `True` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '1' or 'true' (case insensitive).
295 - to `None` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '' (empty string) or leaving it unset.
294 - to `None` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '' (empty string) or leaving it unset.
296
295
297 Any other value are invalid, and will make IPython exit with a non-zero return code.
296 Any other value are invalid, and will make IPython exit with a non-zero return code.
298 """
297 """
299
298
300
299
301 self.log.debug("Searching path %s for config files", self.config_file_paths)
300 self.log.debug("Searching path %s for config files", self.config_file_paths)
302 base_config = 'ipython_config.py'
301 base_config = 'ipython_config.py'
303 self.log.debug("Attempting to load config file: %s" %
302 self.log.debug("Attempting to load config file: %s" %
304 base_config)
303 base_config)
305 try:
304 try:
306 if suppress_errors is not None:
305 if suppress_errors is not None:
307 old_value = Application.raise_config_file_errors
306 old_value = Application.raise_config_file_errors
308 Application.raise_config_file_errors = not suppress_errors;
307 Application.raise_config_file_errors = not suppress_errors;
309 Application.load_config_file(
308 Application.load_config_file(
310 self,
309 self,
311 base_config,
310 base_config,
312 path=self.config_file_paths
311 path=self.config_file_paths
313 )
312 )
314 except ConfigFileNotFound:
313 except ConfigFileNotFound:
315 # ignore errors loading parent
314 # ignore errors loading parent
316 self.log.debug("Config file %s not found", base_config)
315 self.log.debug("Config file %s not found", base_config)
317 pass
316 pass
318 if suppress_errors is not None:
317 if suppress_errors is not None:
319 Application.raise_config_file_errors = old_value
318 Application.raise_config_file_errors = old_value
320
319
321 for config_file_name in self.config_files:
320 for config_file_name in self.config_files:
322 if not config_file_name or config_file_name == base_config:
321 if not config_file_name or config_file_name == base_config:
323 continue
322 continue
324 self.log.debug("Attempting to load config file: %s" %
323 self.log.debug("Attempting to load config file: %s" %
325 self.config_file_name)
324 self.config_file_name)
326 try:
325 try:
327 Application.load_config_file(
326 Application.load_config_file(
328 self,
327 self,
329 config_file_name,
328 config_file_name,
330 path=self.config_file_paths
329 path=self.config_file_paths
331 )
330 )
332 except ConfigFileNotFound:
331 except ConfigFileNotFound:
333 # Only warn if the default config file was NOT being used.
332 # Only warn if the default config file was NOT being used.
334 if config_file_name in self.config_file_specified:
333 if config_file_name in self.config_file_specified:
335 msg = self.log.warning
334 msg = self.log.warning
336 else:
335 else:
337 msg = self.log.debug
336 msg = self.log.debug
338 msg("Config file not found, skipping: %s", config_file_name)
337 msg("Config file not found, skipping: %s", config_file_name)
339 except Exception:
338 except Exception:
340 # For testing purposes.
339 # For testing purposes.
341 if not suppress_errors:
340 if not suppress_errors:
342 raise
341 raise
343 self.log.warning("Error loading config file: %s" %
342 self.log.warning("Error loading config file: %s" %
344 self.config_file_name, exc_info=True)
343 self.config_file_name, exc_info=True)
345
344
346 def init_profile_dir(self):
345 def init_profile_dir(self):
347 """initialize the profile dir"""
346 """initialize the profile dir"""
348 self._in_init_profile_dir = True
347 self._in_init_profile_dir = True
349 if self.profile_dir is not None:
348 if self.profile_dir is not None:
350 # already ran
349 # already ran
351 return
350 return
352 if 'ProfileDir.location' not in self.config:
351 if 'ProfileDir.location' not in self.config:
353 # location not specified, find by profile name
352 # location not specified, find by profile name
354 try:
353 try:
355 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
354 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
356 except ProfileDirError:
355 except ProfileDirError:
357 # not found, maybe create it (always create default profile)
356 # not found, maybe create it (always create default profile)
358 if self.auto_create or self.profile == 'default':
357 if self.auto_create or self.profile == 'default':
359 try:
358 try:
360 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
359 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
361 except ProfileDirError:
360 except ProfileDirError:
362 self.log.fatal("Could not create profile: %r"%self.profile)
361 self.log.fatal("Could not create profile: %r"%self.profile)
363 self.exit(1)
362 self.exit(1)
364 else:
363 else:
365 self.log.info("Created profile dir: %r"%p.location)
364 self.log.info("Created profile dir: %r"%p.location)
366 else:
365 else:
367 self.log.fatal("Profile %r not found."%self.profile)
366 self.log.fatal("Profile %r not found."%self.profile)
368 self.exit(1)
367 self.exit(1)
369 else:
368 else:
370 self.log.debug("Using existing profile dir: %r"%p.location)
369 self.log.debug("Using existing profile dir: %r"%p.location)
371 else:
370 else:
372 location = self.config.ProfileDir.location
371 location = self.config.ProfileDir.location
373 # location is fully specified
372 # location is fully specified
374 try:
373 try:
375 p = ProfileDir.find_profile_dir(location, self.config)
374 p = ProfileDir.find_profile_dir(location, self.config)
376 except ProfileDirError:
375 except ProfileDirError:
377 # not found, maybe create it
376 # not found, maybe create it
378 if self.auto_create:
377 if self.auto_create:
379 try:
378 try:
380 p = ProfileDir.create_profile_dir(location, self.config)
379 p = ProfileDir.create_profile_dir(location, self.config)
381 except ProfileDirError:
380 except ProfileDirError:
382 self.log.fatal("Could not create profile directory: %r"%location)
381 self.log.fatal("Could not create profile directory: %r"%location)
383 self.exit(1)
382 self.exit(1)
384 else:
383 else:
385 self.log.debug("Creating new profile dir: %r"%location)
384 self.log.debug("Creating new profile dir: %r"%location)
386 else:
385 else:
387 self.log.fatal("Profile directory %r not found."%location)
386 self.log.fatal("Profile directory %r not found."%location)
388 self.exit(1)
387 self.exit(1)
389 else:
388 else:
390 self.log.info("Using existing profile dir: %r"%location)
389 self.log.info("Using existing profile dir: %r"%location)
391 # if profile_dir is specified explicitly, set profile name
390 # if profile_dir is specified explicitly, set profile name
392 dir_name = os.path.basename(p.location)
391 dir_name = os.path.basename(p.location)
393 if dir_name.startswith('profile_'):
392 if dir_name.startswith('profile_'):
394 self.profile = dir_name[8:]
393 self.profile = dir_name[8:]
395
394
396 self.profile_dir = p
395 self.profile_dir = p
397 self.config_file_paths.append(p.location)
396 self.config_file_paths.append(p.location)
398 self._in_init_profile_dir = False
397 self._in_init_profile_dir = False
399
398
400 def init_config_files(self):
399 def init_config_files(self):
401 """[optionally] copy default config files into profile dir."""
400 """[optionally] copy default config files into profile dir."""
402 self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
401 self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
403 # copy config files
402 # copy config files
404 path = self.builtin_profile_dir
403 path = self.builtin_profile_dir
405 if self.copy_config_files:
404 if self.copy_config_files:
406 src = self.profile
405 src = self.profile
407
406
408 cfg = self.config_file_name
407 cfg = self.config_file_name
409 if path and os.path.exists(os.path.join(path, cfg)):
408 if path and os.path.exists(os.path.join(path, cfg)):
410 self.log.warning("Staging %r from %s into %r [overwrite=%s]"%(
409 self.log.warning("Staging %r from %s into %r [overwrite=%s]"%(
411 cfg, src, self.profile_dir.location, self.overwrite)
410 cfg, src, self.profile_dir.location, self.overwrite)
412 )
411 )
413 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
412 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
414 else:
413 else:
415 self.stage_default_config_file()
414 self.stage_default_config_file()
416 else:
415 else:
417 # Still stage *bundled* config files, but not generated ones
416 # Still stage *bundled* config files, but not generated ones
418 # This is necessary for `ipython profile=sympy` to load the profile
417 # This is necessary for `ipython profile=sympy` to load the profile
419 # on the first go
418 # on the first go
420 files = glob.glob(os.path.join(path, '*.py'))
419 files = glob.glob(os.path.join(path, '*.py'))
421 for fullpath in files:
420 for fullpath in files:
422 cfg = os.path.basename(fullpath)
421 cfg = os.path.basename(fullpath)
423 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
422 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
424 # file was copied
423 # file was copied
425 self.log.warning("Staging bundled %s from %s into %r"%(
424 self.log.warning("Staging bundled %s from %s into %r"%(
426 cfg, self.profile, self.profile_dir.location)
425 cfg, self.profile, self.profile_dir.location)
427 )
426 )
428
427
429
428
430 def stage_default_config_file(self):
429 def stage_default_config_file(self):
431 """auto generate default config file, and stage it into the profile."""
430 """auto generate default config file, and stage it into the profile."""
432 s = self.generate_config_file()
431 s = self.generate_config_file()
433 fname = os.path.join(self.profile_dir.location, self.config_file_name)
432 fname = os.path.join(self.profile_dir.location, self.config_file_name)
434 if self.overwrite or not os.path.exists(fname):
433 if self.overwrite or not os.path.exists(fname):
435 self.log.warning("Generating default config file: %r"%(fname))
434 self.log.warning("Generating default config file: %r"%(fname))
436 with open(fname, 'w') as f:
435 with open(fname, 'w') as f:
437 f.write(s)
436 f.write(s)
438
437
439 @catch_config_error
438 @catch_config_error
440 def initialize(self, argv=None):
439 def initialize(self, argv=None):
441 # don't hook up crash handler before parsing command-line
440 # don't hook up crash handler before parsing command-line
442 self.parse_command_line(argv)
441 self.parse_command_line(argv)
443 self.init_crash_handler()
442 self.init_crash_handler()
444 if self.subapp is not None:
443 if self.subapp is not None:
445 # stop here if subapp is taking over
444 # stop here if subapp is taking over
446 return
445 return
447 # save a copy of CLI config to re-load after config files
446 # save a copy of CLI config to re-load after config files
448 # so that it has highest priority
447 # so that it has highest priority
449 cl_config = deepcopy(self.config)
448 cl_config = deepcopy(self.config)
450 self.init_profile_dir()
449 self.init_profile_dir()
451 self.init_config_files()
450 self.init_config_files()
452 self.load_config_file()
451 self.load_config_file()
453 # enforce cl-opts override configfile opts:
452 # enforce cl-opts override configfile opts:
454 self.update_config(cl_config)
453 self.update_config(cl_config)
@@ -1,157 +1,155 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """A class for managing IPython extensions."""
2 """A class for managing IPython extensions."""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7 import os
7 import os
8 import os.path
8 import os.path
9 import warnings
10 from shutil import copyfile
11 import sys
9 import sys
12 from importlib import import_module
10 from importlib import import_module
13
11
14 from traitlets.config.configurable import Configurable
12 from traitlets.config.configurable import Configurable
15 from IPython.utils.path import ensure_dir_exists, compress_user
13 from IPython.utils.path import ensure_dir_exists, compress_user
16 from IPython.utils.decorators import undoc
14 from IPython.utils.decorators import undoc
17 from traitlets import Instance
15 from traitlets import Instance
18
16
19 try:
17 try:
20 from importlib import reload
18 from importlib import reload
21 except ImportError :
19 except ImportError :
22 ## deprecated since 3.4
20 ## deprecated since 3.4
23 from imp import reload
21 from imp import reload
24
22
25 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
26 # Main class
24 # Main class
27 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
28
26
29 class ExtensionManager(Configurable):
27 class ExtensionManager(Configurable):
30 """A class to manage IPython extensions.
28 """A class to manage IPython extensions.
31
29
32 An IPython extension is an importable Python module that has
30 An IPython extension is an importable Python module that has
33 a function with the signature::
31 a function with the signature::
34
32
35 def load_ipython_extension(ipython):
33 def load_ipython_extension(ipython):
36 # Do things with ipython
34 # Do things with ipython
37
35
38 This function is called after your extension is imported and the
36 This function is called after your extension is imported and the
39 currently active :class:`InteractiveShell` instance is passed as
37 currently active :class:`InteractiveShell` instance is passed as
40 the only argument. You can do anything you want with IPython at
38 the only argument. You can do anything you want with IPython at
41 that point, including defining new magic and aliases, adding new
39 that point, including defining new magic and aliases, adding new
42 components, etc.
40 components, etc.
43
41
44 You can also optionally define an :func:`unload_ipython_extension(ipython)`
42 You can also optionally define an :func:`unload_ipython_extension(ipython)`
45 function, which will be called if the user unloads or reloads the extension.
43 function, which will be called if the user unloads or reloads the extension.
46 The extension manager will only call :func:`load_ipython_extension` again
44 The extension manager will only call :func:`load_ipython_extension` again
47 if the extension is reloaded.
45 if the extension is reloaded.
48
46
49 You can put your extension modules anywhere you want, as long as
47 You can put your extension modules anywhere you want, as long as
50 they can be imported by Python's standard import mechanism. However,
48 they can be imported by Python's standard import mechanism. However,
51 to make it easy to write extensions, you can also put your extensions
49 to make it easy to write extensions, you can also put your extensions
52 in ``os.path.join(self.ipython_dir, 'extensions')``. This directory
50 in ``os.path.join(self.ipython_dir, 'extensions')``. This directory
53 is added to ``sys.path`` automatically.
51 is added to ``sys.path`` automatically.
54 """
52 """
55
53
56 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
54 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
57
55
58 def __init__(self, shell=None, **kwargs):
56 def __init__(self, shell=None, **kwargs):
59 super(ExtensionManager, self).__init__(shell=shell, **kwargs)
57 super(ExtensionManager, self).__init__(shell=shell, **kwargs)
60 self.shell.observe(
58 self.shell.observe(
61 self._on_ipython_dir_changed, names=('ipython_dir',)
59 self._on_ipython_dir_changed, names=('ipython_dir',)
62 )
60 )
63 self.loaded = set()
61 self.loaded = set()
64
62
65 @property
63 @property
66 def ipython_extension_dir(self):
64 def ipython_extension_dir(self):
67 return os.path.join(self.shell.ipython_dir, u'extensions')
65 return os.path.join(self.shell.ipython_dir, u'extensions')
68
66
69 def _on_ipython_dir_changed(self, change):
67 def _on_ipython_dir_changed(self, change):
70 ensure_dir_exists(self.ipython_extension_dir)
68 ensure_dir_exists(self.ipython_extension_dir)
71
69
72 def load_extension(self, module_str):
70 def load_extension(self, module_str):
73 """Load an IPython extension by its module name.
71 """Load an IPython extension by its module name.
74
72
75 Returns the string "already loaded" if the extension is already loaded,
73 Returns the string "already loaded" if the extension is already loaded,
76 "no load function" if the module doesn't have a load_ipython_extension
74 "no load function" if the module doesn't have a load_ipython_extension
77 function, or None if it succeeded.
75 function, or None if it succeeded.
78 """
76 """
79 if module_str in self.loaded:
77 if module_str in self.loaded:
80 return "already loaded"
78 return "already loaded"
81
79
82 from IPython.utils.syspathcontext import prepended_to_syspath
80 from IPython.utils.syspathcontext import prepended_to_syspath
83
81
84 with self.shell.builtin_trap:
82 with self.shell.builtin_trap:
85 if module_str not in sys.modules:
83 if module_str not in sys.modules:
86 with prepended_to_syspath(self.ipython_extension_dir):
84 with prepended_to_syspath(self.ipython_extension_dir):
87 mod = import_module(module_str)
85 mod = import_module(module_str)
88 if mod.__file__.startswith(self.ipython_extension_dir):
86 if mod.__file__.startswith(self.ipython_extension_dir):
89 print(("Loading extensions from {dir} is deprecated. "
87 print(("Loading extensions from {dir} is deprecated. "
90 "We recommend managing extensions like any "
88 "We recommend managing extensions like any "
91 "other Python packages, in site-packages.").format(
89 "other Python packages, in site-packages.").format(
92 dir=compress_user(self.ipython_extension_dir)))
90 dir=compress_user(self.ipython_extension_dir)))
93 mod = sys.modules[module_str]
91 mod = sys.modules[module_str]
94 if self._call_load_ipython_extension(mod):
92 if self._call_load_ipython_extension(mod):
95 self.loaded.add(module_str)
93 self.loaded.add(module_str)
96 else:
94 else:
97 return "no load function"
95 return "no load function"
98
96
99 def unload_extension(self, module_str):
97 def unload_extension(self, module_str):
100 """Unload an IPython extension by its module name.
98 """Unload an IPython extension by its module name.
101
99
102 This function looks up the extension's name in ``sys.modules`` and
100 This function looks up the extension's name in ``sys.modules`` and
103 simply calls ``mod.unload_ipython_extension(self)``.
101 simply calls ``mod.unload_ipython_extension(self)``.
104
102
105 Returns the string "no unload function" if the extension doesn't define
103 Returns the string "no unload function" if the extension doesn't define
106 a function to unload itself, "not loaded" if the extension isn't loaded,
104 a function to unload itself, "not loaded" if the extension isn't loaded,
107 otherwise None.
105 otherwise None.
108 """
106 """
109 if module_str not in self.loaded:
107 if module_str not in self.loaded:
110 return "not loaded"
108 return "not loaded"
111
109
112 if module_str in sys.modules:
110 if module_str in sys.modules:
113 mod = sys.modules[module_str]
111 mod = sys.modules[module_str]
114 if self._call_unload_ipython_extension(mod):
112 if self._call_unload_ipython_extension(mod):
115 self.loaded.discard(module_str)
113 self.loaded.discard(module_str)
116 else:
114 else:
117 return "no unload function"
115 return "no unload function"
118
116
119 def reload_extension(self, module_str):
117 def reload_extension(self, module_str):
120 """Reload an IPython extension by calling reload.
118 """Reload an IPython extension by calling reload.
121
119
122 If the module has not been loaded before,
120 If the module has not been loaded before,
123 :meth:`InteractiveShell.load_extension` is called. Otherwise
121 :meth:`InteractiveShell.load_extension` is called. Otherwise
124 :func:`reload` is called and then the :func:`load_ipython_extension`
122 :func:`reload` is called and then the :func:`load_ipython_extension`
125 function of the module, if it exists is called.
123 function of the module, if it exists is called.
126 """
124 """
127 from IPython.utils.syspathcontext import prepended_to_syspath
125 from IPython.utils.syspathcontext import prepended_to_syspath
128
126
129 if (module_str in self.loaded) and (module_str in sys.modules):
127 if (module_str in self.loaded) and (module_str in sys.modules):
130 self.unload_extension(module_str)
128 self.unload_extension(module_str)
131 mod = sys.modules[module_str]
129 mod = sys.modules[module_str]
132 with prepended_to_syspath(self.ipython_extension_dir):
130 with prepended_to_syspath(self.ipython_extension_dir):
133 reload(mod)
131 reload(mod)
134 if self._call_load_ipython_extension(mod):
132 if self._call_load_ipython_extension(mod):
135 self.loaded.add(module_str)
133 self.loaded.add(module_str)
136 else:
134 else:
137 self.load_extension(module_str)
135 self.load_extension(module_str)
138
136
139 def _call_load_ipython_extension(self, mod):
137 def _call_load_ipython_extension(self, mod):
140 if hasattr(mod, 'load_ipython_extension'):
138 if hasattr(mod, 'load_ipython_extension'):
141 mod.load_ipython_extension(self.shell)
139 mod.load_ipython_extension(self.shell)
142 return True
140 return True
143
141
144 def _call_unload_ipython_extension(self, mod):
142 def _call_unload_ipython_extension(self, mod):
145 if hasattr(mod, 'unload_ipython_extension'):
143 if hasattr(mod, 'unload_ipython_extension'):
146 mod.unload_ipython_extension(self.shell)
144 mod.unload_ipython_extension(self.shell)
147 return True
145 return True
148
146
149 @undoc
147 @undoc
150 def install_extension(self, url, filename=None):
148 def install_extension(self, url, filename=None):
151 """
149 """
152 Deprecated.
150 Deprecated.
153 """
151 """
154 # Ensure the extension directory exists
152 # Ensure the extension directory exists
155 raise DeprecationWarning(
153 raise DeprecationWarning(
156 '`install_extension` and the `install_ext` magic have been deprecated since IPython 4.0'
154 '`install_extension` and the `install_ext` magic have been deprecated since IPython 4.0'
157 'Use pip or other package managers to manage ipython extensions.')
155 'Use pip or other package managers to manage ipython extensions.')
@@ -1,907 +1,906 b''
1 """ History related magics and functionality """
1 """ History related magics and functionality """
2
2
3 # Copyright (c) IPython Development Team.
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
4 # Distributed under the terms of the Modified BSD License.
5
5
6
6
7 import atexit
7 import atexit
8 import datetime
8 import datetime
9 import os
9 import os
10 import re
10 import re
11 try:
11 try:
12 import sqlite3
12 import sqlite3
13 except ImportError:
13 except ImportError:
14 try:
14 try:
15 from pysqlite2 import dbapi2 as sqlite3
15 from pysqlite2 import dbapi2 as sqlite3
16 except ImportError:
16 except ImportError:
17 sqlite3 = None
17 sqlite3 = None
18 import threading
18 import threading
19
19
20 from traitlets.config.configurable import LoggingConfigurable
20 from traitlets.config.configurable import LoggingConfigurable
21 from decorator import decorator
21 from decorator import decorator
22 from IPython.utils.decorators import undoc
22 from IPython.utils.decorators import undoc
23 from IPython.utils.path import locate_profile
23 from IPython.utils.path import locate_profile
24 from IPython.utils import py3compat
25 from traitlets import (
24 from traitlets import (
26 Any, Bool, Dict, Instance, Integer, List, Unicode, TraitError,
25 Any, Bool, Dict, Instance, Integer, List, Unicode, TraitError,
27 default, observe,
26 default, observe,
28 )
27 )
29 from warnings import warn
28 from warnings import warn
30
29
31 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
32 # Classes and functions
31 # Classes and functions
33 #-----------------------------------------------------------------------------
32 #-----------------------------------------------------------------------------
34
33
35 @undoc
34 @undoc
36 class DummyDB(object):
35 class DummyDB(object):
37 """Dummy DB that will act as a black hole for history.
36 """Dummy DB that will act as a black hole for history.
38
37
39 Only used in the absence of sqlite"""
38 Only used in the absence of sqlite"""
40 def execute(*args, **kwargs):
39 def execute(*args, **kwargs):
41 return []
40 return []
42
41
43 def commit(self, *args, **kwargs):
42 def commit(self, *args, **kwargs):
44 pass
43 pass
45
44
46 def __enter__(self, *args, **kwargs):
45 def __enter__(self, *args, **kwargs):
47 pass
46 pass
48
47
49 def __exit__(self, *args, **kwargs):
48 def __exit__(self, *args, **kwargs):
50 pass
49 pass
51
50
52
51
53 @decorator
52 @decorator
54 def needs_sqlite(f, self, *a, **kw):
53 def needs_sqlite(f, self, *a, **kw):
55 """Decorator: return an empty list in the absence of sqlite."""
54 """Decorator: return an empty list in the absence of sqlite."""
56 if sqlite3 is None or not self.enabled:
55 if sqlite3 is None or not self.enabled:
57 return []
56 return []
58 else:
57 else:
59 return f(self, *a, **kw)
58 return f(self, *a, **kw)
60
59
61
60
62 if sqlite3 is not None:
61 if sqlite3 is not None:
63 DatabaseError = sqlite3.DatabaseError
62 DatabaseError = sqlite3.DatabaseError
64 OperationalError = sqlite3.OperationalError
63 OperationalError = sqlite3.OperationalError
65 else:
64 else:
66 @undoc
65 @undoc
67 class DatabaseError(Exception):
66 class DatabaseError(Exception):
68 "Dummy exception when sqlite could not be imported. Should never occur."
67 "Dummy exception when sqlite could not be imported. Should never occur."
69
68
70 @undoc
69 @undoc
71 class OperationalError(Exception):
70 class OperationalError(Exception):
72 "Dummy exception when sqlite could not be imported. Should never occur."
71 "Dummy exception when sqlite could not be imported. Should never occur."
73
72
74 # use 16kB as threshold for whether a corrupt history db should be saved
73 # use 16kB as threshold for whether a corrupt history db should be saved
75 # that should be at least 100 entries or so
74 # that should be at least 100 entries or so
76 _SAVE_DB_SIZE = 16384
75 _SAVE_DB_SIZE = 16384
77
76
78 @decorator
77 @decorator
79 def catch_corrupt_db(f, self, *a, **kw):
78 def catch_corrupt_db(f, self, *a, **kw):
80 """A decorator which wraps HistoryAccessor method calls to catch errors from
79 """A decorator which wraps HistoryAccessor method calls to catch errors from
81 a corrupt SQLite database, move the old database out of the way, and create
80 a corrupt SQLite database, move the old database out of the way, and create
82 a new one.
81 a new one.
83
82
84 We avoid clobbering larger databases because this may be triggered due to filesystem issues,
83 We avoid clobbering larger databases because this may be triggered due to filesystem issues,
85 not just a corrupt file.
84 not just a corrupt file.
86 """
85 """
87 try:
86 try:
88 return f(self, *a, **kw)
87 return f(self, *a, **kw)
89 except (DatabaseError, OperationalError) as e:
88 except (DatabaseError, OperationalError) as e:
90 self._corrupt_db_counter += 1
89 self._corrupt_db_counter += 1
91 self.log.error("Failed to open SQLite history %s (%s).", self.hist_file, e)
90 self.log.error("Failed to open SQLite history %s (%s).", self.hist_file, e)
92 if self.hist_file != ':memory:':
91 if self.hist_file != ':memory:':
93 if self._corrupt_db_counter > self._corrupt_db_limit:
92 if self._corrupt_db_counter > self._corrupt_db_limit:
94 self.hist_file = ':memory:'
93 self.hist_file = ':memory:'
95 self.log.error("Failed to load history too many times, history will not be saved.")
94 self.log.error("Failed to load history too many times, history will not be saved.")
96 elif os.path.isfile(self.hist_file):
95 elif os.path.isfile(self.hist_file):
97 # move the file out of the way
96 # move the file out of the way
98 base, ext = os.path.splitext(self.hist_file)
97 base, ext = os.path.splitext(self.hist_file)
99 size = os.stat(self.hist_file).st_size
98 size = os.stat(self.hist_file).st_size
100 if size >= _SAVE_DB_SIZE:
99 if size >= _SAVE_DB_SIZE:
101 # if there's significant content, avoid clobbering
100 # if there's significant content, avoid clobbering
102 now = datetime.datetime.now().isoformat().replace(':', '.')
101 now = datetime.datetime.now().isoformat().replace(':', '.')
103 newpath = base + '-corrupt-' + now + ext
102 newpath = base + '-corrupt-' + now + ext
104 # don't clobber previous corrupt backups
103 # don't clobber previous corrupt backups
105 for i in range(100):
104 for i in range(100):
106 if not os.path.isfile(newpath):
105 if not os.path.isfile(newpath):
107 break
106 break
108 else:
107 else:
109 newpath = base + '-corrupt-' + now + (u'-%i' % i) + ext
108 newpath = base + '-corrupt-' + now + (u'-%i' % i) + ext
110 else:
109 else:
111 # not much content, possibly empty; don't worry about clobbering
110 # not much content, possibly empty; don't worry about clobbering
112 # maybe we should just delete it?
111 # maybe we should just delete it?
113 newpath = base + '-corrupt' + ext
112 newpath = base + '-corrupt' + ext
114 os.rename(self.hist_file, newpath)
113 os.rename(self.hist_file, newpath)
115 self.log.error("History file was moved to %s and a new file created.", newpath)
114 self.log.error("History file was moved to %s and a new file created.", newpath)
116 self.init_db()
115 self.init_db()
117 return []
116 return []
118 else:
117 else:
119 # Failed with :memory:, something serious is wrong
118 # Failed with :memory:, something serious is wrong
120 raise
119 raise
121
120
122 class HistoryAccessorBase(LoggingConfigurable):
121 class HistoryAccessorBase(LoggingConfigurable):
123 """An abstract class for History Accessors """
122 """An abstract class for History Accessors """
124
123
125 def get_tail(self, n=10, raw=True, output=False, include_latest=False):
124 def get_tail(self, n=10, raw=True, output=False, include_latest=False):
126 raise NotImplementedError
125 raise NotImplementedError
127
126
128 def search(self, pattern="*", raw=True, search_raw=True,
127 def search(self, pattern="*", raw=True, search_raw=True,
129 output=False, n=None, unique=False):
128 output=False, n=None, unique=False):
130 raise NotImplementedError
129 raise NotImplementedError
131
130
132 def get_range(self, session, start=1, stop=None, raw=True,output=False):
131 def get_range(self, session, start=1, stop=None, raw=True,output=False):
133 raise NotImplementedError
132 raise NotImplementedError
134
133
135 def get_range_by_str(self, rangestr, raw=True, output=False):
134 def get_range_by_str(self, rangestr, raw=True, output=False):
136 raise NotImplementedError
135 raise NotImplementedError
137
136
138
137
139 class HistoryAccessor(HistoryAccessorBase):
138 class HistoryAccessor(HistoryAccessorBase):
140 """Access the history database without adding to it.
139 """Access the history database without adding to it.
141
140
142 This is intended for use by standalone history tools. IPython shells use
141 This is intended for use by standalone history tools. IPython shells use
143 HistoryManager, below, which is a subclass of this."""
142 HistoryManager, below, which is a subclass of this."""
144
143
145 # counter for init_db retries, so we don't keep trying over and over
144 # counter for init_db retries, so we don't keep trying over and over
146 _corrupt_db_counter = 0
145 _corrupt_db_counter = 0
147 # after two failures, fallback on :memory:
146 # after two failures, fallback on :memory:
148 _corrupt_db_limit = 2
147 _corrupt_db_limit = 2
149
148
150 # String holding the path to the history file
149 # String holding the path to the history file
151 hist_file = Unicode(
150 hist_file = Unicode(
152 help="""Path to file to use for SQLite history database.
151 help="""Path to file to use for SQLite history database.
153
152
154 By default, IPython will put the history database in the IPython
153 By default, IPython will put the history database in the IPython
155 profile directory. If you would rather share one history among
154 profile directory. If you would rather share one history among
156 profiles, you can set this value in each, so that they are consistent.
155 profiles, you can set this value in each, so that they are consistent.
157
156
158 Due to an issue with fcntl, SQLite is known to misbehave on some NFS
157 Due to an issue with fcntl, SQLite is known to misbehave on some NFS
159 mounts. If you see IPython hanging, try setting this to something on a
158 mounts. If you see IPython hanging, try setting this to something on a
160 local disk, e.g::
159 local disk, e.g::
161
160
162 ipython --HistoryManager.hist_file=/tmp/ipython_hist.sqlite
161 ipython --HistoryManager.hist_file=/tmp/ipython_hist.sqlite
163
162
164 you can also use the specific value `:memory:` (including the colon
163 you can also use the specific value `:memory:` (including the colon
165 at both end but not the back ticks), to avoid creating an history file.
164 at both end but not the back ticks), to avoid creating an history file.
166
165
167 """).tag(config=True)
166 """).tag(config=True)
168
167
169 enabled = Bool(True,
168 enabled = Bool(True,
170 help="""enable the SQLite history
169 help="""enable the SQLite history
171
170
172 set enabled=False to disable the SQLite history,
171 set enabled=False to disable the SQLite history,
173 in which case there will be no stored history, no SQLite connection,
172 in which case there will be no stored history, no SQLite connection,
174 and no background saving thread. This may be necessary in some
173 and no background saving thread. This may be necessary in some
175 threaded environments where IPython is embedded.
174 threaded environments where IPython is embedded.
176 """
175 """
177 ).tag(config=True)
176 ).tag(config=True)
178
177
179 connection_options = Dict(
178 connection_options = Dict(
180 help="""Options for configuring the SQLite connection
179 help="""Options for configuring the SQLite connection
181
180
182 These options are passed as keyword args to sqlite3.connect
181 These options are passed as keyword args to sqlite3.connect
183 when establishing database conenctions.
182 when establishing database conenctions.
184 """
183 """
185 ).tag(config=True)
184 ).tag(config=True)
186
185
187 # The SQLite database
186 # The SQLite database
188 db = Any()
187 db = Any()
189 @observe('db')
188 @observe('db')
190 def _db_changed(self, change):
189 def _db_changed(self, change):
191 """validate the db, since it can be an Instance of two different types"""
190 """validate the db, since it can be an Instance of two different types"""
192 new = change['new']
191 new = change['new']
193 connection_types = (DummyDB,)
192 connection_types = (DummyDB,)
194 if sqlite3 is not None:
193 if sqlite3 is not None:
195 connection_types = (DummyDB, sqlite3.Connection)
194 connection_types = (DummyDB, sqlite3.Connection)
196 if not isinstance(new, connection_types):
195 if not isinstance(new, connection_types):
197 msg = "%s.db must be sqlite3 Connection or DummyDB, not %r" % \
196 msg = "%s.db must be sqlite3 Connection or DummyDB, not %r" % \
198 (self.__class__.__name__, new)
197 (self.__class__.__name__, new)
199 raise TraitError(msg)
198 raise TraitError(msg)
200
199
201 def __init__(self, profile='default', hist_file=u'', **traits):
200 def __init__(self, profile='default', hist_file=u'', **traits):
202 """Create a new history accessor.
201 """Create a new history accessor.
203
202
204 Parameters
203 Parameters
205 ----------
204 ----------
206 profile : str
205 profile : str
207 The name of the profile from which to open history.
206 The name of the profile from which to open history.
208 hist_file : str
207 hist_file : str
209 Path to an SQLite history database stored by IPython. If specified,
208 Path to an SQLite history database stored by IPython. If specified,
210 hist_file overrides profile.
209 hist_file overrides profile.
211 config : :class:`~traitlets.config.loader.Config`
210 config : :class:`~traitlets.config.loader.Config`
212 Config object. hist_file can also be set through this.
211 Config object. hist_file can also be set through this.
213 """
212 """
214 # We need a pointer back to the shell for various tasks.
213 # We need a pointer back to the shell for various tasks.
215 super(HistoryAccessor, self).__init__(**traits)
214 super(HistoryAccessor, self).__init__(**traits)
216 # defer setting hist_file from kwarg until after init,
215 # defer setting hist_file from kwarg until after init,
217 # otherwise the default kwarg value would clobber any value
216 # otherwise the default kwarg value would clobber any value
218 # set by config
217 # set by config
219 if hist_file:
218 if hist_file:
220 self.hist_file = hist_file
219 self.hist_file = hist_file
221
220
222 if self.hist_file == u'':
221 if self.hist_file == u'':
223 # No one has set the hist_file, yet.
222 # No one has set the hist_file, yet.
224 self.hist_file = self._get_hist_file_name(profile)
223 self.hist_file = self._get_hist_file_name(profile)
225
224
226 if sqlite3 is None and self.enabled:
225 if sqlite3 is None and self.enabled:
227 warn("IPython History requires SQLite, your history will not be saved")
226 warn("IPython History requires SQLite, your history will not be saved")
228 self.enabled = False
227 self.enabled = False
229
228
230 self.init_db()
229 self.init_db()
231
230
232 def _get_hist_file_name(self, profile='default'):
231 def _get_hist_file_name(self, profile='default'):
233 """Find the history file for the given profile name.
232 """Find the history file for the given profile name.
234
233
235 This is overridden by the HistoryManager subclass, to use the shell's
234 This is overridden by the HistoryManager subclass, to use the shell's
236 active profile.
235 active profile.
237
236
238 Parameters
237 Parameters
239 ----------
238 ----------
240 profile : str
239 profile : str
241 The name of a profile which has a history file.
240 The name of a profile which has a history file.
242 """
241 """
243 return os.path.join(locate_profile(profile), 'history.sqlite')
242 return os.path.join(locate_profile(profile), 'history.sqlite')
244
243
245 @catch_corrupt_db
244 @catch_corrupt_db
246 def init_db(self):
245 def init_db(self):
247 """Connect to the database, and create tables if necessary."""
246 """Connect to the database, and create tables if necessary."""
248 if not self.enabled:
247 if not self.enabled:
249 self.db = DummyDB()
248 self.db = DummyDB()
250 return
249 return
251
250
252 # use detect_types so that timestamps return datetime objects
251 # use detect_types so that timestamps return datetime objects
253 kwargs = dict(detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
252 kwargs = dict(detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
254 kwargs.update(self.connection_options)
253 kwargs.update(self.connection_options)
255 self.db = sqlite3.connect(self.hist_file, **kwargs)
254 self.db = sqlite3.connect(self.hist_file, **kwargs)
256 self.db.execute("""CREATE TABLE IF NOT EXISTS sessions (session integer
255 self.db.execute("""CREATE TABLE IF NOT EXISTS sessions (session integer
257 primary key autoincrement, start timestamp,
256 primary key autoincrement, start timestamp,
258 end timestamp, num_cmds integer, remark text)""")
257 end timestamp, num_cmds integer, remark text)""")
259 self.db.execute("""CREATE TABLE IF NOT EXISTS history
258 self.db.execute("""CREATE TABLE IF NOT EXISTS history
260 (session integer, line integer, source text, source_raw text,
259 (session integer, line integer, source text, source_raw text,
261 PRIMARY KEY (session, line))""")
260 PRIMARY KEY (session, line))""")
262 # Output history is optional, but ensure the table's there so it can be
261 # Output history is optional, but ensure the table's there so it can be
263 # enabled later.
262 # enabled later.
264 self.db.execute("""CREATE TABLE IF NOT EXISTS output_history
263 self.db.execute("""CREATE TABLE IF NOT EXISTS output_history
265 (session integer, line integer, output text,
264 (session integer, line integer, output text,
266 PRIMARY KEY (session, line))""")
265 PRIMARY KEY (session, line))""")
267 self.db.commit()
266 self.db.commit()
268 # success! reset corrupt db count
267 # success! reset corrupt db count
269 self._corrupt_db_counter = 0
268 self._corrupt_db_counter = 0
270
269
271 def writeout_cache(self):
270 def writeout_cache(self):
272 """Overridden by HistoryManager to dump the cache before certain
271 """Overridden by HistoryManager to dump the cache before certain
273 database lookups."""
272 database lookups."""
274 pass
273 pass
275
274
276 ## -------------------------------
275 ## -------------------------------
277 ## Methods for retrieving history:
276 ## Methods for retrieving history:
278 ## -------------------------------
277 ## -------------------------------
279 def _run_sql(self, sql, params, raw=True, output=False):
278 def _run_sql(self, sql, params, raw=True, output=False):
280 """Prepares and runs an SQL query for the history database.
279 """Prepares and runs an SQL query for the history database.
281
280
282 Parameters
281 Parameters
283 ----------
282 ----------
284 sql : str
283 sql : str
285 Any filtering expressions to go after SELECT ... FROM ...
284 Any filtering expressions to go after SELECT ... FROM ...
286 params : tuple
285 params : tuple
287 Parameters passed to the SQL query (to replace "?")
286 Parameters passed to the SQL query (to replace "?")
288 raw, output : bool
287 raw, output : bool
289 See :meth:`get_range`
288 See :meth:`get_range`
290
289
291 Returns
290 Returns
292 -------
291 -------
293 Tuples as :meth:`get_range`
292 Tuples as :meth:`get_range`
294 """
293 """
295 toget = 'source_raw' if raw else 'source'
294 toget = 'source_raw' if raw else 'source'
296 sqlfrom = "history"
295 sqlfrom = "history"
297 if output:
296 if output:
298 sqlfrom = "history LEFT JOIN output_history USING (session, line)"
297 sqlfrom = "history LEFT JOIN output_history USING (session, line)"
299 toget = "history.%s, output_history.output" % toget
298 toget = "history.%s, output_history.output" % toget
300 cur = self.db.execute("SELECT session, line, %s FROM %s " %\
299 cur = self.db.execute("SELECT session, line, %s FROM %s " %\
301 (toget, sqlfrom) + sql, params)
300 (toget, sqlfrom) + sql, params)
302 if output: # Regroup into 3-tuples, and parse JSON
301 if output: # Regroup into 3-tuples, and parse JSON
303 return ((ses, lin, (inp, out)) for ses, lin, inp, out in cur)
302 return ((ses, lin, (inp, out)) for ses, lin, inp, out in cur)
304 return cur
303 return cur
305
304
306 @needs_sqlite
305 @needs_sqlite
307 @catch_corrupt_db
306 @catch_corrupt_db
308 def get_session_info(self, session):
307 def get_session_info(self, session):
309 """Get info about a session.
308 """Get info about a session.
310
309
311 Parameters
310 Parameters
312 ----------
311 ----------
313
312
314 session : int
313 session : int
315 Session number to retrieve.
314 Session number to retrieve.
316
315
317 Returns
316 Returns
318 -------
317 -------
319
318
320 session_id : int
319 session_id : int
321 Session ID number
320 Session ID number
322 start : datetime
321 start : datetime
323 Timestamp for the start of the session.
322 Timestamp for the start of the session.
324 end : datetime
323 end : datetime
325 Timestamp for the end of the session, or None if IPython crashed.
324 Timestamp for the end of the session, or None if IPython crashed.
326 num_cmds : int
325 num_cmds : int
327 Number of commands run, or None if IPython crashed.
326 Number of commands run, or None if IPython crashed.
328 remark : unicode
327 remark : unicode
329 A manually set description.
328 A manually set description.
330 """
329 """
331 query = "SELECT * from sessions where session == ?"
330 query = "SELECT * from sessions where session == ?"
332 return self.db.execute(query, (session,)).fetchone()
331 return self.db.execute(query, (session,)).fetchone()
333
332
334 @catch_corrupt_db
333 @catch_corrupt_db
335 def get_last_session_id(self):
334 def get_last_session_id(self):
336 """Get the last session ID currently in the database.
335 """Get the last session ID currently in the database.
337
336
338 Within IPython, this should be the same as the value stored in
337 Within IPython, this should be the same as the value stored in
339 :attr:`HistoryManager.session_number`.
338 :attr:`HistoryManager.session_number`.
340 """
339 """
341 for record in self.get_tail(n=1, include_latest=True):
340 for record in self.get_tail(n=1, include_latest=True):
342 return record[0]
341 return record[0]
343
342
344 @catch_corrupt_db
343 @catch_corrupt_db
345 def get_tail(self, n=10, raw=True, output=False, include_latest=False):
344 def get_tail(self, n=10, raw=True, output=False, include_latest=False):
346 """Get the last n lines from the history database.
345 """Get the last n lines from the history database.
347
346
348 Parameters
347 Parameters
349 ----------
348 ----------
350 n : int
349 n : int
351 The number of lines to get
350 The number of lines to get
352 raw, output : bool
351 raw, output : bool
353 See :meth:`get_range`
352 See :meth:`get_range`
354 include_latest : bool
353 include_latest : bool
355 If False (default), n+1 lines are fetched, and the latest one
354 If False (default), n+1 lines are fetched, and the latest one
356 is discarded. This is intended to be used where the function
355 is discarded. This is intended to be used where the function
357 is called by a user command, which it should not return.
356 is called by a user command, which it should not return.
358
357
359 Returns
358 Returns
360 -------
359 -------
361 Tuples as :meth:`get_range`
360 Tuples as :meth:`get_range`
362 """
361 """
363 self.writeout_cache()
362 self.writeout_cache()
364 if not include_latest:
363 if not include_latest:
365 n += 1
364 n += 1
366 cur = self._run_sql("ORDER BY session DESC, line DESC LIMIT ?",
365 cur = self._run_sql("ORDER BY session DESC, line DESC LIMIT ?",
367 (n,), raw=raw, output=output)
366 (n,), raw=raw, output=output)
368 if not include_latest:
367 if not include_latest:
369 return reversed(list(cur)[1:])
368 return reversed(list(cur)[1:])
370 return reversed(list(cur))
369 return reversed(list(cur))
371
370
372 @catch_corrupt_db
371 @catch_corrupt_db
373 def search(self, pattern="*", raw=True, search_raw=True,
372 def search(self, pattern="*", raw=True, search_raw=True,
374 output=False, n=None, unique=False):
373 output=False, n=None, unique=False):
375 """Search the database using unix glob-style matching (wildcards
374 """Search the database using unix glob-style matching (wildcards
376 * and ?).
375 * and ?).
377
376
378 Parameters
377 Parameters
379 ----------
378 ----------
380 pattern : str
379 pattern : str
381 The wildcarded pattern to match when searching
380 The wildcarded pattern to match when searching
382 search_raw : bool
381 search_raw : bool
383 If True, search the raw input, otherwise, the parsed input
382 If True, search the raw input, otherwise, the parsed input
384 raw, output : bool
383 raw, output : bool
385 See :meth:`get_range`
384 See :meth:`get_range`
386 n : None or int
385 n : None or int
387 If an integer is given, it defines the limit of
386 If an integer is given, it defines the limit of
388 returned entries.
387 returned entries.
389 unique : bool
388 unique : bool
390 When it is true, return only unique entries.
389 When it is true, return only unique entries.
391
390
392 Returns
391 Returns
393 -------
392 -------
394 Tuples as :meth:`get_range`
393 Tuples as :meth:`get_range`
395 """
394 """
396 tosearch = "source_raw" if search_raw else "source"
395 tosearch = "source_raw" if search_raw else "source"
397 if output:
396 if output:
398 tosearch = "history." + tosearch
397 tosearch = "history." + tosearch
399 self.writeout_cache()
398 self.writeout_cache()
400 sqlform = "WHERE %s GLOB ?" % tosearch
399 sqlform = "WHERE %s GLOB ?" % tosearch
401 params = (pattern,)
400 params = (pattern,)
402 if unique:
401 if unique:
403 sqlform += ' GROUP BY {0}'.format(tosearch)
402 sqlform += ' GROUP BY {0}'.format(tosearch)
404 if n is not None:
403 if n is not None:
405 sqlform += " ORDER BY session DESC, line DESC LIMIT ?"
404 sqlform += " ORDER BY session DESC, line DESC LIMIT ?"
406 params += (n,)
405 params += (n,)
407 elif unique:
406 elif unique:
408 sqlform += " ORDER BY session, line"
407 sqlform += " ORDER BY session, line"
409 cur = self._run_sql(sqlform, params, raw=raw, output=output)
408 cur = self._run_sql(sqlform, params, raw=raw, output=output)
410 if n is not None:
409 if n is not None:
411 return reversed(list(cur))
410 return reversed(list(cur))
412 return cur
411 return cur
413
412
414 @catch_corrupt_db
413 @catch_corrupt_db
415 def get_range(self, session, start=1, stop=None, raw=True,output=False):
414 def get_range(self, session, start=1, stop=None, raw=True,output=False):
416 """Retrieve input by session.
415 """Retrieve input by session.
417
416
418 Parameters
417 Parameters
419 ----------
418 ----------
420 session : int
419 session : int
421 Session number to retrieve.
420 Session number to retrieve.
422 start : int
421 start : int
423 First line to retrieve.
422 First line to retrieve.
424 stop : int
423 stop : int
425 End of line range (excluded from output itself). If None, retrieve
424 End of line range (excluded from output itself). If None, retrieve
426 to the end of the session.
425 to the end of the session.
427 raw : bool
426 raw : bool
428 If True, return untranslated input
427 If True, return untranslated input
429 output : bool
428 output : bool
430 If True, attempt to include output. This will be 'real' Python
429 If True, attempt to include output. This will be 'real' Python
431 objects for the current session, or text reprs from previous
430 objects for the current session, or text reprs from previous
432 sessions if db_log_output was enabled at the time. Where no output
431 sessions if db_log_output was enabled at the time. Where no output
433 is found, None is used.
432 is found, None is used.
434
433
435 Returns
434 Returns
436 -------
435 -------
437 entries
436 entries
438 An iterator over the desired lines. Each line is a 3-tuple, either
437 An iterator over the desired lines. Each line is a 3-tuple, either
439 (session, line, input) if output is False, or
438 (session, line, input) if output is False, or
440 (session, line, (input, output)) if output is True.
439 (session, line, (input, output)) if output is True.
441 """
440 """
442 if stop:
441 if stop:
443 lineclause = "line >= ? AND line < ?"
442 lineclause = "line >= ? AND line < ?"
444 params = (session, start, stop)
443 params = (session, start, stop)
445 else:
444 else:
446 lineclause = "line>=?"
445 lineclause = "line>=?"
447 params = (session, start)
446 params = (session, start)
448
447
449 return self._run_sql("WHERE session==? AND %s" % lineclause,
448 return self._run_sql("WHERE session==? AND %s" % lineclause,
450 params, raw=raw, output=output)
449 params, raw=raw, output=output)
451
450
452 def get_range_by_str(self, rangestr, raw=True, output=False):
451 def get_range_by_str(self, rangestr, raw=True, output=False):
453 """Get lines of history from a string of ranges, as used by magic
452 """Get lines of history from a string of ranges, as used by magic
454 commands %hist, %save, %macro, etc.
453 commands %hist, %save, %macro, etc.
455
454
456 Parameters
455 Parameters
457 ----------
456 ----------
458 rangestr : str
457 rangestr : str
459 A string specifying ranges, e.g. "5 ~2/1-4". See
458 A string specifying ranges, e.g. "5 ~2/1-4". See
460 :func:`magic_history` for full details.
459 :func:`magic_history` for full details.
461 raw, output : bool
460 raw, output : bool
462 As :meth:`get_range`
461 As :meth:`get_range`
463
462
464 Returns
463 Returns
465 -------
464 -------
466 Tuples as :meth:`get_range`
465 Tuples as :meth:`get_range`
467 """
466 """
468 for sess, s, e in extract_hist_ranges(rangestr):
467 for sess, s, e in extract_hist_ranges(rangestr):
469 for line in self.get_range(sess, s, e, raw=raw, output=output):
468 for line in self.get_range(sess, s, e, raw=raw, output=output):
470 yield line
469 yield line
471
470
472
471
473 class HistoryManager(HistoryAccessor):
472 class HistoryManager(HistoryAccessor):
474 """A class to organize all history-related functionality in one place.
473 """A class to organize all history-related functionality in one place.
475 """
474 """
476 # Public interface
475 # Public interface
477
476
478 # An instance of the IPython shell we are attached to
477 # An instance of the IPython shell we are attached to
479 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
478 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
480 allow_none=True)
479 allow_none=True)
481 # Lists to hold processed and raw history. These start with a blank entry
480 # Lists to hold processed and raw history. These start with a blank entry
482 # so that we can index them starting from 1
481 # so that we can index them starting from 1
483 input_hist_parsed = List([""])
482 input_hist_parsed = List([""])
484 input_hist_raw = List([""])
483 input_hist_raw = List([""])
485 # A list of directories visited during session
484 # A list of directories visited during session
486 dir_hist = List()
485 dir_hist = List()
487 @default('dir_hist')
486 @default('dir_hist')
488 def _dir_hist_default(self):
487 def _dir_hist_default(self):
489 try:
488 try:
490 return [os.getcwd()]
489 return [os.getcwd()]
491 except OSError:
490 except OSError:
492 return []
491 return []
493
492
494 # A dict of output history, keyed with ints from the shell's
493 # A dict of output history, keyed with ints from the shell's
495 # execution count.
494 # execution count.
496 output_hist = Dict()
495 output_hist = Dict()
497 # The text/plain repr of outputs.
496 # The text/plain repr of outputs.
498 output_hist_reprs = Dict()
497 output_hist_reprs = Dict()
499
498
500 # The number of the current session in the history database
499 # The number of the current session in the history database
501 session_number = Integer()
500 session_number = Integer()
502
501
503 db_log_output = Bool(False,
502 db_log_output = Bool(False,
504 help="Should the history database include output? (default: no)"
503 help="Should the history database include output? (default: no)"
505 ).tag(config=True)
504 ).tag(config=True)
506 db_cache_size = Integer(0,
505 db_cache_size = Integer(0,
507 help="Write to database every x commands (higher values save disk access & power).\n"
506 help="Write to database every x commands (higher values save disk access & power).\n"
508 "Values of 1 or less effectively disable caching."
507 "Values of 1 or less effectively disable caching."
509 ).tag(config=True)
508 ).tag(config=True)
510 # The input and output caches
509 # The input and output caches
511 db_input_cache = List()
510 db_input_cache = List()
512 db_output_cache = List()
511 db_output_cache = List()
513
512
514 # History saving in separate thread
513 # History saving in separate thread
515 save_thread = Instance('IPython.core.history.HistorySavingThread',
514 save_thread = Instance('IPython.core.history.HistorySavingThread',
516 allow_none=True)
515 allow_none=True)
517 save_flag = Instance(threading.Event, allow_none=True)
516 save_flag = Instance(threading.Event, allow_none=True)
518
517
519 # Private interface
518 # Private interface
520 # Variables used to store the three last inputs from the user. On each new
519 # Variables used to store the three last inputs from the user. On each new
521 # history update, we populate the user's namespace with these, shifted as
520 # history update, we populate the user's namespace with these, shifted as
522 # necessary.
521 # necessary.
523 _i00 = Unicode(u'')
522 _i00 = Unicode(u'')
524 _i = Unicode(u'')
523 _i = Unicode(u'')
525 _ii = Unicode(u'')
524 _ii = Unicode(u'')
526 _iii = Unicode(u'')
525 _iii = Unicode(u'')
527
526
528 # A regex matching all forms of the exit command, so that we don't store
527 # A regex matching all forms of the exit command, so that we don't store
529 # them in the history (it's annoying to rewind the first entry and land on
528 # them in the history (it's annoying to rewind the first entry and land on
530 # an exit call).
529 # an exit call).
531 _exit_re = re.compile(r"(exit|quit)(\s*\(.*\))?$")
530 _exit_re = re.compile(r"(exit|quit)(\s*\(.*\))?$")
532
531
533 def __init__(self, shell=None, config=None, **traits):
532 def __init__(self, shell=None, config=None, **traits):
534 """Create a new history manager associated with a shell instance.
533 """Create a new history manager associated with a shell instance.
535 """
534 """
536 # We need a pointer back to the shell for various tasks.
535 # We need a pointer back to the shell for various tasks.
537 super(HistoryManager, self).__init__(shell=shell, config=config,
536 super(HistoryManager, self).__init__(shell=shell, config=config,
538 **traits)
537 **traits)
539 self.save_flag = threading.Event()
538 self.save_flag = threading.Event()
540 self.db_input_cache_lock = threading.Lock()
539 self.db_input_cache_lock = threading.Lock()
541 self.db_output_cache_lock = threading.Lock()
540 self.db_output_cache_lock = threading.Lock()
542
541
543 try:
542 try:
544 self.new_session()
543 self.new_session()
545 except OperationalError:
544 except OperationalError:
546 self.log.error("Failed to create history session in %s. History will not be saved.",
545 self.log.error("Failed to create history session in %s. History will not be saved.",
547 self.hist_file, exc_info=True)
546 self.hist_file, exc_info=True)
548 self.hist_file = ':memory:'
547 self.hist_file = ':memory:'
549
548
550 if self.enabled and self.hist_file != ':memory:':
549 if self.enabled and self.hist_file != ':memory:':
551 self.save_thread = HistorySavingThread(self)
550 self.save_thread = HistorySavingThread(self)
552 self.save_thread.start()
551 self.save_thread.start()
553
552
554 def _get_hist_file_name(self, profile=None):
553 def _get_hist_file_name(self, profile=None):
555 """Get default history file name based on the Shell's profile.
554 """Get default history file name based on the Shell's profile.
556
555
557 The profile parameter is ignored, but must exist for compatibility with
556 The profile parameter is ignored, but must exist for compatibility with
558 the parent class."""
557 the parent class."""
559 profile_dir = self.shell.profile_dir.location
558 profile_dir = self.shell.profile_dir.location
560 return os.path.join(profile_dir, 'history.sqlite')
559 return os.path.join(profile_dir, 'history.sqlite')
561
560
562 @needs_sqlite
561 @needs_sqlite
563 def new_session(self, conn=None):
562 def new_session(self, conn=None):
564 """Get a new session number."""
563 """Get a new session number."""
565 if conn is None:
564 if conn is None:
566 conn = self.db
565 conn = self.db
567
566
568 with conn:
567 with conn:
569 cur = conn.execute("""INSERT INTO sessions VALUES (NULL, ?, NULL,
568 cur = conn.execute("""INSERT INTO sessions VALUES (NULL, ?, NULL,
570 NULL, "") """, (datetime.datetime.now(),))
569 NULL, "") """, (datetime.datetime.now(),))
571 self.session_number = cur.lastrowid
570 self.session_number = cur.lastrowid
572
571
573 def end_session(self):
572 def end_session(self):
574 """Close the database session, filling in the end time and line count."""
573 """Close the database session, filling in the end time and line count."""
575 self.writeout_cache()
574 self.writeout_cache()
576 with self.db:
575 with self.db:
577 self.db.execute("""UPDATE sessions SET end=?, num_cmds=? WHERE
576 self.db.execute("""UPDATE sessions SET end=?, num_cmds=? WHERE
578 session==?""", (datetime.datetime.now(),
577 session==?""", (datetime.datetime.now(),
579 len(self.input_hist_parsed)-1, self.session_number))
578 len(self.input_hist_parsed)-1, self.session_number))
580 self.session_number = 0
579 self.session_number = 0
581
580
582 def name_session(self, name):
581 def name_session(self, name):
583 """Give the current session a name in the history database."""
582 """Give the current session a name in the history database."""
584 with self.db:
583 with self.db:
585 self.db.execute("UPDATE sessions SET remark=? WHERE session==?",
584 self.db.execute("UPDATE sessions SET remark=? WHERE session==?",
586 (name, self.session_number))
585 (name, self.session_number))
587
586
588 def reset(self, new_session=True):
587 def reset(self, new_session=True):
589 """Clear the session history, releasing all object references, and
588 """Clear the session history, releasing all object references, and
590 optionally open a new session."""
589 optionally open a new session."""
591 self.output_hist.clear()
590 self.output_hist.clear()
592 # The directory history can't be completely empty
591 # The directory history can't be completely empty
593 self.dir_hist[:] = [os.getcwd()]
592 self.dir_hist[:] = [os.getcwd()]
594
593
595 if new_session:
594 if new_session:
596 if self.session_number:
595 if self.session_number:
597 self.end_session()
596 self.end_session()
598 self.input_hist_parsed[:] = [""]
597 self.input_hist_parsed[:] = [""]
599 self.input_hist_raw[:] = [""]
598 self.input_hist_raw[:] = [""]
600 self.new_session()
599 self.new_session()
601
600
602 # ------------------------------
601 # ------------------------------
603 # Methods for retrieving history
602 # Methods for retrieving history
604 # ------------------------------
603 # ------------------------------
605 def get_session_info(self, session=0):
604 def get_session_info(self, session=0):
606 """Get info about a session.
605 """Get info about a session.
607
606
608 Parameters
607 Parameters
609 ----------
608 ----------
610
609
611 session : int
610 session : int
612 Session number to retrieve. The current session is 0, and negative
611 Session number to retrieve. The current session is 0, and negative
613 numbers count back from current session, so -1 is the previous session.
612 numbers count back from current session, so -1 is the previous session.
614
613
615 Returns
614 Returns
616 -------
615 -------
617
616
618 session_id : int
617 session_id : int
619 Session ID number
618 Session ID number
620 start : datetime
619 start : datetime
621 Timestamp for the start of the session.
620 Timestamp for the start of the session.
622 end : datetime
621 end : datetime
623 Timestamp for the end of the session, or None if IPython crashed.
622 Timestamp for the end of the session, or None if IPython crashed.
624 num_cmds : int
623 num_cmds : int
625 Number of commands run, or None if IPython crashed.
624 Number of commands run, or None if IPython crashed.
626 remark : unicode
625 remark : unicode
627 A manually set description.
626 A manually set description.
628 """
627 """
629 if session <= 0:
628 if session <= 0:
630 session += self.session_number
629 session += self.session_number
631
630
632 return super(HistoryManager, self).get_session_info(session=session)
631 return super(HistoryManager, self).get_session_info(session=session)
633
632
634 def _get_range_session(self, start=1, stop=None, raw=True, output=False):
633 def _get_range_session(self, start=1, stop=None, raw=True, output=False):
635 """Get input and output history from the current session. Called by
634 """Get input and output history from the current session. Called by
636 get_range, and takes similar parameters."""
635 get_range, and takes similar parameters."""
637 input_hist = self.input_hist_raw if raw else self.input_hist_parsed
636 input_hist = self.input_hist_raw if raw else self.input_hist_parsed
638
637
639 n = len(input_hist)
638 n = len(input_hist)
640 if start < 0:
639 if start < 0:
641 start += n
640 start += n
642 if not stop or (stop > n):
641 if not stop or (stop > n):
643 stop = n
642 stop = n
644 elif stop < 0:
643 elif stop < 0:
645 stop += n
644 stop += n
646
645
647 for i in range(start, stop):
646 for i in range(start, stop):
648 if output:
647 if output:
649 line = (input_hist[i], self.output_hist_reprs.get(i))
648 line = (input_hist[i], self.output_hist_reprs.get(i))
650 else:
649 else:
651 line = input_hist[i]
650 line = input_hist[i]
652 yield (0, i, line)
651 yield (0, i, line)
653
652
654 def get_range(self, session=0, start=1, stop=None, raw=True,output=False):
653 def get_range(self, session=0, start=1, stop=None, raw=True,output=False):
655 """Retrieve input by session.
654 """Retrieve input by session.
656
655
657 Parameters
656 Parameters
658 ----------
657 ----------
659 session : int
658 session : int
660 Session number to retrieve. The current session is 0, and negative
659 Session number to retrieve. The current session is 0, and negative
661 numbers count back from current session, so -1 is previous session.
660 numbers count back from current session, so -1 is previous session.
662 start : int
661 start : int
663 First line to retrieve.
662 First line to retrieve.
664 stop : int
663 stop : int
665 End of line range (excluded from output itself). If None, retrieve
664 End of line range (excluded from output itself). If None, retrieve
666 to the end of the session.
665 to the end of the session.
667 raw : bool
666 raw : bool
668 If True, return untranslated input
667 If True, return untranslated input
669 output : bool
668 output : bool
670 If True, attempt to include output. This will be 'real' Python
669 If True, attempt to include output. This will be 'real' Python
671 objects for the current session, or text reprs from previous
670 objects for the current session, or text reprs from previous
672 sessions if db_log_output was enabled at the time. Where no output
671 sessions if db_log_output was enabled at the time. Where no output
673 is found, None is used.
672 is found, None is used.
674
673
675 Returns
674 Returns
676 -------
675 -------
677 entries
676 entries
678 An iterator over the desired lines. Each line is a 3-tuple, either
677 An iterator over the desired lines. Each line is a 3-tuple, either
679 (session, line, input) if output is False, or
678 (session, line, input) if output is False, or
680 (session, line, (input, output)) if output is True.
679 (session, line, (input, output)) if output is True.
681 """
680 """
682 if session <= 0:
681 if session <= 0:
683 session += self.session_number
682 session += self.session_number
684 if session==self.session_number: # Current session
683 if session==self.session_number: # Current session
685 return self._get_range_session(start, stop, raw, output)
684 return self._get_range_session(start, stop, raw, output)
686 return super(HistoryManager, self).get_range(session, start, stop, raw,
685 return super(HistoryManager, self).get_range(session, start, stop, raw,
687 output)
686 output)
688
687
689 ## ----------------------------
688 ## ----------------------------
690 ## Methods for storing history:
689 ## Methods for storing history:
691 ## ----------------------------
690 ## ----------------------------
692 def store_inputs(self, line_num, source, source_raw=None):
691 def store_inputs(self, line_num, source, source_raw=None):
693 """Store source and raw input in history and create input cache
692 """Store source and raw input in history and create input cache
694 variables ``_i*``.
693 variables ``_i*``.
695
694
696 Parameters
695 Parameters
697 ----------
696 ----------
698 line_num : int
697 line_num : int
699 The prompt number of this input.
698 The prompt number of this input.
700
699
701 source : str
700 source : str
702 Python input.
701 Python input.
703
702
704 source_raw : str, optional
703 source_raw : str, optional
705 If given, this is the raw input without any IPython transformations
704 If given, this is the raw input without any IPython transformations
706 applied to it. If not given, ``source`` is used.
705 applied to it. If not given, ``source`` is used.
707 """
706 """
708 if source_raw is None:
707 if source_raw is None:
709 source_raw = source
708 source_raw = source
710 source = source.rstrip('\n')
709 source = source.rstrip('\n')
711 source_raw = source_raw.rstrip('\n')
710 source_raw = source_raw.rstrip('\n')
712
711
713 # do not store exit/quit commands
712 # do not store exit/quit commands
714 if self._exit_re.match(source_raw.strip()):
713 if self._exit_re.match(source_raw.strip()):
715 return
714 return
716
715
717 self.input_hist_parsed.append(source)
716 self.input_hist_parsed.append(source)
718 self.input_hist_raw.append(source_raw)
717 self.input_hist_raw.append(source_raw)
719
718
720 with self.db_input_cache_lock:
719 with self.db_input_cache_lock:
721 self.db_input_cache.append((line_num, source, source_raw))
720 self.db_input_cache.append((line_num, source, source_raw))
722 # Trigger to flush cache and write to DB.
721 # Trigger to flush cache and write to DB.
723 if len(self.db_input_cache) >= self.db_cache_size:
722 if len(self.db_input_cache) >= self.db_cache_size:
724 self.save_flag.set()
723 self.save_flag.set()
725
724
726 # update the auto _i variables
725 # update the auto _i variables
727 self._iii = self._ii
726 self._iii = self._ii
728 self._ii = self._i
727 self._ii = self._i
729 self._i = self._i00
728 self._i = self._i00
730 self._i00 = source_raw
729 self._i00 = source_raw
731
730
732 # hackish access to user namespace to create _i1,_i2... dynamically
731 # hackish access to user namespace to create _i1,_i2... dynamically
733 new_i = '_i%s' % line_num
732 new_i = '_i%s' % line_num
734 to_main = {'_i': self._i,
733 to_main = {'_i': self._i,
735 '_ii': self._ii,
734 '_ii': self._ii,
736 '_iii': self._iii,
735 '_iii': self._iii,
737 new_i : self._i00 }
736 new_i : self._i00 }
738
737
739 if self.shell is not None:
738 if self.shell is not None:
740 self.shell.push(to_main, interactive=False)
739 self.shell.push(to_main, interactive=False)
741
740
742 def store_output(self, line_num):
741 def store_output(self, line_num):
743 """If database output logging is enabled, this saves all the
742 """If database output logging is enabled, this saves all the
744 outputs from the indicated prompt number to the database. It's
743 outputs from the indicated prompt number to the database. It's
745 called by run_cell after code has been executed.
744 called by run_cell after code has been executed.
746
745
747 Parameters
746 Parameters
748 ----------
747 ----------
749 line_num : int
748 line_num : int
750 The line number from which to save outputs
749 The line number from which to save outputs
751 """
750 """
752 if (not self.db_log_output) or (line_num not in self.output_hist_reprs):
751 if (not self.db_log_output) or (line_num not in self.output_hist_reprs):
753 return
752 return
754 output = self.output_hist_reprs[line_num]
753 output = self.output_hist_reprs[line_num]
755
754
756 with self.db_output_cache_lock:
755 with self.db_output_cache_lock:
757 self.db_output_cache.append((line_num, output))
756 self.db_output_cache.append((line_num, output))
758 if self.db_cache_size <= 1:
757 if self.db_cache_size <= 1:
759 self.save_flag.set()
758 self.save_flag.set()
760
759
761 def _writeout_input_cache(self, conn):
760 def _writeout_input_cache(self, conn):
762 with conn:
761 with conn:
763 for line in self.db_input_cache:
762 for line in self.db_input_cache:
764 conn.execute("INSERT INTO history VALUES (?, ?, ?, ?)",
763 conn.execute("INSERT INTO history VALUES (?, ?, ?, ?)",
765 (self.session_number,)+line)
764 (self.session_number,)+line)
766
765
767 def _writeout_output_cache(self, conn):
766 def _writeout_output_cache(self, conn):
768 with conn:
767 with conn:
769 for line in self.db_output_cache:
768 for line in self.db_output_cache:
770 conn.execute("INSERT INTO output_history VALUES (?, ?, ?)",
769 conn.execute("INSERT INTO output_history VALUES (?, ?, ?)",
771 (self.session_number,)+line)
770 (self.session_number,)+line)
772
771
773 @needs_sqlite
772 @needs_sqlite
774 def writeout_cache(self, conn=None):
773 def writeout_cache(self, conn=None):
775 """Write any entries in the cache to the database."""
774 """Write any entries in the cache to the database."""
776 if conn is None:
775 if conn is None:
777 conn = self.db
776 conn = self.db
778
777
779 with self.db_input_cache_lock:
778 with self.db_input_cache_lock:
780 try:
779 try:
781 self._writeout_input_cache(conn)
780 self._writeout_input_cache(conn)
782 except sqlite3.IntegrityError:
781 except sqlite3.IntegrityError:
783 self.new_session(conn)
782 self.new_session(conn)
784 print("ERROR! Session/line number was not unique in",
783 print("ERROR! Session/line number was not unique in",
785 "database. History logging moved to new session",
784 "database. History logging moved to new session",
786 self.session_number)
785 self.session_number)
787 try:
786 try:
788 # Try writing to the new session. If this fails, don't
787 # Try writing to the new session. If this fails, don't
789 # recurse
788 # recurse
790 self._writeout_input_cache(conn)
789 self._writeout_input_cache(conn)
791 except sqlite3.IntegrityError:
790 except sqlite3.IntegrityError:
792 pass
791 pass
793 finally:
792 finally:
794 self.db_input_cache = []
793 self.db_input_cache = []
795
794
796 with self.db_output_cache_lock:
795 with self.db_output_cache_lock:
797 try:
796 try:
798 self._writeout_output_cache(conn)
797 self._writeout_output_cache(conn)
799 except sqlite3.IntegrityError:
798 except sqlite3.IntegrityError:
800 print("!! Session/line number for output was not unique",
799 print("!! Session/line number for output was not unique",
801 "in database. Output will not be stored.")
800 "in database. Output will not be stored.")
802 finally:
801 finally:
803 self.db_output_cache = []
802 self.db_output_cache = []
804
803
805
804
806 class HistorySavingThread(threading.Thread):
805 class HistorySavingThread(threading.Thread):
807 """This thread takes care of writing history to the database, so that
806 """This thread takes care of writing history to the database, so that
808 the UI isn't held up while that happens.
807 the UI isn't held up while that happens.
809
808
810 It waits for the HistoryManager's save_flag to be set, then writes out
809 It waits for the HistoryManager's save_flag to be set, then writes out
811 the history cache. The main thread is responsible for setting the flag when
810 the history cache. The main thread is responsible for setting the flag when
812 the cache size reaches a defined threshold."""
811 the cache size reaches a defined threshold."""
813 daemon = True
812 daemon = True
814 stop_now = False
813 stop_now = False
815 enabled = True
814 enabled = True
816 def __init__(self, history_manager):
815 def __init__(self, history_manager):
817 super(HistorySavingThread, self).__init__(name="IPythonHistorySavingThread")
816 super(HistorySavingThread, self).__init__(name="IPythonHistorySavingThread")
818 self.history_manager = history_manager
817 self.history_manager = history_manager
819 self.enabled = history_manager.enabled
818 self.enabled = history_manager.enabled
820 atexit.register(self.stop)
819 atexit.register(self.stop)
821
820
822 @needs_sqlite
821 @needs_sqlite
823 def run(self):
822 def run(self):
824 # We need a separate db connection per thread:
823 # We need a separate db connection per thread:
825 try:
824 try:
826 self.db = sqlite3.connect(self.history_manager.hist_file,
825 self.db = sqlite3.connect(self.history_manager.hist_file,
827 **self.history_manager.connection_options
826 **self.history_manager.connection_options
828 )
827 )
829 while True:
828 while True:
830 self.history_manager.save_flag.wait()
829 self.history_manager.save_flag.wait()
831 if self.stop_now:
830 if self.stop_now:
832 self.db.close()
831 self.db.close()
833 return
832 return
834 self.history_manager.save_flag.clear()
833 self.history_manager.save_flag.clear()
835 self.history_manager.writeout_cache(self.db)
834 self.history_manager.writeout_cache(self.db)
836 except Exception as e:
835 except Exception as e:
837 print(("The history saving thread hit an unexpected error (%s)."
836 print(("The history saving thread hit an unexpected error (%s)."
838 "History will not be written to the database.") % repr(e))
837 "History will not be written to the database.") % repr(e))
839
838
840 def stop(self):
839 def stop(self):
841 """This can be called from the main thread to safely stop this thread.
840 """This can be called from the main thread to safely stop this thread.
842
841
843 Note that it does not attempt to write out remaining history before
842 Note that it does not attempt to write out remaining history before
844 exiting. That should be done by calling the HistoryManager's
843 exiting. That should be done by calling the HistoryManager's
845 end_session method."""
844 end_session method."""
846 self.stop_now = True
845 self.stop_now = True
847 self.history_manager.save_flag.set()
846 self.history_manager.save_flag.set()
848 self.join()
847 self.join()
849
848
850
849
851 # To match, e.g. ~5/8-~2/3
850 # To match, e.g. ~5/8-~2/3
852 range_re = re.compile(r"""
851 range_re = re.compile(r"""
853 ((?P<startsess>~?\d+)/)?
852 ((?P<startsess>~?\d+)/)?
854 (?P<start>\d+)?
853 (?P<start>\d+)?
855 ((?P<sep>[\-:])
854 ((?P<sep>[\-:])
856 ((?P<endsess>~?\d+)/)?
855 ((?P<endsess>~?\d+)/)?
857 (?P<end>\d+))?
856 (?P<end>\d+))?
858 $""", re.VERBOSE)
857 $""", re.VERBOSE)
859
858
860
859
861 def extract_hist_ranges(ranges_str):
860 def extract_hist_ranges(ranges_str):
862 """Turn a string of history ranges into 3-tuples of (session, start, stop).
861 """Turn a string of history ranges into 3-tuples of (session, start, stop).
863
862
864 Examples
863 Examples
865 --------
864 --------
866 >>> list(extract_hist_ranges("~8/5-~7/4 2"))
865 >>> list(extract_hist_ranges("~8/5-~7/4 2"))
867 [(-8, 5, None), (-7, 1, 5), (0, 2, 3)]
866 [(-8, 5, None), (-7, 1, 5), (0, 2, 3)]
868 """
867 """
869 for range_str in ranges_str.split():
868 for range_str in ranges_str.split():
870 rmatch = range_re.match(range_str)
869 rmatch = range_re.match(range_str)
871 if not rmatch:
870 if not rmatch:
872 continue
871 continue
873 start = rmatch.group("start")
872 start = rmatch.group("start")
874 if start:
873 if start:
875 start = int(start)
874 start = int(start)
876 end = rmatch.group("end")
875 end = rmatch.group("end")
877 # If no end specified, get (a, a + 1)
876 # If no end specified, get (a, a + 1)
878 end = int(end) if end else start + 1
877 end = int(end) if end else start + 1
879 else: # start not specified
878 else: # start not specified
880 if not rmatch.group('startsess'): # no startsess
879 if not rmatch.group('startsess'): # no startsess
881 continue
880 continue
882 start = 1
881 start = 1
883 end = None # provide the entire session hist
882 end = None # provide the entire session hist
884
883
885 if rmatch.group("sep") == "-": # 1-3 == 1:4 --> [1, 2, 3]
884 if rmatch.group("sep") == "-": # 1-3 == 1:4 --> [1, 2, 3]
886 end += 1
885 end += 1
887 startsess = rmatch.group("startsess") or "0"
886 startsess = rmatch.group("startsess") or "0"
888 endsess = rmatch.group("endsess") or startsess
887 endsess = rmatch.group("endsess") or startsess
889 startsess = int(startsess.replace("~","-"))
888 startsess = int(startsess.replace("~","-"))
890 endsess = int(endsess.replace("~","-"))
889 endsess = int(endsess.replace("~","-"))
891 assert endsess >= startsess, "start session must be earlier than end session"
890 assert endsess >= startsess, "start session must be earlier than end session"
892
891
893 if endsess == startsess:
892 if endsess == startsess:
894 yield (startsess, start, end)
893 yield (startsess, start, end)
895 continue
894 continue
896 # Multiple sessions in one range:
895 # Multiple sessions in one range:
897 yield (startsess, start, None)
896 yield (startsess, start, None)
898 for sess in range(startsess+1, endsess):
897 for sess in range(startsess+1, endsess):
899 yield (sess, 1, None)
898 yield (sess, 1, None)
900 yield (endsess, 1, end)
899 yield (endsess, 1, end)
901
900
902
901
903 def _format_lineno(session, line):
902 def _format_lineno(session, line):
904 """Helper function to format line numbers properly."""
903 """Helper function to format line numbers properly."""
905 if session == 0:
904 if session == 0:
906 return str(line)
905 return str(line)
907 return "%s#%s" % (session, line)
906 return "%s#%s" % (session, line)
@@ -1,54 +1,53 b''
1 """Support for interactive macros in IPython"""
1 """Support for interactive macros in IPython"""
2
2
3 #*****************************************************************************
3 #*****************************************************************************
4 # Copyright (C) 2001-2005 Fernando Perez <fperez@colorado.edu>
4 # Copyright (C) 2001-2005 Fernando Perez <fperez@colorado.edu>
5 #
5 #
6 # Distributed under the terms of the BSD License. The full license is in
6 # Distributed under the terms of the BSD License. The full license is in
7 # the file COPYING, distributed as part of this software.
7 # the file COPYING, distributed as part of this software.
8 #*****************************************************************************
8 #*****************************************************************************
9
9
10 import re
10 import re
11
11
12 from IPython.utils import py3compat
13 from IPython.utils.encoding import DEFAULT_ENCODING
12 from IPython.utils.encoding import DEFAULT_ENCODING
14
13
15 coding_declaration = re.compile(r"#\s*coding[:=]\s*([-\w.]+)")
14 coding_declaration = re.compile(r"#\s*coding[:=]\s*([-\w.]+)")
16
15
17 class Macro(object):
16 class Macro(object):
18 """Simple class to store the value of macros as strings.
17 """Simple class to store the value of macros as strings.
19
18
20 Macro is just a callable that executes a string of IPython
19 Macro is just a callable that executes a string of IPython
21 input when called.
20 input when called.
22 """
21 """
23
22
24 def __init__(self,code):
23 def __init__(self,code):
25 """store the macro value, as a single string which can be executed"""
24 """store the macro value, as a single string which can be executed"""
26 lines = []
25 lines = []
27 enc = None
26 enc = None
28 for line in code.splitlines():
27 for line in code.splitlines():
29 coding_match = coding_declaration.match(line)
28 coding_match = coding_declaration.match(line)
30 if coding_match:
29 if coding_match:
31 enc = coding_match.group(1)
30 enc = coding_match.group(1)
32 else:
31 else:
33 lines.append(line)
32 lines.append(line)
34 code = "\n".join(lines)
33 code = "\n".join(lines)
35 if isinstance(code, bytes):
34 if isinstance(code, bytes):
36 code = code.decode(enc or DEFAULT_ENCODING)
35 code = code.decode(enc or DEFAULT_ENCODING)
37 self.value = code + '\n'
36 self.value = code + '\n'
38
37
39 def __str__(self):
38 def __str__(self):
40 return self.value
39 return self.value
41
40
42 def __repr__(self):
41 def __repr__(self):
43 return 'IPython.macro.Macro(%s)' % repr(self.value)
42 return 'IPython.macro.Macro(%s)' % repr(self.value)
44
43
45 def __getstate__(self):
44 def __getstate__(self):
46 """ needed for safe pickling via %store """
45 """ needed for safe pickling via %store """
47 return {'value': self.value}
46 return {'value': self.value}
48
47
49 def __add__(self, other):
48 def __add__(self, other):
50 if isinstance(other, Macro):
49 if isinstance(other, Macro):
51 return Macro(self.value + other.value)
50 return Macro(self.value + other.value)
52 elif isinstance(other, str):
51 elif isinstance(other, str):
53 return Macro(self.value + other)
52 return Macro(self.value + other)
54 raise TypeError
53 raise TypeError
@@ -1,685 +1,684 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Magic functions for InteractiveShell.
2 """Magic functions for InteractiveShell.
3 """
3 """
4
4
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
6 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
7 # Copyright (C) 2001 Fernando Perez <fperez@colorado.edu>
7 # Copyright (C) 2001 Fernando Perez <fperez@colorado.edu>
8 # Copyright (C) 2008 The IPython Development Team
8 # Copyright (C) 2008 The IPython Development Team
9
9
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 import os
14 import os
15 import re
15 import re
16 import sys
16 import sys
17 import types
18 from getopt import getopt, GetoptError
17 from getopt import getopt, GetoptError
19
18
20 from traitlets.config.configurable import Configurable
19 from traitlets.config.configurable import Configurable
21 from IPython.core import oinspect
20 from IPython.core import oinspect
22 from IPython.core.error import UsageError
21 from IPython.core.error import UsageError
23 from IPython.core.inputsplitter import ESC_MAGIC, ESC_MAGIC2
22 from IPython.core.inputsplitter import ESC_MAGIC, ESC_MAGIC2
24 from decorator import decorator
23 from decorator import decorator
25 from IPython.utils.ipstruct import Struct
24 from IPython.utils.ipstruct import Struct
26 from IPython.utils.process import arg_split
25 from IPython.utils.process import arg_split
27 from IPython.utils.text import dedent
26 from IPython.utils.text import dedent
28 from traitlets import Bool, Dict, Instance, observe
27 from traitlets import Bool, Dict, Instance, observe
29 from logging import error
28 from logging import error
30
29
31 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
32 # Globals
31 # Globals
33 #-----------------------------------------------------------------------------
32 #-----------------------------------------------------------------------------
34
33
35 # A dict we'll use for each class that has magics, used as temporary storage to
34 # A dict we'll use for each class that has magics, used as temporary storage to
36 # pass information between the @line/cell_magic method decorators and the
35 # pass information between the @line/cell_magic method decorators and the
37 # @magics_class class decorator, because the method decorators have no
36 # @magics_class class decorator, because the method decorators have no
38 # access to the class when they run. See for more details:
37 # access to the class when they run. See for more details:
39 # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
38 # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
40
39
41 magics = dict(line={}, cell={})
40 magics = dict(line={}, cell={})
42
41
43 magic_kinds = ('line', 'cell')
42 magic_kinds = ('line', 'cell')
44 magic_spec = ('line', 'cell', 'line_cell')
43 magic_spec = ('line', 'cell', 'line_cell')
45 magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
44 magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
46
45
47 #-----------------------------------------------------------------------------
46 #-----------------------------------------------------------------------------
48 # Utility classes and functions
47 # Utility classes and functions
49 #-----------------------------------------------------------------------------
48 #-----------------------------------------------------------------------------
50
49
51 class Bunch: pass
50 class Bunch: pass
52
51
53
52
54 def on_off(tag):
53 def on_off(tag):
55 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
54 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
56 return ['OFF','ON'][tag]
55 return ['OFF','ON'][tag]
57
56
58
57
59 def compress_dhist(dh):
58 def compress_dhist(dh):
60 """Compress a directory history into a new one with at most 20 entries.
59 """Compress a directory history into a new one with at most 20 entries.
61
60
62 Return a new list made from the first and last 10 elements of dhist after
61 Return a new list made from the first and last 10 elements of dhist after
63 removal of duplicates.
62 removal of duplicates.
64 """
63 """
65 head, tail = dh[:-10], dh[-10:]
64 head, tail = dh[:-10], dh[-10:]
66
65
67 newhead = []
66 newhead = []
68 done = set()
67 done = set()
69 for h in head:
68 for h in head:
70 if h in done:
69 if h in done:
71 continue
70 continue
72 newhead.append(h)
71 newhead.append(h)
73 done.add(h)
72 done.add(h)
74
73
75 return newhead + tail
74 return newhead + tail
76
75
77
76
78 def needs_local_scope(func):
77 def needs_local_scope(func):
79 """Decorator to mark magic functions which need to local scope to run."""
78 """Decorator to mark magic functions which need to local scope to run."""
80 func.needs_local_scope = True
79 func.needs_local_scope = True
81 return func
80 return func
82
81
83 #-----------------------------------------------------------------------------
82 #-----------------------------------------------------------------------------
84 # Class and method decorators for registering magics
83 # Class and method decorators for registering magics
85 #-----------------------------------------------------------------------------
84 #-----------------------------------------------------------------------------
86
85
87 def magics_class(cls):
86 def magics_class(cls):
88 """Class decorator for all subclasses of the main Magics class.
87 """Class decorator for all subclasses of the main Magics class.
89
88
90 Any class that subclasses Magics *must* also apply this decorator, to
89 Any class that subclasses Magics *must* also apply this decorator, to
91 ensure that all the methods that have been decorated as line/cell magics
90 ensure that all the methods that have been decorated as line/cell magics
92 get correctly registered in the class instance. This is necessary because
91 get correctly registered in the class instance. This is necessary because
93 when method decorators run, the class does not exist yet, so they
92 when method decorators run, the class does not exist yet, so they
94 temporarily store their information into a module global. Application of
93 temporarily store their information into a module global. Application of
95 this class decorator copies that global data to the class instance and
94 this class decorator copies that global data to the class instance and
96 clears the global.
95 clears the global.
97
96
98 Obviously, this mechanism is not thread-safe, which means that the
97 Obviously, this mechanism is not thread-safe, which means that the
99 *creation* of subclasses of Magic should only be done in a single-thread
98 *creation* of subclasses of Magic should only be done in a single-thread
100 context. Instantiation of the classes has no restrictions. Given that
99 context. Instantiation of the classes has no restrictions. Given that
101 these classes are typically created at IPython startup time and before user
100 these classes are typically created at IPython startup time and before user
102 application code becomes active, in practice this should not pose any
101 application code becomes active, in practice this should not pose any
103 problems.
102 problems.
104 """
103 """
105 cls.registered = True
104 cls.registered = True
106 cls.magics = dict(line = magics['line'],
105 cls.magics = dict(line = magics['line'],
107 cell = magics['cell'])
106 cell = magics['cell'])
108 magics['line'] = {}
107 magics['line'] = {}
109 magics['cell'] = {}
108 magics['cell'] = {}
110 return cls
109 return cls
111
110
112
111
113 def record_magic(dct, magic_kind, magic_name, func):
112 def record_magic(dct, magic_kind, magic_name, func):
114 """Utility function to store a function as a magic of a specific kind.
113 """Utility function to store a function as a magic of a specific kind.
115
114
116 Parameters
115 Parameters
117 ----------
116 ----------
118 dct : dict
117 dct : dict
119 A dictionary with 'line' and 'cell' subdicts.
118 A dictionary with 'line' and 'cell' subdicts.
120
119
121 magic_kind : str
120 magic_kind : str
122 Kind of magic to be stored.
121 Kind of magic to be stored.
123
122
124 magic_name : str
123 magic_name : str
125 Key to store the magic as.
124 Key to store the magic as.
126
125
127 func : function
126 func : function
128 Callable object to store.
127 Callable object to store.
129 """
128 """
130 if magic_kind == 'line_cell':
129 if magic_kind == 'line_cell':
131 dct['line'][magic_name] = dct['cell'][magic_name] = func
130 dct['line'][magic_name] = dct['cell'][magic_name] = func
132 else:
131 else:
133 dct[magic_kind][magic_name] = func
132 dct[magic_kind][magic_name] = func
134
133
135
134
136 def validate_type(magic_kind):
135 def validate_type(magic_kind):
137 """Ensure that the given magic_kind is valid.
136 """Ensure that the given magic_kind is valid.
138
137
139 Check that the given magic_kind is one of the accepted spec types (stored
138 Check that the given magic_kind is one of the accepted spec types (stored
140 in the global `magic_spec`), raise ValueError otherwise.
139 in the global `magic_spec`), raise ValueError otherwise.
141 """
140 """
142 if magic_kind not in magic_spec:
141 if magic_kind not in magic_spec:
143 raise ValueError('magic_kind must be one of %s, %s given' %
142 raise ValueError('magic_kind must be one of %s, %s given' %
144 magic_kinds, magic_kind)
143 magic_kinds, magic_kind)
145
144
146
145
147 # The docstrings for the decorator below will be fairly similar for the two
146 # The docstrings for the decorator below will be fairly similar for the two
148 # types (method and function), so we generate them here once and reuse the
147 # types (method and function), so we generate them here once and reuse the
149 # templates below.
148 # templates below.
150 _docstring_template = \
149 _docstring_template = \
151 """Decorate the given {0} as {1} magic.
150 """Decorate the given {0} as {1} magic.
152
151
153 The decorator can be used with or without arguments, as follows.
152 The decorator can be used with or without arguments, as follows.
154
153
155 i) without arguments: it will create a {1} magic named as the {0} being
154 i) without arguments: it will create a {1} magic named as the {0} being
156 decorated::
155 decorated::
157
156
158 @deco
157 @deco
159 def foo(...)
158 def foo(...)
160
159
161 will create a {1} magic named `foo`.
160 will create a {1} magic named `foo`.
162
161
163 ii) with one string argument: which will be used as the actual name of the
162 ii) with one string argument: which will be used as the actual name of the
164 resulting magic::
163 resulting magic::
165
164
166 @deco('bar')
165 @deco('bar')
167 def foo(...)
166 def foo(...)
168
167
169 will create a {1} magic named `bar`.
168 will create a {1} magic named `bar`.
170
169
171 To register a class magic use ``Interactiveshell.register_magic(class or instance)``.
170 To register a class magic use ``Interactiveshell.register_magic(class or instance)``.
172 """
171 """
173
172
174 # These two are decorator factories. While they are conceptually very similar,
173 # These two are decorator factories. While they are conceptually very similar,
175 # there are enough differences in the details that it's simpler to have them
174 # there are enough differences in the details that it's simpler to have them
176 # written as completely standalone functions rather than trying to share code
175 # written as completely standalone functions rather than trying to share code
177 # and make a single one with convoluted logic.
176 # and make a single one with convoluted logic.
178
177
179 def _method_magic_marker(magic_kind):
178 def _method_magic_marker(magic_kind):
180 """Decorator factory for methods in Magics subclasses.
179 """Decorator factory for methods in Magics subclasses.
181 """
180 """
182
181
183 validate_type(magic_kind)
182 validate_type(magic_kind)
184
183
185 # This is a closure to capture the magic_kind. We could also use a class,
184 # This is a closure to capture the magic_kind. We could also use a class,
186 # but it's overkill for just that one bit of state.
185 # but it's overkill for just that one bit of state.
187 def magic_deco(arg):
186 def magic_deco(arg):
188 call = lambda f, *a, **k: f(*a, **k)
187 call = lambda f, *a, **k: f(*a, **k)
189
188
190 if callable(arg):
189 if callable(arg):
191 # "Naked" decorator call (just @foo, no args)
190 # "Naked" decorator call (just @foo, no args)
192 func = arg
191 func = arg
193 name = func.__name__
192 name = func.__name__
194 retval = decorator(call, func)
193 retval = decorator(call, func)
195 record_magic(magics, magic_kind, name, name)
194 record_magic(magics, magic_kind, name, name)
196 elif isinstance(arg, str):
195 elif isinstance(arg, str):
197 # Decorator called with arguments (@foo('bar'))
196 # Decorator called with arguments (@foo('bar'))
198 name = arg
197 name = arg
199 def mark(func, *a, **kw):
198 def mark(func, *a, **kw):
200 record_magic(magics, magic_kind, name, func.__name__)
199 record_magic(magics, magic_kind, name, func.__name__)
201 return decorator(call, func)
200 return decorator(call, func)
202 retval = mark
201 retval = mark
203 else:
202 else:
204 raise TypeError("Decorator can only be called with "
203 raise TypeError("Decorator can only be called with "
205 "string or function")
204 "string or function")
206 return retval
205 return retval
207
206
208 # Ensure the resulting decorator has a usable docstring
207 # Ensure the resulting decorator has a usable docstring
209 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
208 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
210 return magic_deco
209 return magic_deco
211
210
212
211
213 def _function_magic_marker(magic_kind):
212 def _function_magic_marker(magic_kind):
214 """Decorator factory for standalone functions.
213 """Decorator factory for standalone functions.
215 """
214 """
216 validate_type(magic_kind)
215 validate_type(magic_kind)
217
216
218 # This is a closure to capture the magic_kind. We could also use a class,
217 # This is a closure to capture the magic_kind. We could also use a class,
219 # but it's overkill for just that one bit of state.
218 # but it's overkill for just that one bit of state.
220 def magic_deco(arg):
219 def magic_deco(arg):
221 call = lambda f, *a, **k: f(*a, **k)
220 call = lambda f, *a, **k: f(*a, **k)
222
221
223 # Find get_ipython() in the caller's namespace
222 # Find get_ipython() in the caller's namespace
224 caller = sys._getframe(1)
223 caller = sys._getframe(1)
225 for ns in ['f_locals', 'f_globals', 'f_builtins']:
224 for ns in ['f_locals', 'f_globals', 'f_builtins']:
226 get_ipython = getattr(caller, ns).get('get_ipython')
225 get_ipython = getattr(caller, ns).get('get_ipython')
227 if get_ipython is not None:
226 if get_ipython is not None:
228 break
227 break
229 else:
228 else:
230 raise NameError('Decorator can only run in context where '
229 raise NameError('Decorator can only run in context where '
231 '`get_ipython` exists')
230 '`get_ipython` exists')
232
231
233 ip = get_ipython()
232 ip = get_ipython()
234
233
235 if callable(arg):
234 if callable(arg):
236 # "Naked" decorator call (just @foo, no args)
235 # "Naked" decorator call (just @foo, no args)
237 func = arg
236 func = arg
238 name = func.__name__
237 name = func.__name__
239 ip.register_magic_function(func, magic_kind, name)
238 ip.register_magic_function(func, magic_kind, name)
240 retval = decorator(call, func)
239 retval = decorator(call, func)
241 elif isinstance(arg, str):
240 elif isinstance(arg, str):
242 # Decorator called with arguments (@foo('bar'))
241 # Decorator called with arguments (@foo('bar'))
243 name = arg
242 name = arg
244 def mark(func, *a, **kw):
243 def mark(func, *a, **kw):
245 ip.register_magic_function(func, magic_kind, name)
244 ip.register_magic_function(func, magic_kind, name)
246 return decorator(call, func)
245 return decorator(call, func)
247 retval = mark
246 retval = mark
248 else:
247 else:
249 raise TypeError("Decorator can only be called with "
248 raise TypeError("Decorator can only be called with "
250 "string or function")
249 "string or function")
251 return retval
250 return retval
252
251
253 # Ensure the resulting decorator has a usable docstring
252 # Ensure the resulting decorator has a usable docstring
254 ds = _docstring_template.format('function', magic_kind)
253 ds = _docstring_template.format('function', magic_kind)
255
254
256 ds += dedent("""
255 ds += dedent("""
257 Note: this decorator can only be used in a context where IPython is already
256 Note: this decorator can only be used in a context where IPython is already
258 active, so that the `get_ipython()` call succeeds. You can therefore use
257 active, so that the `get_ipython()` call succeeds. You can therefore use
259 it in your startup files loaded after IPython initializes, but *not* in the
258 it in your startup files loaded after IPython initializes, but *not* in the
260 IPython configuration file itself, which is executed before IPython is
259 IPython configuration file itself, which is executed before IPython is
261 fully up and running. Any file located in the `startup` subdirectory of
260 fully up and running. Any file located in the `startup` subdirectory of
262 your configuration profile will be OK in this sense.
261 your configuration profile will be OK in this sense.
263 """)
262 """)
264
263
265 magic_deco.__doc__ = ds
264 magic_deco.__doc__ = ds
266 return magic_deco
265 return magic_deco
267
266
268
267
269 # Create the actual decorators for public use
268 # Create the actual decorators for public use
270
269
271 # These three are used to decorate methods in class definitions
270 # These three are used to decorate methods in class definitions
272 line_magic = _method_magic_marker('line')
271 line_magic = _method_magic_marker('line')
273 cell_magic = _method_magic_marker('cell')
272 cell_magic = _method_magic_marker('cell')
274 line_cell_magic = _method_magic_marker('line_cell')
273 line_cell_magic = _method_magic_marker('line_cell')
275
274
276 # These three decorate standalone functions and perform the decoration
275 # These three decorate standalone functions and perform the decoration
277 # immediately. They can only run where get_ipython() works
276 # immediately. They can only run where get_ipython() works
278 register_line_magic = _function_magic_marker('line')
277 register_line_magic = _function_magic_marker('line')
279 register_cell_magic = _function_magic_marker('cell')
278 register_cell_magic = _function_magic_marker('cell')
280 register_line_cell_magic = _function_magic_marker('line_cell')
279 register_line_cell_magic = _function_magic_marker('line_cell')
281
280
282 #-----------------------------------------------------------------------------
281 #-----------------------------------------------------------------------------
283 # Core Magic classes
282 # Core Magic classes
284 #-----------------------------------------------------------------------------
283 #-----------------------------------------------------------------------------
285
284
286 class MagicsManager(Configurable):
285 class MagicsManager(Configurable):
287 """Object that handles all magic-related functionality for IPython.
286 """Object that handles all magic-related functionality for IPython.
288 """
287 """
289 # Non-configurable class attributes
288 # Non-configurable class attributes
290
289
291 # A two-level dict, first keyed by magic type, then by magic function, and
290 # A two-level dict, first keyed by magic type, then by magic function, and
292 # holding the actual callable object as value. This is the dict used for
291 # holding the actual callable object as value. This is the dict used for
293 # magic function dispatch
292 # magic function dispatch
294 magics = Dict()
293 magics = Dict()
295
294
296 # A registry of the original objects that we've been given holding magics.
295 # A registry of the original objects that we've been given holding magics.
297 registry = Dict()
296 registry = Dict()
298
297
299 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
298 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
300
299
301 auto_magic = Bool(True, help=
300 auto_magic = Bool(True, help=
302 "Automatically call line magics without requiring explicit % prefix"
301 "Automatically call line magics without requiring explicit % prefix"
303 ).tag(config=True)
302 ).tag(config=True)
304 @observe('auto_magic')
303 @observe('auto_magic')
305 def _auto_magic_changed(self, change):
304 def _auto_magic_changed(self, change):
306 self.shell.automagic = change['new']
305 self.shell.automagic = change['new']
307
306
308 _auto_status = [
307 _auto_status = [
309 'Automagic is OFF, % prefix IS needed for line magics.',
308 'Automagic is OFF, % prefix IS needed for line magics.',
310 'Automagic is ON, % prefix IS NOT needed for line magics.']
309 'Automagic is ON, % prefix IS NOT needed for line magics.']
311
310
312 user_magics = Instance('IPython.core.magics.UserMagics', allow_none=True)
311 user_magics = Instance('IPython.core.magics.UserMagics', allow_none=True)
313
312
314 def __init__(self, shell=None, config=None, user_magics=None, **traits):
313 def __init__(self, shell=None, config=None, user_magics=None, **traits):
315
314
316 super(MagicsManager, self).__init__(shell=shell, config=config,
315 super(MagicsManager, self).__init__(shell=shell, config=config,
317 user_magics=user_magics, **traits)
316 user_magics=user_magics, **traits)
318 self.magics = dict(line={}, cell={})
317 self.magics = dict(line={}, cell={})
319 # Let's add the user_magics to the registry for uniformity, so *all*
318 # Let's add the user_magics to the registry for uniformity, so *all*
320 # registered magic containers can be found there.
319 # registered magic containers can be found there.
321 self.registry[user_magics.__class__.__name__] = user_magics
320 self.registry[user_magics.__class__.__name__] = user_magics
322
321
323 def auto_status(self):
322 def auto_status(self):
324 """Return descriptive string with automagic status."""
323 """Return descriptive string with automagic status."""
325 return self._auto_status[self.auto_magic]
324 return self._auto_status[self.auto_magic]
326
325
327 def lsmagic(self):
326 def lsmagic(self):
328 """Return a dict of currently available magic functions.
327 """Return a dict of currently available magic functions.
329
328
330 The return dict has the keys 'line' and 'cell', corresponding to the
329 The return dict has the keys 'line' and 'cell', corresponding to the
331 two types of magics we support. Each value is a list of names.
330 two types of magics we support. Each value is a list of names.
332 """
331 """
333 return self.magics
332 return self.magics
334
333
335 def lsmagic_docs(self, brief=False, missing=''):
334 def lsmagic_docs(self, brief=False, missing=''):
336 """Return dict of documentation of magic functions.
335 """Return dict of documentation of magic functions.
337
336
338 The return dict has the keys 'line' and 'cell', corresponding to the
337 The return dict has the keys 'line' and 'cell', corresponding to the
339 two types of magics we support. Each value is a dict keyed by magic
338 two types of magics we support. Each value is a dict keyed by magic
340 name whose value is the function docstring. If a docstring is
339 name whose value is the function docstring. If a docstring is
341 unavailable, the value of `missing` is used instead.
340 unavailable, the value of `missing` is used instead.
342
341
343 If brief is True, only the first line of each docstring will be returned.
342 If brief is True, only the first line of each docstring will be returned.
344 """
343 """
345 docs = {}
344 docs = {}
346 for m_type in self.magics:
345 for m_type in self.magics:
347 m_docs = {}
346 m_docs = {}
348 for m_name, m_func in self.magics[m_type].items():
347 for m_name, m_func in self.magics[m_type].items():
349 if m_func.__doc__:
348 if m_func.__doc__:
350 if brief:
349 if brief:
351 m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
350 m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
352 else:
351 else:
353 m_docs[m_name] = m_func.__doc__.rstrip()
352 m_docs[m_name] = m_func.__doc__.rstrip()
354 else:
353 else:
355 m_docs[m_name] = missing
354 m_docs[m_name] = missing
356 docs[m_type] = m_docs
355 docs[m_type] = m_docs
357 return docs
356 return docs
358
357
359 def register(self, *magic_objects):
358 def register(self, *magic_objects):
360 """Register one or more instances of Magics.
359 """Register one or more instances of Magics.
361
360
362 Take one or more classes or instances of classes that subclass the main
361 Take one or more classes or instances of classes that subclass the main
363 `core.Magic` class, and register them with IPython to use the magic
362 `core.Magic` class, and register them with IPython to use the magic
364 functions they provide. The registration process will then ensure that
363 functions they provide. The registration process will then ensure that
365 any methods that have decorated to provide line and/or cell magics will
364 any methods that have decorated to provide line and/or cell magics will
366 be recognized with the `%x`/`%%x` syntax as a line/cell magic
365 be recognized with the `%x`/`%%x` syntax as a line/cell magic
367 respectively.
366 respectively.
368
367
369 If classes are given, they will be instantiated with the default
368 If classes are given, they will be instantiated with the default
370 constructor. If your classes need a custom constructor, you should
369 constructor. If your classes need a custom constructor, you should
371 instanitate them first and pass the instance.
370 instanitate them first and pass the instance.
372
371
373 The provided arguments can be an arbitrary mix of classes and instances.
372 The provided arguments can be an arbitrary mix of classes and instances.
374
373
375 Parameters
374 Parameters
376 ----------
375 ----------
377 magic_objects : one or more classes or instances
376 magic_objects : one or more classes or instances
378 """
377 """
379 # Start by validating them to ensure they have all had their magic
378 # Start by validating them to ensure they have all had their magic
380 # methods registered at the instance level
379 # methods registered at the instance level
381 for m in magic_objects:
380 for m in magic_objects:
382 if not m.registered:
381 if not m.registered:
383 raise ValueError("Class of magics %r was constructed without "
382 raise ValueError("Class of magics %r was constructed without "
384 "the @register_magics class decorator")
383 "the @register_magics class decorator")
385 if isinstance(m, type):
384 if isinstance(m, type):
386 # If we're given an uninstantiated class
385 # If we're given an uninstantiated class
387 m = m(shell=self.shell)
386 m = m(shell=self.shell)
388
387
389 # Now that we have an instance, we can register it and update the
388 # Now that we have an instance, we can register it and update the
390 # table of callables
389 # table of callables
391 self.registry[m.__class__.__name__] = m
390 self.registry[m.__class__.__name__] = m
392 for mtype in magic_kinds:
391 for mtype in magic_kinds:
393 self.magics[mtype].update(m.magics[mtype])
392 self.magics[mtype].update(m.magics[mtype])
394
393
395 def register_function(self, func, magic_kind='line', magic_name=None):
394 def register_function(self, func, magic_kind='line', magic_name=None):
396 """Expose a standalone function as magic function for IPython.
395 """Expose a standalone function as magic function for IPython.
397
396
398 This will create an IPython magic (line, cell or both) from a
397 This will create an IPython magic (line, cell or both) from a
399 standalone function. The functions should have the following
398 standalone function. The functions should have the following
400 signatures:
399 signatures:
401
400
402 * For line magics: `def f(line)`
401 * For line magics: `def f(line)`
403 * For cell magics: `def f(line, cell)`
402 * For cell magics: `def f(line, cell)`
404 * For a function that does both: `def f(line, cell=None)`
403 * For a function that does both: `def f(line, cell=None)`
405
404
406 In the latter case, the function will be called with `cell==None` when
405 In the latter case, the function will be called with `cell==None` when
407 invoked as `%f`, and with cell as a string when invoked as `%%f`.
406 invoked as `%f`, and with cell as a string when invoked as `%%f`.
408
407
409 Parameters
408 Parameters
410 ----------
409 ----------
411 func : callable
410 func : callable
412 Function to be registered as a magic.
411 Function to be registered as a magic.
413
412
414 magic_kind : str
413 magic_kind : str
415 Kind of magic, one of 'line', 'cell' or 'line_cell'
414 Kind of magic, one of 'line', 'cell' or 'line_cell'
416
415
417 magic_name : optional str
416 magic_name : optional str
418 If given, the name the magic will have in the IPython namespace. By
417 If given, the name the magic will have in the IPython namespace. By
419 default, the name of the function itself is used.
418 default, the name of the function itself is used.
420 """
419 """
421
420
422 # Create the new method in the user_magics and register it in the
421 # Create the new method in the user_magics and register it in the
423 # global table
422 # global table
424 validate_type(magic_kind)
423 validate_type(magic_kind)
425 magic_name = func.__name__ if magic_name is None else magic_name
424 magic_name = func.__name__ if magic_name is None else magic_name
426 setattr(self.user_magics, magic_name, func)
425 setattr(self.user_magics, magic_name, func)
427 record_magic(self.magics, magic_kind, magic_name, func)
426 record_magic(self.magics, magic_kind, magic_name, func)
428
427
429 def register_alias(self, alias_name, magic_name, magic_kind='line', magic_params=None):
428 def register_alias(self, alias_name, magic_name, magic_kind='line', magic_params=None):
430 """Register an alias to a magic function.
429 """Register an alias to a magic function.
431
430
432 The alias is an instance of :class:`MagicAlias`, which holds the
431 The alias is an instance of :class:`MagicAlias`, which holds the
433 name and kind of the magic it should call. Binding is done at
432 name and kind of the magic it should call. Binding is done at
434 call time, so if the underlying magic function is changed the alias
433 call time, so if the underlying magic function is changed the alias
435 will call the new function.
434 will call the new function.
436
435
437 Parameters
436 Parameters
438 ----------
437 ----------
439 alias_name : str
438 alias_name : str
440 The name of the magic to be registered.
439 The name of the magic to be registered.
441
440
442 magic_name : str
441 magic_name : str
443 The name of an existing magic.
442 The name of an existing magic.
444
443
445 magic_kind : str
444 magic_kind : str
446 Kind of magic, one of 'line' or 'cell'
445 Kind of magic, one of 'line' or 'cell'
447 """
446 """
448
447
449 # `validate_type` is too permissive, as it allows 'line_cell'
448 # `validate_type` is too permissive, as it allows 'line_cell'
450 # which we do not handle.
449 # which we do not handle.
451 if magic_kind not in magic_kinds:
450 if magic_kind not in magic_kinds:
452 raise ValueError('magic_kind must be one of %s, %s given' %
451 raise ValueError('magic_kind must be one of %s, %s given' %
453 magic_kinds, magic_kind)
452 magic_kinds, magic_kind)
454
453
455 alias = MagicAlias(self.shell, magic_name, magic_kind, magic_params)
454 alias = MagicAlias(self.shell, magic_name, magic_kind, magic_params)
456 setattr(self.user_magics, alias_name, alias)
455 setattr(self.user_magics, alias_name, alias)
457 record_magic(self.magics, magic_kind, alias_name, alias)
456 record_magic(self.magics, magic_kind, alias_name, alias)
458
457
459 # Key base class that provides the central functionality for magics.
458 # Key base class that provides the central functionality for magics.
460
459
461
460
462 class Magics(Configurable):
461 class Magics(Configurable):
463 """Base class for implementing magic functions.
462 """Base class for implementing magic functions.
464
463
465 Shell functions which can be reached as %function_name. All magic
464 Shell functions which can be reached as %function_name. All magic
466 functions should accept a string, which they can parse for their own
465 functions should accept a string, which they can parse for their own
467 needs. This can make some functions easier to type, eg `%cd ../`
466 needs. This can make some functions easier to type, eg `%cd ../`
468 vs. `%cd("../")`
467 vs. `%cd("../")`
469
468
470 Classes providing magic functions need to subclass this class, and they
469 Classes providing magic functions need to subclass this class, and they
471 MUST:
470 MUST:
472
471
473 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
472 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
474 individual methods as magic functions, AND
473 individual methods as magic functions, AND
475
474
476 - Use the class decorator `@magics_class` to ensure that the magic
475 - Use the class decorator `@magics_class` to ensure that the magic
477 methods are properly registered at the instance level upon instance
476 methods are properly registered at the instance level upon instance
478 initialization.
477 initialization.
479
478
480 See :mod:`magic_functions` for examples of actual implementation classes.
479 See :mod:`magic_functions` for examples of actual implementation classes.
481 """
480 """
482 # Dict holding all command-line options for each magic.
481 # Dict holding all command-line options for each magic.
483 options_table = None
482 options_table = None
484 # Dict for the mapping of magic names to methods, set by class decorator
483 # Dict for the mapping of magic names to methods, set by class decorator
485 magics = None
484 magics = None
486 # Flag to check that the class decorator was properly applied
485 # Flag to check that the class decorator was properly applied
487 registered = False
486 registered = False
488 # Instance of IPython shell
487 # Instance of IPython shell
489 shell = None
488 shell = None
490
489
491 def __init__(self, shell=None, **kwargs):
490 def __init__(self, shell=None, **kwargs):
492 if not(self.__class__.registered):
491 if not(self.__class__.registered):
493 raise ValueError('Magics subclass without registration - '
492 raise ValueError('Magics subclass without registration - '
494 'did you forget to apply @magics_class?')
493 'did you forget to apply @magics_class?')
495 if shell is not None:
494 if shell is not None:
496 if hasattr(shell, 'configurables'):
495 if hasattr(shell, 'configurables'):
497 shell.configurables.append(self)
496 shell.configurables.append(self)
498 if hasattr(shell, 'config'):
497 if hasattr(shell, 'config'):
499 kwargs.setdefault('parent', shell)
498 kwargs.setdefault('parent', shell)
500
499
501 self.shell = shell
500 self.shell = shell
502 self.options_table = {}
501 self.options_table = {}
503 # The method decorators are run when the instance doesn't exist yet, so
502 # The method decorators are run when the instance doesn't exist yet, so
504 # they can only record the names of the methods they are supposed to
503 # they can only record the names of the methods they are supposed to
505 # grab. Only now, that the instance exists, can we create the proper
504 # grab. Only now, that the instance exists, can we create the proper
506 # mapping to bound methods. So we read the info off the original names
505 # mapping to bound methods. So we read the info off the original names
507 # table and replace each method name by the actual bound method.
506 # table and replace each method name by the actual bound method.
508 # But we mustn't clobber the *class* mapping, in case of multiple instances.
507 # But we mustn't clobber the *class* mapping, in case of multiple instances.
509 class_magics = self.magics
508 class_magics = self.magics
510 self.magics = {}
509 self.magics = {}
511 for mtype in magic_kinds:
510 for mtype in magic_kinds:
512 tab = self.magics[mtype] = {}
511 tab = self.magics[mtype] = {}
513 cls_tab = class_magics[mtype]
512 cls_tab = class_magics[mtype]
514 for magic_name, meth_name in cls_tab.items():
513 for magic_name, meth_name in cls_tab.items():
515 if isinstance(meth_name, str):
514 if isinstance(meth_name, str):
516 # it's a method name, grab it
515 # it's a method name, grab it
517 tab[magic_name] = getattr(self, meth_name)
516 tab[magic_name] = getattr(self, meth_name)
518 else:
517 else:
519 # it's the real thing
518 # it's the real thing
520 tab[magic_name] = meth_name
519 tab[magic_name] = meth_name
521 # Configurable **needs** to be initiated at the end or the config
520 # Configurable **needs** to be initiated at the end or the config
522 # magics get screwed up.
521 # magics get screwed up.
523 super(Magics, self).__init__(**kwargs)
522 super(Magics, self).__init__(**kwargs)
524
523
525 def arg_err(self,func):
524 def arg_err(self,func):
526 """Print docstring if incorrect arguments were passed"""
525 """Print docstring if incorrect arguments were passed"""
527 print('Error in arguments:')
526 print('Error in arguments:')
528 print(oinspect.getdoc(func))
527 print(oinspect.getdoc(func))
529
528
530 def format_latex(self, strng):
529 def format_latex(self, strng):
531 """Format a string for latex inclusion."""
530 """Format a string for latex inclusion."""
532
531
533 # Characters that need to be escaped for latex:
532 # Characters that need to be escaped for latex:
534 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
533 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
535 # Magic command names as headers:
534 # Magic command names as headers:
536 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
535 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
537 re.MULTILINE)
536 re.MULTILINE)
538 # Magic commands
537 # Magic commands
539 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
538 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
540 re.MULTILINE)
539 re.MULTILINE)
541 # Paragraph continue
540 # Paragraph continue
542 par_re = re.compile(r'\\$',re.MULTILINE)
541 par_re = re.compile(r'\\$',re.MULTILINE)
543
542
544 # The "\n" symbol
543 # The "\n" symbol
545 newline_re = re.compile(r'\\n')
544 newline_re = re.compile(r'\\n')
546
545
547 # Now build the string for output:
546 # Now build the string for output:
548 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
547 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
549 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
548 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
550 strng)
549 strng)
551 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
550 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
552 strng = par_re.sub(r'\\\\',strng)
551 strng = par_re.sub(r'\\\\',strng)
553 strng = escape_re.sub(r'\\\1',strng)
552 strng = escape_re.sub(r'\\\1',strng)
554 strng = newline_re.sub(r'\\textbackslash{}n',strng)
553 strng = newline_re.sub(r'\\textbackslash{}n',strng)
555 return strng
554 return strng
556
555
557 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
556 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
558 """Parse options passed to an argument string.
557 """Parse options passed to an argument string.
559
558
560 The interface is similar to that of :func:`getopt.getopt`, but it
559 The interface is similar to that of :func:`getopt.getopt`, but it
561 returns a :class:`~IPython.utils.struct.Struct` with the options as keys
560 returns a :class:`~IPython.utils.struct.Struct` with the options as keys
562 and the stripped argument string still as a string.
561 and the stripped argument string still as a string.
563
562
564 arg_str is quoted as a true sys.argv vector by using shlex.split.
563 arg_str is quoted as a true sys.argv vector by using shlex.split.
565 This allows us to easily expand variables, glob files, quote
564 This allows us to easily expand variables, glob files, quote
566 arguments, etc.
565 arguments, etc.
567
566
568 Parameters
567 Parameters
569 ----------
568 ----------
570
569
571 arg_str : str
570 arg_str : str
572 The arguments to parse.
571 The arguments to parse.
573
572
574 opt_str : str
573 opt_str : str
575 The options specification.
574 The options specification.
576
575
577 mode : str, default 'string'
576 mode : str, default 'string'
578 If given as 'list', the argument string is returned as a list (split
577 If given as 'list', the argument string is returned as a list (split
579 on whitespace) instead of a string.
578 on whitespace) instead of a string.
580
579
581 list_all : bool, default False
580 list_all : bool, default False
582 Put all option values in lists. Normally only options
581 Put all option values in lists. Normally only options
583 appearing more than once are put in a list.
582 appearing more than once are put in a list.
584
583
585 posix : bool, default True
584 posix : bool, default True
586 Whether to split the input line in POSIX mode or not, as per the
585 Whether to split the input line in POSIX mode or not, as per the
587 conventions outlined in the :mod:`shlex` module from the standard
586 conventions outlined in the :mod:`shlex` module from the standard
588 library.
587 library.
589 """
588 """
590
589
591 # inject default options at the beginning of the input line
590 # inject default options at the beginning of the input line
592 caller = sys._getframe(1).f_code.co_name
591 caller = sys._getframe(1).f_code.co_name
593 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
592 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
594
593
595 mode = kw.get('mode','string')
594 mode = kw.get('mode','string')
596 if mode not in ['string','list']:
595 if mode not in ['string','list']:
597 raise ValueError('incorrect mode given: %s' % mode)
596 raise ValueError('incorrect mode given: %s' % mode)
598 # Get options
597 # Get options
599 list_all = kw.get('list_all',0)
598 list_all = kw.get('list_all',0)
600 posix = kw.get('posix', os.name == 'posix')
599 posix = kw.get('posix', os.name == 'posix')
601 strict = kw.get('strict', True)
600 strict = kw.get('strict', True)
602
601
603 # Check if we have more than one argument to warrant extra processing:
602 # Check if we have more than one argument to warrant extra processing:
604 odict = {} # Dictionary with options
603 odict = {} # Dictionary with options
605 args = arg_str.split()
604 args = arg_str.split()
606 if len(args) >= 1:
605 if len(args) >= 1:
607 # If the list of inputs only has 0 or 1 thing in it, there's no
606 # If the list of inputs only has 0 or 1 thing in it, there's no
608 # need to look for options
607 # need to look for options
609 argv = arg_split(arg_str, posix, strict)
608 argv = arg_split(arg_str, posix, strict)
610 # Do regular option processing
609 # Do regular option processing
611 try:
610 try:
612 opts,args = getopt(argv, opt_str, long_opts)
611 opts,args = getopt(argv, opt_str, long_opts)
613 except GetoptError as e:
612 except GetoptError as e:
614 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
613 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
615 " ".join(long_opts)))
614 " ".join(long_opts)))
616 for o,a in opts:
615 for o,a in opts:
617 if o.startswith('--'):
616 if o.startswith('--'):
618 o = o[2:]
617 o = o[2:]
619 else:
618 else:
620 o = o[1:]
619 o = o[1:]
621 try:
620 try:
622 odict[o].append(a)
621 odict[o].append(a)
623 except AttributeError:
622 except AttributeError:
624 odict[o] = [odict[o],a]
623 odict[o] = [odict[o],a]
625 except KeyError:
624 except KeyError:
626 if list_all:
625 if list_all:
627 odict[o] = [a]
626 odict[o] = [a]
628 else:
627 else:
629 odict[o] = a
628 odict[o] = a
630
629
631 # Prepare opts,args for return
630 # Prepare opts,args for return
632 opts = Struct(odict)
631 opts = Struct(odict)
633 if mode == 'string':
632 if mode == 'string':
634 args = ' '.join(args)
633 args = ' '.join(args)
635
634
636 return opts,args
635 return opts,args
637
636
638 def default_option(self, fn, optstr):
637 def default_option(self, fn, optstr):
639 """Make an entry in the options_table for fn, with value optstr"""
638 """Make an entry in the options_table for fn, with value optstr"""
640
639
641 if fn not in self.lsmagic():
640 if fn not in self.lsmagic():
642 error("%s is not a magic function" % fn)
641 error("%s is not a magic function" % fn)
643 self.options_table[fn] = optstr
642 self.options_table[fn] = optstr
644
643
645
644
646 class MagicAlias(object):
645 class MagicAlias(object):
647 """An alias to another magic function.
646 """An alias to another magic function.
648
647
649 An alias is determined by its magic name and magic kind. Lookup
648 An alias is determined by its magic name and magic kind. Lookup
650 is done at call time, so if the underlying magic changes the alias
649 is done at call time, so if the underlying magic changes the alias
651 will call the new function.
650 will call the new function.
652
651
653 Use the :meth:`MagicsManager.register_alias` method or the
652 Use the :meth:`MagicsManager.register_alias` method or the
654 `%alias_magic` magic function to create and register a new alias.
653 `%alias_magic` magic function to create and register a new alias.
655 """
654 """
656 def __init__(self, shell, magic_name, magic_kind, magic_params=None):
655 def __init__(self, shell, magic_name, magic_kind, magic_params=None):
657 self.shell = shell
656 self.shell = shell
658 self.magic_name = magic_name
657 self.magic_name = magic_name
659 self.magic_params = magic_params
658 self.magic_params = magic_params
660 self.magic_kind = magic_kind
659 self.magic_kind = magic_kind
661
660
662 self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name)
661 self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name)
663 self.__doc__ = "Alias for `%s`." % self.pretty_target
662 self.__doc__ = "Alias for `%s`." % self.pretty_target
664
663
665 self._in_call = False
664 self._in_call = False
666
665
667 def __call__(self, *args, **kwargs):
666 def __call__(self, *args, **kwargs):
668 """Call the magic alias."""
667 """Call the magic alias."""
669 fn = self.shell.find_magic(self.magic_name, self.magic_kind)
668 fn = self.shell.find_magic(self.magic_name, self.magic_kind)
670 if fn is None:
669 if fn is None:
671 raise UsageError("Magic `%s` not found." % self.pretty_target)
670 raise UsageError("Magic `%s` not found." % self.pretty_target)
672
671
673 # Protect against infinite recursion.
672 # Protect against infinite recursion.
674 if self._in_call:
673 if self._in_call:
675 raise UsageError("Infinite recursion detected; "
674 raise UsageError("Infinite recursion detected; "
676 "magic aliases cannot call themselves.")
675 "magic aliases cannot call themselves.")
677 self._in_call = True
676 self._in_call = True
678 try:
677 try:
679 if self.magic_params:
678 if self.magic_params:
680 args_list = list(args)
679 args_list = list(args)
681 args_list[0] = self.magic_params + " " + args[0]
680 args_list[0] = self.magic_params + " " + args[0]
682 args = tuple(args_list)
681 args = tuple(args_list)
683 return fn(*args, **kwargs)
682 return fn(*args, **kwargs)
684 finally:
683 finally:
685 self._in_call = False
684 self._in_call = False
@@ -1,66 +1,63 b''
1 """Implementation of magic functions for the extension machinery.
1 """Implementation of magic functions for the extension machinery.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2012 The IPython Development Team.
4 # Copyright (c) 2012 The IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7 #
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 # Stdlib
16 import os
17
15
18 # Our own packages
16 # Our own packages
19 from IPython.core.error import UsageError
17 from IPython.core.error import UsageError
20 from IPython.core.magic import Magics, magics_class, line_magic
18 from IPython.core.magic import Magics, magics_class, line_magic
21 from warnings import warn
22
19
23 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
24 # Magic implementation classes
21 # Magic implementation classes
25 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
26
23
27 @magics_class
24 @magics_class
28 class ExtensionMagics(Magics):
25 class ExtensionMagics(Magics):
29 """Magics to manage the IPython extensions system."""
26 """Magics to manage the IPython extensions system."""
30
27
31 @line_magic
28 @line_magic
32 def load_ext(self, module_str):
29 def load_ext(self, module_str):
33 """Load an IPython extension by its module name."""
30 """Load an IPython extension by its module name."""
34 if not module_str:
31 if not module_str:
35 raise UsageError('Missing module name.')
32 raise UsageError('Missing module name.')
36 res = self.shell.extension_manager.load_extension(module_str)
33 res = self.shell.extension_manager.load_extension(module_str)
37
34
38 if res == 'already loaded':
35 if res == 'already loaded':
39 print("The %s extension is already loaded. To reload it, use:" % module_str)
36 print("The %s extension is already loaded. To reload it, use:" % module_str)
40 print(" %reload_ext", module_str)
37 print(" %reload_ext", module_str)
41 elif res == 'no load function':
38 elif res == 'no load function':
42 print("The %s module is not an IPython extension." % module_str)
39 print("The %s module is not an IPython extension." % module_str)
43
40
44 @line_magic
41 @line_magic
45 def unload_ext(self, module_str):
42 def unload_ext(self, module_str):
46 """Unload an IPython extension by its module name.
43 """Unload an IPython extension by its module name.
47
44
48 Not all extensions can be unloaded, only those which define an
45 Not all extensions can be unloaded, only those which define an
49 ``unload_ipython_extension`` function.
46 ``unload_ipython_extension`` function.
50 """
47 """
51 if not module_str:
48 if not module_str:
52 raise UsageError('Missing module name.')
49 raise UsageError('Missing module name.')
53
50
54 res = self.shell.extension_manager.unload_extension(module_str)
51 res = self.shell.extension_manager.unload_extension(module_str)
55
52
56 if res == 'no unload function':
53 if res == 'no unload function':
57 print("The %s extension doesn't define how to unload it." % module_str)
54 print("The %s extension doesn't define how to unload it." % module_str)
58 elif res == "not loaded":
55 elif res == "not loaded":
59 print("The %s extension is not loaded." % module_str)
56 print("The %s extension is not loaded." % module_str)
60
57
61 @line_magic
58 @line_magic
62 def reload_ext(self, module_str):
59 def reload_ext(self, module_str):
63 """Reload an IPython extension by its module name."""
60 """Reload an IPython extension by its module name."""
64 if not module_str:
61 if not module_str:
65 raise UsageError('Missing module name.')
62 raise UsageError('Missing module name.')
66 self.shell.extension_manager.reload_extension(module_str)
63 self.shell.extension_manager.reload_extension(module_str)
@@ -1,793 +1,792 b''
1 """Implementation of magic functions for interaction with the OS.
1 """Implementation of magic functions for interaction with the OS.
2
2
3 Note: this module is named 'osm' instead of 'os' to avoid a collision with the
3 Note: this module is named 'osm' instead of 'os' to avoid a collision with the
4 builtin.
4 builtin.
5 """
5 """
6 # Copyright (c) IPython Development Team.
6 # Copyright (c) IPython Development Team.
7 # Distributed under the terms of the Modified BSD License.
7 # Distributed under the terms of the Modified BSD License.
8
8
9 import io
9 import io
10 import os
10 import os
11 import re
11 import re
12 import sys
12 import sys
13 from pprint import pformat
13 from pprint import pformat
14
14
15 from IPython.core import magic_arguments
15 from IPython.core import magic_arguments
16 from IPython.core import oinspect
16 from IPython.core import oinspect
17 from IPython.core import page
17 from IPython.core import page
18 from IPython.core.alias import AliasError, Alias
18 from IPython.core.alias import AliasError, Alias
19 from IPython.core.error import UsageError
19 from IPython.core.error import UsageError
20 from IPython.core.magic import (
20 from IPython.core.magic import (
21 Magics, compress_dhist, magics_class, line_magic, cell_magic, line_cell_magic
21 Magics, compress_dhist, magics_class, line_magic, cell_magic, line_cell_magic
22 )
22 )
23 from IPython.testing.skipdoctest import skip_doctest
23 from IPython.testing.skipdoctest import skip_doctest
24 from IPython.utils.openpy import source_to_unicode
24 from IPython.utils.openpy import source_to_unicode
25 from IPython.utils.process import abbrev_cwd
25 from IPython.utils.process import abbrev_cwd
26 from IPython.utils import py3compat
27 from IPython.utils.terminal import set_term_title
26 from IPython.utils.terminal import set_term_title
28
27
29
28
30 @magics_class
29 @magics_class
31 class OSMagics(Magics):
30 class OSMagics(Magics):
32 """Magics to interact with the underlying OS (shell-type functionality).
31 """Magics to interact with the underlying OS (shell-type functionality).
33 """
32 """
34
33
35 @skip_doctest
34 @skip_doctest
36 @line_magic
35 @line_magic
37 def alias(self, parameter_s=''):
36 def alias(self, parameter_s=''):
38 """Define an alias for a system command.
37 """Define an alias for a system command.
39
38
40 '%alias alias_name cmd' defines 'alias_name' as an alias for 'cmd'
39 '%alias alias_name cmd' defines 'alias_name' as an alias for 'cmd'
41
40
42 Then, typing 'alias_name params' will execute the system command 'cmd
41 Then, typing 'alias_name params' will execute the system command 'cmd
43 params' (from your underlying operating system).
42 params' (from your underlying operating system).
44
43
45 Aliases have lower precedence than magic functions and Python normal
44 Aliases have lower precedence than magic functions and Python normal
46 variables, so if 'foo' is both a Python variable and an alias, the
45 variables, so if 'foo' is both a Python variable and an alias, the
47 alias can not be executed until 'del foo' removes the Python variable.
46 alias can not be executed until 'del foo' removes the Python variable.
48
47
49 You can use the %l specifier in an alias definition to represent the
48 You can use the %l specifier in an alias definition to represent the
50 whole line when the alias is called. For example::
49 whole line when the alias is called. For example::
51
50
52 In [2]: alias bracket echo "Input in brackets: <%l>"
51 In [2]: alias bracket echo "Input in brackets: <%l>"
53 In [3]: bracket hello world
52 In [3]: bracket hello world
54 Input in brackets: <hello world>
53 Input in brackets: <hello world>
55
54
56 You can also define aliases with parameters using %s specifiers (one
55 You can also define aliases with parameters using %s specifiers (one
57 per parameter)::
56 per parameter)::
58
57
59 In [1]: alias parts echo first %s second %s
58 In [1]: alias parts echo first %s second %s
60 In [2]: %parts A B
59 In [2]: %parts A B
61 first A second B
60 first A second B
62 In [3]: %parts A
61 In [3]: %parts A
63 Incorrect number of arguments: 2 expected.
62 Incorrect number of arguments: 2 expected.
64 parts is an alias to: 'echo first %s second %s'
63 parts is an alias to: 'echo first %s second %s'
65
64
66 Note that %l and %s are mutually exclusive. You can only use one or
65 Note that %l and %s are mutually exclusive. You can only use one or
67 the other in your aliases.
66 the other in your aliases.
68
67
69 Aliases expand Python variables just like system calls using ! or !!
68 Aliases expand Python variables just like system calls using ! or !!
70 do: all expressions prefixed with '$' get expanded. For details of
69 do: all expressions prefixed with '$' get expanded. For details of
71 the semantic rules, see PEP-215:
70 the semantic rules, see PEP-215:
72 http://www.python.org/peps/pep-0215.html. This is the library used by
71 http://www.python.org/peps/pep-0215.html. This is the library used by
73 IPython for variable expansion. If you want to access a true shell
72 IPython for variable expansion. If you want to access a true shell
74 variable, an extra $ is necessary to prevent its expansion by
73 variable, an extra $ is necessary to prevent its expansion by
75 IPython::
74 IPython::
76
75
77 In [6]: alias show echo
76 In [6]: alias show echo
78 In [7]: PATH='A Python string'
77 In [7]: PATH='A Python string'
79 In [8]: show $PATH
78 In [8]: show $PATH
80 A Python string
79 A Python string
81 In [9]: show $$PATH
80 In [9]: show $$PATH
82 /usr/local/lf9560/bin:/usr/local/intel/compiler70/ia32/bin:...
81 /usr/local/lf9560/bin:/usr/local/intel/compiler70/ia32/bin:...
83
82
84 You can use the alias facility to access all of $PATH. See the %rehashx
83 You can use the alias facility to access all of $PATH. See the %rehashx
85 function, which automatically creates aliases for the contents of your
84 function, which automatically creates aliases for the contents of your
86 $PATH.
85 $PATH.
87
86
88 If called with no parameters, %alias prints the current alias table
87 If called with no parameters, %alias prints the current alias table
89 for your system. For posix systems, the default aliases are 'cat',
88 for your system. For posix systems, the default aliases are 'cat',
90 'cp', 'mv', 'rm', 'rmdir', and 'mkdir', and other platform-specific
89 'cp', 'mv', 'rm', 'rmdir', and 'mkdir', and other platform-specific
91 aliases are added. For windows-based systems, the default aliases are
90 aliases are added. For windows-based systems, the default aliases are
92 'copy', 'ddir', 'echo', 'ls', 'ldir', 'mkdir', 'ren', and 'rmdir'.
91 'copy', 'ddir', 'echo', 'ls', 'ldir', 'mkdir', 'ren', and 'rmdir'.
93
92
94 You can see the definition of alias by adding a question mark in the
93 You can see the definition of alias by adding a question mark in the
95 end::
94 end::
96
95
97 In [1]: cat?
96 In [1]: cat?
98 Repr: <alias cat for 'cat'>"""
97 Repr: <alias cat for 'cat'>"""
99
98
100 par = parameter_s.strip()
99 par = parameter_s.strip()
101 if not par:
100 if not par:
102 aliases = sorted(self.shell.alias_manager.aliases)
101 aliases = sorted(self.shell.alias_manager.aliases)
103 # stored = self.shell.db.get('stored_aliases', {} )
102 # stored = self.shell.db.get('stored_aliases', {} )
104 # for k, v in stored:
103 # for k, v in stored:
105 # atab.append(k, v[0])
104 # atab.append(k, v[0])
106
105
107 print("Total number of aliases:", len(aliases))
106 print("Total number of aliases:", len(aliases))
108 sys.stdout.flush()
107 sys.stdout.flush()
109 return aliases
108 return aliases
110
109
111 # Now try to define a new one
110 # Now try to define a new one
112 try:
111 try:
113 alias,cmd = par.split(None, 1)
112 alias,cmd = par.split(None, 1)
114 except TypeError:
113 except TypeError:
115 print(oinspect.getdoc(self.alias))
114 print(oinspect.getdoc(self.alias))
116 return
115 return
117
116
118 try:
117 try:
119 self.shell.alias_manager.define_alias(alias, cmd)
118 self.shell.alias_manager.define_alias(alias, cmd)
120 except AliasError as e:
119 except AliasError as e:
121 print(e)
120 print(e)
122 # end magic_alias
121 # end magic_alias
123
122
124 @line_magic
123 @line_magic
125 def unalias(self, parameter_s=''):
124 def unalias(self, parameter_s=''):
126 """Remove an alias"""
125 """Remove an alias"""
127
126
128 aname = parameter_s.strip()
127 aname = parameter_s.strip()
129 try:
128 try:
130 self.shell.alias_manager.undefine_alias(aname)
129 self.shell.alias_manager.undefine_alias(aname)
131 except ValueError as e:
130 except ValueError as e:
132 print(e)
131 print(e)
133 return
132 return
134
133
135 stored = self.shell.db.get('stored_aliases', {} )
134 stored = self.shell.db.get('stored_aliases', {} )
136 if aname in stored:
135 if aname in stored:
137 print("Removing %stored alias",aname)
136 print("Removing %stored alias",aname)
138 del stored[aname]
137 del stored[aname]
139 self.shell.db['stored_aliases'] = stored
138 self.shell.db['stored_aliases'] = stored
140
139
141 @line_magic
140 @line_magic
142 def rehashx(self, parameter_s=''):
141 def rehashx(self, parameter_s=''):
143 """Update the alias table with all executable files in $PATH.
142 """Update the alias table with all executable files in $PATH.
144
143
145 rehashx explicitly checks that every entry in $PATH is a file
144 rehashx explicitly checks that every entry in $PATH is a file
146 with execute access (os.X_OK).
145 with execute access (os.X_OK).
147
146
148 Under Windows, it checks executability as a match against a
147 Under Windows, it checks executability as a match against a
149 '|'-separated string of extensions, stored in the IPython config
148 '|'-separated string of extensions, stored in the IPython config
150 variable win_exec_ext. This defaults to 'exe|com|bat'.
149 variable win_exec_ext. This defaults to 'exe|com|bat'.
151
150
152 This function also resets the root module cache of module completer,
151 This function also resets the root module cache of module completer,
153 used on slow filesystems.
152 used on slow filesystems.
154 """
153 """
155 from IPython.core.alias import InvalidAliasError
154 from IPython.core.alias import InvalidAliasError
156
155
157 # for the benefit of module completer in ipy_completers.py
156 # for the benefit of module completer in ipy_completers.py
158 del self.shell.db['rootmodules_cache']
157 del self.shell.db['rootmodules_cache']
159
158
160 path = [os.path.abspath(os.path.expanduser(p)) for p in
159 path = [os.path.abspath(os.path.expanduser(p)) for p in
161 os.environ.get('PATH','').split(os.pathsep)]
160 os.environ.get('PATH','').split(os.pathsep)]
162
161
163 syscmdlist = []
162 syscmdlist = []
164 # Now define isexec in a cross platform manner.
163 # Now define isexec in a cross platform manner.
165 if os.name == 'posix':
164 if os.name == 'posix':
166 isexec = lambda fname:os.path.isfile(fname) and \
165 isexec = lambda fname:os.path.isfile(fname) and \
167 os.access(fname,os.X_OK)
166 os.access(fname,os.X_OK)
168 else:
167 else:
169 try:
168 try:
170 winext = os.environ['pathext'].replace(';','|').replace('.','')
169 winext = os.environ['pathext'].replace(';','|').replace('.','')
171 except KeyError:
170 except KeyError:
172 winext = 'exe|com|bat|py'
171 winext = 'exe|com|bat|py'
173 if 'py' not in winext:
172 if 'py' not in winext:
174 winext += '|py'
173 winext += '|py'
175 execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE)
174 execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE)
176 isexec = lambda fname:os.path.isfile(fname) and execre.match(fname)
175 isexec = lambda fname:os.path.isfile(fname) and execre.match(fname)
177 savedir = os.getcwd()
176 savedir = os.getcwd()
178
177
179 # Now walk the paths looking for executables to alias.
178 # Now walk the paths looking for executables to alias.
180 try:
179 try:
181 # write the whole loop for posix/Windows so we don't have an if in
180 # write the whole loop for posix/Windows so we don't have an if in
182 # the innermost part
181 # the innermost part
183 if os.name == 'posix':
182 if os.name == 'posix':
184 for pdir in path:
183 for pdir in path:
185 try:
184 try:
186 os.chdir(pdir)
185 os.chdir(pdir)
187 dirlist = os.listdir(pdir)
186 dirlist = os.listdir(pdir)
188 except OSError:
187 except OSError:
189 continue
188 continue
190 for ff in dirlist:
189 for ff in dirlist:
191 if isexec(ff):
190 if isexec(ff):
192 try:
191 try:
193 # Removes dots from the name since ipython
192 # Removes dots from the name since ipython
194 # will assume names with dots to be python.
193 # will assume names with dots to be python.
195 if not self.shell.alias_manager.is_alias(ff):
194 if not self.shell.alias_manager.is_alias(ff):
196 self.shell.alias_manager.define_alias(
195 self.shell.alias_manager.define_alias(
197 ff.replace('.',''), ff)
196 ff.replace('.',''), ff)
198 except InvalidAliasError:
197 except InvalidAliasError:
199 pass
198 pass
200 else:
199 else:
201 syscmdlist.append(ff)
200 syscmdlist.append(ff)
202 else:
201 else:
203 no_alias = Alias.blacklist
202 no_alias = Alias.blacklist
204 for pdir in path:
203 for pdir in path:
205 try:
204 try:
206 os.chdir(pdir)
205 os.chdir(pdir)
207 dirlist = os.listdir(pdir)
206 dirlist = os.listdir(pdir)
208 except OSError:
207 except OSError:
209 continue
208 continue
210 for ff in dirlist:
209 for ff in dirlist:
211 base, ext = os.path.splitext(ff)
210 base, ext = os.path.splitext(ff)
212 if isexec(ff) and base.lower() not in no_alias:
211 if isexec(ff) and base.lower() not in no_alias:
213 if ext.lower() == '.exe':
212 if ext.lower() == '.exe':
214 ff = base
213 ff = base
215 try:
214 try:
216 # Removes dots from the name since ipython
215 # Removes dots from the name since ipython
217 # will assume names with dots to be python.
216 # will assume names with dots to be python.
218 self.shell.alias_manager.define_alias(
217 self.shell.alias_manager.define_alias(
219 base.lower().replace('.',''), ff)
218 base.lower().replace('.',''), ff)
220 except InvalidAliasError:
219 except InvalidAliasError:
221 pass
220 pass
222 syscmdlist.append(ff)
221 syscmdlist.append(ff)
223 self.shell.db['syscmdlist'] = syscmdlist
222 self.shell.db['syscmdlist'] = syscmdlist
224 finally:
223 finally:
225 os.chdir(savedir)
224 os.chdir(savedir)
226
225
227 @skip_doctest
226 @skip_doctest
228 @line_magic
227 @line_magic
229 def pwd(self, parameter_s=''):
228 def pwd(self, parameter_s=''):
230 """Return the current working directory path.
229 """Return the current working directory path.
231
230
232 Examples
231 Examples
233 --------
232 --------
234 ::
233 ::
235
234
236 In [9]: pwd
235 In [9]: pwd
237 Out[9]: '/home/tsuser/sprint/ipython'
236 Out[9]: '/home/tsuser/sprint/ipython'
238 """
237 """
239 try:
238 try:
240 return os.getcwd()
239 return os.getcwd()
241 except FileNotFoundError:
240 except FileNotFoundError:
242 raise UsageError("CWD no longer exists - please use %cd to change directory.")
241 raise UsageError("CWD no longer exists - please use %cd to change directory.")
243
242
244 @skip_doctest
243 @skip_doctest
245 @line_magic
244 @line_magic
246 def cd(self, parameter_s=''):
245 def cd(self, parameter_s=''):
247 """Change the current working directory.
246 """Change the current working directory.
248
247
249 This command automatically maintains an internal list of directories
248 This command automatically maintains an internal list of directories
250 you visit during your IPython session, in the variable _dh. The
249 you visit during your IPython session, in the variable _dh. The
251 command %dhist shows this history nicely formatted. You can also
250 command %dhist shows this history nicely formatted. You can also
252 do 'cd -<tab>' to see directory history conveniently.
251 do 'cd -<tab>' to see directory history conveniently.
253
252
254 Usage:
253 Usage:
255
254
256 cd 'dir': changes to directory 'dir'.
255 cd 'dir': changes to directory 'dir'.
257
256
258 cd -: changes to the last visited directory.
257 cd -: changes to the last visited directory.
259
258
260 cd -<n>: changes to the n-th directory in the directory history.
259 cd -<n>: changes to the n-th directory in the directory history.
261
260
262 cd --foo: change to directory that matches 'foo' in history
261 cd --foo: change to directory that matches 'foo' in history
263
262
264 cd -b <bookmark_name>: jump to a bookmark set by %bookmark
263 cd -b <bookmark_name>: jump to a bookmark set by %bookmark
265 (note: cd <bookmark_name> is enough if there is no
264 (note: cd <bookmark_name> is enough if there is no
266 directory <bookmark_name>, but a bookmark with the name exists.)
265 directory <bookmark_name>, but a bookmark with the name exists.)
267 'cd -b <tab>' allows you to tab-complete bookmark names.
266 'cd -b <tab>' allows you to tab-complete bookmark names.
268
267
269 Options:
268 Options:
270
269
271 -q: quiet. Do not print the working directory after the cd command is
270 -q: quiet. Do not print the working directory after the cd command is
272 executed. By default IPython's cd command does print this directory,
271 executed. By default IPython's cd command does print this directory,
273 since the default prompts do not display path information.
272 since the default prompts do not display path information.
274
273
275 Note that !cd doesn't work for this purpose because the shell where
274 Note that !cd doesn't work for this purpose because the shell where
276 !command runs is immediately discarded after executing 'command'.
275 !command runs is immediately discarded after executing 'command'.
277
276
278 Examples
277 Examples
279 --------
278 --------
280 ::
279 ::
281
280
282 In [10]: cd parent/child
281 In [10]: cd parent/child
283 /home/tsuser/parent/child
282 /home/tsuser/parent/child
284 """
283 """
285
284
286 try:
285 try:
287 oldcwd = os.getcwd()
286 oldcwd = os.getcwd()
288 except FileNotFoundError:
287 except FileNotFoundError:
289 # Happens if the CWD has been deleted.
288 # Happens if the CWD has been deleted.
290 oldcwd = None
289 oldcwd = None
291
290
292 numcd = re.match(r'(-)(\d+)$',parameter_s)
291 numcd = re.match(r'(-)(\d+)$',parameter_s)
293 # jump in directory history by number
292 # jump in directory history by number
294 if numcd:
293 if numcd:
295 nn = int(numcd.group(2))
294 nn = int(numcd.group(2))
296 try:
295 try:
297 ps = self.shell.user_ns['_dh'][nn]
296 ps = self.shell.user_ns['_dh'][nn]
298 except IndexError:
297 except IndexError:
299 print('The requested directory does not exist in history.')
298 print('The requested directory does not exist in history.')
300 return
299 return
301 else:
300 else:
302 opts = {}
301 opts = {}
303 elif parameter_s.startswith('--'):
302 elif parameter_s.startswith('--'):
304 ps = None
303 ps = None
305 fallback = None
304 fallback = None
306 pat = parameter_s[2:]
305 pat = parameter_s[2:]
307 dh = self.shell.user_ns['_dh']
306 dh = self.shell.user_ns['_dh']
308 # first search only by basename (last component)
307 # first search only by basename (last component)
309 for ent in reversed(dh):
308 for ent in reversed(dh):
310 if pat in os.path.basename(ent) and os.path.isdir(ent):
309 if pat in os.path.basename(ent) and os.path.isdir(ent):
311 ps = ent
310 ps = ent
312 break
311 break
313
312
314 if fallback is None and pat in ent and os.path.isdir(ent):
313 if fallback is None and pat in ent and os.path.isdir(ent):
315 fallback = ent
314 fallback = ent
316
315
317 # if we have no last part match, pick the first full path match
316 # if we have no last part match, pick the first full path match
318 if ps is None:
317 if ps is None:
319 ps = fallback
318 ps = fallback
320
319
321 if ps is None:
320 if ps is None:
322 print("No matching entry in directory history")
321 print("No matching entry in directory history")
323 return
322 return
324 else:
323 else:
325 opts = {}
324 opts = {}
326
325
327
326
328 else:
327 else:
329 opts, ps = self.parse_options(parameter_s, 'qb', mode='string')
328 opts, ps = self.parse_options(parameter_s, 'qb', mode='string')
330 # jump to previous
329 # jump to previous
331 if ps == '-':
330 if ps == '-':
332 try:
331 try:
333 ps = self.shell.user_ns['_dh'][-2]
332 ps = self.shell.user_ns['_dh'][-2]
334 except IndexError:
333 except IndexError:
335 raise UsageError('%cd -: No previous directory to change to.')
334 raise UsageError('%cd -: No previous directory to change to.')
336 # jump to bookmark if needed
335 # jump to bookmark if needed
337 else:
336 else:
338 if not os.path.isdir(ps) or 'b' in opts:
337 if not os.path.isdir(ps) or 'b' in opts:
339 bkms = self.shell.db.get('bookmarks', {})
338 bkms = self.shell.db.get('bookmarks', {})
340
339
341 if ps in bkms:
340 if ps in bkms:
342 target = bkms[ps]
341 target = bkms[ps]
343 print('(bookmark:%s) -> %s' % (ps, target))
342 print('(bookmark:%s) -> %s' % (ps, target))
344 ps = target
343 ps = target
345 else:
344 else:
346 if 'b' in opts:
345 if 'b' in opts:
347 raise UsageError("Bookmark '%s' not found. "
346 raise UsageError("Bookmark '%s' not found. "
348 "Use '%%bookmark -l' to see your bookmarks." % ps)
347 "Use '%%bookmark -l' to see your bookmarks." % ps)
349
348
350 # at this point ps should point to the target dir
349 # at this point ps should point to the target dir
351 if ps:
350 if ps:
352 try:
351 try:
353 os.chdir(os.path.expanduser(ps))
352 os.chdir(os.path.expanduser(ps))
354 if hasattr(self.shell, 'term_title') and self.shell.term_title:
353 if hasattr(self.shell, 'term_title') and self.shell.term_title:
355 set_term_title(self.shell.term_title_format.format(cwd=abbrev_cwd()))
354 set_term_title(self.shell.term_title_format.format(cwd=abbrev_cwd()))
356 except OSError:
355 except OSError:
357 print(sys.exc_info()[1])
356 print(sys.exc_info()[1])
358 else:
357 else:
359 cwd = os.getcwd()
358 cwd = os.getcwd()
360 dhist = self.shell.user_ns['_dh']
359 dhist = self.shell.user_ns['_dh']
361 if oldcwd != cwd:
360 if oldcwd != cwd:
362 dhist.append(cwd)
361 dhist.append(cwd)
363 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
362 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
364
363
365 else:
364 else:
366 os.chdir(self.shell.home_dir)
365 os.chdir(self.shell.home_dir)
367 if hasattr(self.shell, 'term_title') and self.shell.term_title:
366 if hasattr(self.shell, 'term_title') and self.shell.term_title:
368 set_term_title(self.shell.term_title_format.format(cwd="~"))
367 set_term_title(self.shell.term_title_format.format(cwd="~"))
369 cwd = os.getcwd()
368 cwd = os.getcwd()
370 dhist = self.shell.user_ns['_dh']
369 dhist = self.shell.user_ns['_dh']
371
370
372 if oldcwd != cwd:
371 if oldcwd != cwd:
373 dhist.append(cwd)
372 dhist.append(cwd)
374 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
373 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
375 if not 'q' in opts and self.shell.user_ns['_dh']:
374 if not 'q' in opts and self.shell.user_ns['_dh']:
376 print(self.shell.user_ns['_dh'][-1])
375 print(self.shell.user_ns['_dh'][-1])
377
376
378 @line_magic
377 @line_magic
379 def env(self, parameter_s=''):
378 def env(self, parameter_s=''):
380 """Get, set, or list environment variables.
379 """Get, set, or list environment variables.
381
380
382 Usage:\\
381 Usage:\\
383
382
384 %env: lists all environment variables/values
383 %env: lists all environment variables/values
385 %env var: get value for var
384 %env var: get value for var
386 %env var val: set value for var
385 %env var val: set value for var
387 %env var=val: set value for var
386 %env var=val: set value for var
388 %env var=$val: set value for var, using python expansion if possible
387 %env var=$val: set value for var, using python expansion if possible
389 """
388 """
390 if parameter_s.strip():
389 if parameter_s.strip():
391 split = '=' if '=' in parameter_s else ' '
390 split = '=' if '=' in parameter_s else ' '
392 bits = parameter_s.split(split)
391 bits = parameter_s.split(split)
393 if len(bits) == 1:
392 if len(bits) == 1:
394 key = parameter_s.strip()
393 key = parameter_s.strip()
395 if key in os.environ:
394 if key in os.environ:
396 return os.environ[key]
395 return os.environ[key]
397 else:
396 else:
398 err = "Environment does not have key: {0}".format(key)
397 err = "Environment does not have key: {0}".format(key)
399 raise UsageError(err)
398 raise UsageError(err)
400 if len(bits) > 1:
399 if len(bits) > 1:
401 return self.set_env(parameter_s)
400 return self.set_env(parameter_s)
402 return dict(os.environ)
401 return dict(os.environ)
403
402
404 @line_magic
403 @line_magic
405 def set_env(self, parameter_s):
404 def set_env(self, parameter_s):
406 """Set environment variables. Assumptions are that either "val" is a
405 """Set environment variables. Assumptions are that either "val" is a
407 name in the user namespace, or val is something that evaluates to a
406 name in the user namespace, or val is something that evaluates to a
408 string.
407 string.
409
408
410 Usage:\\
409 Usage:\\
411 %set_env var val: set value for var
410 %set_env var val: set value for var
412 %set_env var=val: set value for var
411 %set_env var=val: set value for var
413 %set_env var=$val: set value for var, using python expansion if possible
412 %set_env var=$val: set value for var, using python expansion if possible
414 """
413 """
415 split = '=' if '=' in parameter_s else ' '
414 split = '=' if '=' in parameter_s else ' '
416 bits = parameter_s.split(split, 1)
415 bits = parameter_s.split(split, 1)
417 if not parameter_s.strip() or len(bits)<2:
416 if not parameter_s.strip() or len(bits)<2:
418 raise UsageError("usage is 'set_env var=val'")
417 raise UsageError("usage is 'set_env var=val'")
419 var = bits[0].strip()
418 var = bits[0].strip()
420 val = bits[1].strip()
419 val = bits[1].strip()
421 if re.match(r'.*\s.*', var):
420 if re.match(r'.*\s.*', var):
422 # an environment variable with whitespace is almost certainly
421 # an environment variable with whitespace is almost certainly
423 # not what the user intended. what's more likely is the wrong
422 # not what the user intended. what's more likely is the wrong
424 # split was chosen, ie for "set_env cmd_args A=B", we chose
423 # split was chosen, ie for "set_env cmd_args A=B", we chose
425 # '=' for the split and should have chosen ' '. to get around
424 # '=' for the split and should have chosen ' '. to get around
426 # this, users should just assign directly to os.environ or use
425 # this, users should just assign directly to os.environ or use
427 # standard magic {var} expansion.
426 # standard magic {var} expansion.
428 err = "refusing to set env var with whitespace: '{0}'"
427 err = "refusing to set env var with whitespace: '{0}'"
429 err = err.format(val)
428 err = err.format(val)
430 raise UsageError(err)
429 raise UsageError(err)
431 os.environ[var] = val
430 os.environ[var] = val
432 print('env: {0}={1}'.format(var,val))
431 print('env: {0}={1}'.format(var,val))
433
432
434 @line_magic
433 @line_magic
435 def pushd(self, parameter_s=''):
434 def pushd(self, parameter_s=''):
436 """Place the current dir on stack and change directory.
435 """Place the current dir on stack and change directory.
437
436
438 Usage:\\
437 Usage:\\
439 %pushd ['dirname']
438 %pushd ['dirname']
440 """
439 """
441
440
442 dir_s = self.shell.dir_stack
441 dir_s = self.shell.dir_stack
443 tgt = os.path.expanduser(parameter_s)
442 tgt = os.path.expanduser(parameter_s)
444 cwd = os.getcwd().replace(self.shell.home_dir,'~')
443 cwd = os.getcwd().replace(self.shell.home_dir,'~')
445 if tgt:
444 if tgt:
446 self.cd(parameter_s)
445 self.cd(parameter_s)
447 dir_s.insert(0,cwd)
446 dir_s.insert(0,cwd)
448 return self.shell.magic('dirs')
447 return self.shell.magic('dirs')
449
448
450 @line_magic
449 @line_magic
451 def popd(self, parameter_s=''):
450 def popd(self, parameter_s=''):
452 """Change to directory popped off the top of the stack.
451 """Change to directory popped off the top of the stack.
453 """
452 """
454 if not self.shell.dir_stack:
453 if not self.shell.dir_stack:
455 raise UsageError("%popd on empty stack")
454 raise UsageError("%popd on empty stack")
456 top = self.shell.dir_stack.pop(0)
455 top = self.shell.dir_stack.pop(0)
457 self.cd(top)
456 self.cd(top)
458 print("popd ->",top)
457 print("popd ->",top)
459
458
460 @line_magic
459 @line_magic
461 def dirs(self, parameter_s=''):
460 def dirs(self, parameter_s=''):
462 """Return the current directory stack."""
461 """Return the current directory stack."""
463
462
464 return self.shell.dir_stack
463 return self.shell.dir_stack
465
464
466 @line_magic
465 @line_magic
467 def dhist(self, parameter_s=''):
466 def dhist(self, parameter_s=''):
468 """Print your history of visited directories.
467 """Print your history of visited directories.
469
468
470 %dhist -> print full history\\
469 %dhist -> print full history\\
471 %dhist n -> print last n entries only\\
470 %dhist n -> print last n entries only\\
472 %dhist n1 n2 -> print entries between n1 and n2 (n2 not included)\\
471 %dhist n1 n2 -> print entries between n1 and n2 (n2 not included)\\
473
472
474 This history is automatically maintained by the %cd command, and
473 This history is automatically maintained by the %cd command, and
475 always available as the global list variable _dh. You can use %cd -<n>
474 always available as the global list variable _dh. You can use %cd -<n>
476 to go to directory number <n>.
475 to go to directory number <n>.
477
476
478 Note that most of time, you should view directory history by entering
477 Note that most of time, you should view directory history by entering
479 cd -<TAB>.
478 cd -<TAB>.
480
479
481 """
480 """
482
481
483 dh = self.shell.user_ns['_dh']
482 dh = self.shell.user_ns['_dh']
484 if parameter_s:
483 if parameter_s:
485 try:
484 try:
486 args = map(int,parameter_s.split())
485 args = map(int,parameter_s.split())
487 except:
486 except:
488 self.arg_err(self.dhist)
487 self.arg_err(self.dhist)
489 return
488 return
490 if len(args) == 1:
489 if len(args) == 1:
491 ini,fin = max(len(dh)-(args[0]),0),len(dh)
490 ini,fin = max(len(dh)-(args[0]),0),len(dh)
492 elif len(args) == 2:
491 elif len(args) == 2:
493 ini,fin = args
492 ini,fin = args
494 fin = min(fin, len(dh))
493 fin = min(fin, len(dh))
495 else:
494 else:
496 self.arg_err(self.dhist)
495 self.arg_err(self.dhist)
497 return
496 return
498 else:
497 else:
499 ini,fin = 0,len(dh)
498 ini,fin = 0,len(dh)
500 print('Directory history (kept in _dh)')
499 print('Directory history (kept in _dh)')
501 for i in range(ini, fin):
500 for i in range(ini, fin):
502 print("%d: %s" % (i, dh[i]))
501 print("%d: %s" % (i, dh[i]))
503
502
504 @skip_doctest
503 @skip_doctest
505 @line_magic
504 @line_magic
506 def sc(self, parameter_s=''):
505 def sc(self, parameter_s=''):
507 """Shell capture - run shell command and capture output (DEPRECATED use !).
506 """Shell capture - run shell command and capture output (DEPRECATED use !).
508
507
509 DEPRECATED. Suboptimal, retained for backwards compatibility.
508 DEPRECATED. Suboptimal, retained for backwards compatibility.
510
509
511 You should use the form 'var = !command' instead. Example:
510 You should use the form 'var = !command' instead. Example:
512
511
513 "%sc -l myfiles = ls ~" should now be written as
512 "%sc -l myfiles = ls ~" should now be written as
514
513
515 "myfiles = !ls ~"
514 "myfiles = !ls ~"
516
515
517 myfiles.s, myfiles.l and myfiles.n still apply as documented
516 myfiles.s, myfiles.l and myfiles.n still apply as documented
518 below.
517 below.
519
518
520 --
519 --
521 %sc [options] varname=command
520 %sc [options] varname=command
522
521
523 IPython will run the given command using commands.getoutput(), and
522 IPython will run the given command using commands.getoutput(), and
524 will then update the user's interactive namespace with a variable
523 will then update the user's interactive namespace with a variable
525 called varname, containing the value of the call. Your command can
524 called varname, containing the value of the call. Your command can
526 contain shell wildcards, pipes, etc.
525 contain shell wildcards, pipes, etc.
527
526
528 The '=' sign in the syntax is mandatory, and the variable name you
527 The '=' sign in the syntax is mandatory, and the variable name you
529 supply must follow Python's standard conventions for valid names.
528 supply must follow Python's standard conventions for valid names.
530
529
531 (A special format without variable name exists for internal use)
530 (A special format without variable name exists for internal use)
532
531
533 Options:
532 Options:
534
533
535 -l: list output. Split the output on newlines into a list before
534 -l: list output. Split the output on newlines into a list before
536 assigning it to the given variable. By default the output is stored
535 assigning it to the given variable. By default the output is stored
537 as a single string.
536 as a single string.
538
537
539 -v: verbose. Print the contents of the variable.
538 -v: verbose. Print the contents of the variable.
540
539
541 In most cases you should not need to split as a list, because the
540 In most cases you should not need to split as a list, because the
542 returned value is a special type of string which can automatically
541 returned value is a special type of string which can automatically
543 provide its contents either as a list (split on newlines) or as a
542 provide its contents either as a list (split on newlines) or as a
544 space-separated string. These are convenient, respectively, either
543 space-separated string. These are convenient, respectively, either
545 for sequential processing or to be passed to a shell command.
544 for sequential processing or to be passed to a shell command.
546
545
547 For example::
546 For example::
548
547
549 # Capture into variable a
548 # Capture into variable a
550 In [1]: sc a=ls *py
549 In [1]: sc a=ls *py
551
550
552 # a is a string with embedded newlines
551 # a is a string with embedded newlines
553 In [2]: a
552 In [2]: a
554 Out[2]: 'setup.py\\nwin32_manual_post_install.py'
553 Out[2]: 'setup.py\\nwin32_manual_post_install.py'
555
554
556 # which can be seen as a list:
555 # which can be seen as a list:
557 In [3]: a.l
556 In [3]: a.l
558 Out[3]: ['setup.py', 'win32_manual_post_install.py']
557 Out[3]: ['setup.py', 'win32_manual_post_install.py']
559
558
560 # or as a whitespace-separated string:
559 # or as a whitespace-separated string:
561 In [4]: a.s
560 In [4]: a.s
562 Out[4]: 'setup.py win32_manual_post_install.py'
561 Out[4]: 'setup.py win32_manual_post_install.py'
563
562
564 # a.s is useful to pass as a single command line:
563 # a.s is useful to pass as a single command line:
565 In [5]: !wc -l $a.s
564 In [5]: !wc -l $a.s
566 146 setup.py
565 146 setup.py
567 130 win32_manual_post_install.py
566 130 win32_manual_post_install.py
568 276 total
567 276 total
569
568
570 # while the list form is useful to loop over:
569 # while the list form is useful to loop over:
571 In [6]: for f in a.l:
570 In [6]: for f in a.l:
572 ...: !wc -l $f
571 ...: !wc -l $f
573 ...:
572 ...:
574 146 setup.py
573 146 setup.py
575 130 win32_manual_post_install.py
574 130 win32_manual_post_install.py
576
575
577 Similarly, the lists returned by the -l option are also special, in
576 Similarly, the lists returned by the -l option are also special, in
578 the sense that you can equally invoke the .s attribute on them to
577 the sense that you can equally invoke the .s attribute on them to
579 automatically get a whitespace-separated string from their contents::
578 automatically get a whitespace-separated string from their contents::
580
579
581 In [7]: sc -l b=ls *py
580 In [7]: sc -l b=ls *py
582
581
583 In [8]: b
582 In [8]: b
584 Out[8]: ['setup.py', 'win32_manual_post_install.py']
583 Out[8]: ['setup.py', 'win32_manual_post_install.py']
585
584
586 In [9]: b.s
585 In [9]: b.s
587 Out[9]: 'setup.py win32_manual_post_install.py'
586 Out[9]: 'setup.py win32_manual_post_install.py'
588
587
589 In summary, both the lists and strings used for output capture have
588 In summary, both the lists and strings used for output capture have
590 the following special attributes::
589 the following special attributes::
591
590
592 .l (or .list) : value as list.
591 .l (or .list) : value as list.
593 .n (or .nlstr): value as newline-separated string.
592 .n (or .nlstr): value as newline-separated string.
594 .s (or .spstr): value as space-separated string.
593 .s (or .spstr): value as space-separated string.
595 """
594 """
596
595
597 opts,args = self.parse_options(parameter_s, 'lv')
596 opts,args = self.parse_options(parameter_s, 'lv')
598 # Try to get a variable name and command to run
597 # Try to get a variable name and command to run
599 try:
598 try:
600 # the variable name must be obtained from the parse_options
599 # the variable name must be obtained from the parse_options
601 # output, which uses shlex.split to strip options out.
600 # output, which uses shlex.split to strip options out.
602 var,_ = args.split('=', 1)
601 var,_ = args.split('=', 1)
603 var = var.strip()
602 var = var.strip()
604 # But the command has to be extracted from the original input
603 # But the command has to be extracted from the original input
605 # parameter_s, not on what parse_options returns, to avoid the
604 # parameter_s, not on what parse_options returns, to avoid the
606 # quote stripping which shlex.split performs on it.
605 # quote stripping which shlex.split performs on it.
607 _,cmd = parameter_s.split('=', 1)
606 _,cmd = parameter_s.split('=', 1)
608 except ValueError:
607 except ValueError:
609 var,cmd = '',''
608 var,cmd = '',''
610 # If all looks ok, proceed
609 # If all looks ok, proceed
611 split = 'l' in opts
610 split = 'l' in opts
612 out = self.shell.getoutput(cmd, split=split)
611 out = self.shell.getoutput(cmd, split=split)
613 if 'v' in opts:
612 if 'v' in opts:
614 print('%s ==\n%s' % (var, pformat(out)))
613 print('%s ==\n%s' % (var, pformat(out)))
615 if var:
614 if var:
616 self.shell.user_ns.update({var:out})
615 self.shell.user_ns.update({var:out})
617 else:
616 else:
618 return out
617 return out
619
618
620 @line_cell_magic
619 @line_cell_magic
621 def sx(self, line='', cell=None):
620 def sx(self, line='', cell=None):
622 """Shell execute - run shell command and capture output (!! is short-hand).
621 """Shell execute - run shell command and capture output (!! is short-hand).
623
622
624 %sx command
623 %sx command
625
624
626 IPython will run the given command using commands.getoutput(), and
625 IPython will run the given command using commands.getoutput(), and
627 return the result formatted as a list (split on '\\n'). Since the
626 return the result formatted as a list (split on '\\n'). Since the
628 output is _returned_, it will be stored in ipython's regular output
627 output is _returned_, it will be stored in ipython's regular output
629 cache Out[N] and in the '_N' automatic variables.
628 cache Out[N] and in the '_N' automatic variables.
630
629
631 Notes:
630 Notes:
632
631
633 1) If an input line begins with '!!', then %sx is automatically
632 1) If an input line begins with '!!', then %sx is automatically
634 invoked. That is, while::
633 invoked. That is, while::
635
634
636 !ls
635 !ls
637
636
638 causes ipython to simply issue system('ls'), typing::
637 causes ipython to simply issue system('ls'), typing::
639
638
640 !!ls
639 !!ls
641
640
642 is a shorthand equivalent to::
641 is a shorthand equivalent to::
643
642
644 %sx ls
643 %sx ls
645
644
646 2) %sx differs from %sc in that %sx automatically splits into a list,
645 2) %sx differs from %sc in that %sx automatically splits into a list,
647 like '%sc -l'. The reason for this is to make it as easy as possible
646 like '%sc -l'. The reason for this is to make it as easy as possible
648 to process line-oriented shell output via further python commands.
647 to process line-oriented shell output via further python commands.
649 %sc is meant to provide much finer control, but requires more
648 %sc is meant to provide much finer control, but requires more
650 typing.
649 typing.
651
650
652 3) Just like %sc -l, this is a list with special attributes:
651 3) Just like %sc -l, this is a list with special attributes:
653 ::
652 ::
654
653
655 .l (or .list) : value as list.
654 .l (or .list) : value as list.
656 .n (or .nlstr): value as newline-separated string.
655 .n (or .nlstr): value as newline-separated string.
657 .s (or .spstr): value as whitespace-separated string.
656 .s (or .spstr): value as whitespace-separated string.
658
657
659 This is very useful when trying to use such lists as arguments to
658 This is very useful when trying to use such lists as arguments to
660 system commands."""
659 system commands."""
661
660
662 if cell is None:
661 if cell is None:
663 # line magic
662 # line magic
664 return self.shell.getoutput(line)
663 return self.shell.getoutput(line)
665 else:
664 else:
666 opts,args = self.parse_options(line, '', 'out=')
665 opts,args = self.parse_options(line, '', 'out=')
667 output = self.shell.getoutput(cell)
666 output = self.shell.getoutput(cell)
668 out_name = opts.get('out', opts.get('o'))
667 out_name = opts.get('out', opts.get('o'))
669 if out_name:
668 if out_name:
670 self.shell.user_ns[out_name] = output
669 self.shell.user_ns[out_name] = output
671 else:
670 else:
672 return output
671 return output
673
672
674 system = line_cell_magic('system')(sx)
673 system = line_cell_magic('system')(sx)
675 bang = cell_magic('!')(sx)
674 bang = cell_magic('!')(sx)
676
675
677 @line_magic
676 @line_magic
678 def bookmark(self, parameter_s=''):
677 def bookmark(self, parameter_s=''):
679 """Manage IPython's bookmark system.
678 """Manage IPython's bookmark system.
680
679
681 %bookmark <name> - set bookmark to current dir
680 %bookmark <name> - set bookmark to current dir
682 %bookmark <name> <dir> - set bookmark to <dir>
681 %bookmark <name> <dir> - set bookmark to <dir>
683 %bookmark -l - list all bookmarks
682 %bookmark -l - list all bookmarks
684 %bookmark -d <name> - remove bookmark
683 %bookmark -d <name> - remove bookmark
685 %bookmark -r - remove all bookmarks
684 %bookmark -r - remove all bookmarks
686
685
687 You can later on access a bookmarked folder with::
686 You can later on access a bookmarked folder with::
688
687
689 %cd -b <name>
688 %cd -b <name>
690
689
691 or simply '%cd <name>' if there is no directory called <name> AND
690 or simply '%cd <name>' if there is no directory called <name> AND
692 there is such a bookmark defined.
691 there is such a bookmark defined.
693
692
694 Your bookmarks persist through IPython sessions, but they are
693 Your bookmarks persist through IPython sessions, but they are
695 associated with each profile."""
694 associated with each profile."""
696
695
697 opts,args = self.parse_options(parameter_s,'drl',mode='list')
696 opts,args = self.parse_options(parameter_s,'drl',mode='list')
698 if len(args) > 2:
697 if len(args) > 2:
699 raise UsageError("%bookmark: too many arguments")
698 raise UsageError("%bookmark: too many arguments")
700
699
701 bkms = self.shell.db.get('bookmarks',{})
700 bkms = self.shell.db.get('bookmarks',{})
702
701
703 if 'd' in opts:
702 if 'd' in opts:
704 try:
703 try:
705 todel = args[0]
704 todel = args[0]
706 except IndexError:
705 except IndexError:
707 raise UsageError(
706 raise UsageError(
708 "%bookmark -d: must provide a bookmark to delete")
707 "%bookmark -d: must provide a bookmark to delete")
709 else:
708 else:
710 try:
709 try:
711 del bkms[todel]
710 del bkms[todel]
712 except KeyError:
711 except KeyError:
713 raise UsageError(
712 raise UsageError(
714 "%%bookmark -d: Can't delete bookmark '%s'" % todel)
713 "%%bookmark -d: Can't delete bookmark '%s'" % todel)
715
714
716 elif 'r' in opts:
715 elif 'r' in opts:
717 bkms = {}
716 bkms = {}
718 elif 'l' in opts:
717 elif 'l' in opts:
719 bks = sorted(bkms)
718 bks = sorted(bkms)
720 if bks:
719 if bks:
721 size = max(map(len, bks))
720 size = max(map(len, bks))
722 else:
721 else:
723 size = 0
722 size = 0
724 fmt = '%-'+str(size)+'s -> %s'
723 fmt = '%-'+str(size)+'s -> %s'
725 print('Current bookmarks:')
724 print('Current bookmarks:')
726 for bk in bks:
725 for bk in bks:
727 print(fmt % (bk, bkms[bk]))
726 print(fmt % (bk, bkms[bk]))
728 else:
727 else:
729 if not args:
728 if not args:
730 raise UsageError("%bookmark: You must specify the bookmark name")
729 raise UsageError("%bookmark: You must specify the bookmark name")
731 elif len(args)==1:
730 elif len(args)==1:
732 bkms[args[0]] = os.getcwd()
731 bkms[args[0]] = os.getcwd()
733 elif len(args)==2:
732 elif len(args)==2:
734 bkms[args[0]] = args[1]
733 bkms[args[0]] = args[1]
735 self.shell.db['bookmarks'] = bkms
734 self.shell.db['bookmarks'] = bkms
736
735
737 @line_magic
736 @line_magic
738 def pycat(self, parameter_s=''):
737 def pycat(self, parameter_s=''):
739 """Show a syntax-highlighted file through a pager.
738 """Show a syntax-highlighted file through a pager.
740
739
741 This magic is similar to the cat utility, but it will assume the file
740 This magic is similar to the cat utility, but it will assume the file
742 to be Python source and will show it with syntax highlighting.
741 to be Python source and will show it with syntax highlighting.
743
742
744 This magic command can either take a local filename, an url,
743 This magic command can either take a local filename, an url,
745 an history range (see %history) or a macro as argument ::
744 an history range (see %history) or a macro as argument ::
746
745
747 %pycat myscript.py
746 %pycat myscript.py
748 %pycat 7-27
747 %pycat 7-27
749 %pycat myMacro
748 %pycat myMacro
750 %pycat http://www.example.com/myscript.py
749 %pycat http://www.example.com/myscript.py
751 """
750 """
752 if not parameter_s:
751 if not parameter_s:
753 raise UsageError('Missing filename, URL, input history range, '
752 raise UsageError('Missing filename, URL, input history range, '
754 'or macro.')
753 'or macro.')
755
754
756 try :
755 try :
757 cont = self.shell.find_user_code(parameter_s, skip_encoding_cookie=False)
756 cont = self.shell.find_user_code(parameter_s, skip_encoding_cookie=False)
758 except (ValueError, IOError):
757 except (ValueError, IOError):
759 print("Error: no such file, variable, URL, history range or macro")
758 print("Error: no such file, variable, URL, history range or macro")
760 return
759 return
761
760
762 page.page(self.shell.pycolorize(source_to_unicode(cont)))
761 page.page(self.shell.pycolorize(source_to_unicode(cont)))
763
762
764 @magic_arguments.magic_arguments()
763 @magic_arguments.magic_arguments()
765 @magic_arguments.argument(
764 @magic_arguments.argument(
766 '-a', '--append', action='store_true', default=False,
765 '-a', '--append', action='store_true', default=False,
767 help='Append contents of the cell to an existing file. '
766 help='Append contents of the cell to an existing file. '
768 'The file will be created if it does not exist.'
767 'The file will be created if it does not exist.'
769 )
768 )
770 @magic_arguments.argument(
769 @magic_arguments.argument(
771 'filename', type=str,
770 'filename', type=str,
772 help='file to write'
771 help='file to write'
773 )
772 )
774 @cell_magic
773 @cell_magic
775 def writefile(self, line, cell):
774 def writefile(self, line, cell):
776 """Write the contents of the cell to a file.
775 """Write the contents of the cell to a file.
777
776
778 The file will be overwritten unless the -a (--append) flag is specified.
777 The file will be overwritten unless the -a (--append) flag is specified.
779 """
778 """
780 args = magic_arguments.parse_argstring(self.writefile, line)
779 args = magic_arguments.parse_argstring(self.writefile, line)
781 filename = os.path.expanduser(args.filename)
780 filename = os.path.expanduser(args.filename)
782
781
783 if os.path.exists(filename):
782 if os.path.exists(filename):
784 if args.append:
783 if args.append:
785 print("Appending to %s" % filename)
784 print("Appending to %s" % filename)
786 else:
785 else:
787 print("Overwriting %s" % filename)
786 print("Overwriting %s" % filename)
788 else:
787 else:
789 print("Writing %s" % filename)
788 print("Writing %s" % filename)
790
789
791 mode = 'a' if args.append else 'w'
790 mode = 'a' if args.append else 'w'
792 with io.open(filename, mode, encoding='utf-8') as f:
791 with io.open(filename, mode, encoding='utf-8') as f:
793 f.write(cell)
792 f.write(cell)
@@ -1,313 +1,312 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 An application for managing IPython profiles.
3 An application for managing IPython profiles.
4
4
5 To be invoked as the `ipython profile` subcommand.
5 To be invoked as the `ipython profile` subcommand.
6
6
7 Authors:
7 Authors:
8
8
9 * Min RK
9 * Min RK
10
10
11 """
11 """
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Copyright (C) 2008 The IPython Development Team
14 # Copyright (C) 2008 The IPython Development Team
15 #
15 #
16 # Distributed under the terms of the BSD License. The full license is in
16 # Distributed under the terms of the BSD License. The full license is in
17 # the file COPYING, distributed as part of this software.
17 # the file COPYING, distributed as part of this software.
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19
19
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21 # Imports
21 # Imports
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23
23
24 import os
24 import os
25
25
26 from traitlets.config.application import Application
26 from traitlets.config.application import Application
27 from IPython.core.application import (
27 from IPython.core.application import (
28 BaseIPythonApplication, base_flags
28 BaseIPythonApplication, base_flags
29 )
29 )
30 from IPython.core.profiledir import ProfileDir
30 from IPython.core.profiledir import ProfileDir
31 from IPython.utils.importstring import import_item
31 from IPython.utils.importstring import import_item
32 from IPython.paths import get_ipython_dir, get_ipython_package_dir
32 from IPython.paths import get_ipython_dir, get_ipython_package_dir
33 from IPython.utils import py3compat
34 from traitlets import Unicode, Bool, Dict, observe
33 from traitlets import Unicode, Bool, Dict, observe
35
34
36 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
37 # Constants
36 # Constants
38 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
39
38
40 create_help = """Create an IPython profile by name
39 create_help = """Create an IPython profile by name
41
40
42 Create an ipython profile directory by its name or
41 Create an ipython profile directory by its name or
43 profile directory path. Profile directories contain
42 profile directory path. Profile directories contain
44 configuration, log and security related files and are named
43 configuration, log and security related files and are named
45 using the convention 'profile_<name>'. By default they are
44 using the convention 'profile_<name>'. By default they are
46 located in your ipython directory. Once created, you will
45 located in your ipython directory. Once created, you will
47 can edit the configuration files in the profile
46 can edit the configuration files in the profile
48 directory to configure IPython. Most users will create a
47 directory to configure IPython. Most users will create a
49 profile directory by name,
48 profile directory by name,
50 `ipython profile create myprofile`, which will put the directory
49 `ipython profile create myprofile`, which will put the directory
51 in `<ipython_dir>/profile_myprofile`.
50 in `<ipython_dir>/profile_myprofile`.
52 """
51 """
53 list_help = """List available IPython profiles
52 list_help = """List available IPython profiles
54
53
55 List all available profiles, by profile location, that can
54 List all available profiles, by profile location, that can
56 be found in the current working directly or in the ipython
55 be found in the current working directly or in the ipython
57 directory. Profile directories are named using the convention
56 directory. Profile directories are named using the convention
58 'profile_<profile>'.
57 'profile_<profile>'.
59 """
58 """
60 profile_help = """Manage IPython profiles
59 profile_help = """Manage IPython profiles
61
60
62 Profile directories contain
61 Profile directories contain
63 configuration, log and security related files and are named
62 configuration, log and security related files and are named
64 using the convention 'profile_<name>'. By default they are
63 using the convention 'profile_<name>'. By default they are
65 located in your ipython directory. You can create profiles
64 located in your ipython directory. You can create profiles
66 with `ipython profile create <name>`, or see the profiles you
65 with `ipython profile create <name>`, or see the profiles you
67 already have with `ipython profile list`
66 already have with `ipython profile list`
68
67
69 To get started configuring IPython, simply do:
68 To get started configuring IPython, simply do:
70
69
71 $> ipython profile create
70 $> ipython profile create
72
71
73 and IPython will create the default profile in <ipython_dir>/profile_default,
72 and IPython will create the default profile in <ipython_dir>/profile_default,
74 where you can edit ipython_config.py to start configuring IPython.
73 where you can edit ipython_config.py to start configuring IPython.
75
74
76 """
75 """
77
76
78 _list_examples = "ipython profile list # list all profiles"
77 _list_examples = "ipython profile list # list all profiles"
79
78
80 _create_examples = """
79 _create_examples = """
81 ipython profile create foo # create profile foo w/ default config files
80 ipython profile create foo # create profile foo w/ default config files
82 ipython profile create foo --reset # restage default config files over current
81 ipython profile create foo --reset # restage default config files over current
83 ipython profile create foo --parallel # also stage parallel config files
82 ipython profile create foo --parallel # also stage parallel config files
84 """
83 """
85
84
86 _main_examples = """
85 _main_examples = """
87 ipython profile create -h # show the help string for the create subcommand
86 ipython profile create -h # show the help string for the create subcommand
88 ipython profile list -h # show the help string for the list subcommand
87 ipython profile list -h # show the help string for the list subcommand
89
88
90 ipython locate profile foo # print the path to the directory for profile 'foo'
89 ipython locate profile foo # print the path to the directory for profile 'foo'
91 """
90 """
92
91
93 #-----------------------------------------------------------------------------
92 #-----------------------------------------------------------------------------
94 # Profile Application Class (for `ipython profile` subcommand)
93 # Profile Application Class (for `ipython profile` subcommand)
95 #-----------------------------------------------------------------------------
94 #-----------------------------------------------------------------------------
96
95
97
96
98 def list_profiles_in(path):
97 def list_profiles_in(path):
99 """list profiles in a given root directory"""
98 """list profiles in a given root directory"""
100 files = os.listdir(path)
99 files = os.listdir(path)
101 profiles = []
100 profiles = []
102 for f in files:
101 for f in files:
103 try:
102 try:
104 full_path = os.path.join(path, f)
103 full_path = os.path.join(path, f)
105 except UnicodeError:
104 except UnicodeError:
106 continue
105 continue
107 if os.path.isdir(full_path) and f.startswith('profile_'):
106 if os.path.isdir(full_path) and f.startswith('profile_'):
108 profiles.append(f.split('_',1)[-1])
107 profiles.append(f.split('_',1)[-1])
109 return profiles
108 return profiles
110
109
111
110
112 def list_bundled_profiles():
111 def list_bundled_profiles():
113 """list profiles that are bundled with IPython."""
112 """list profiles that are bundled with IPython."""
114 path = os.path.join(get_ipython_package_dir(), u'core', u'profile')
113 path = os.path.join(get_ipython_package_dir(), u'core', u'profile')
115 files = os.listdir(path)
114 files = os.listdir(path)
116 profiles = []
115 profiles = []
117 for profile in files:
116 for profile in files:
118 full_path = os.path.join(path, profile)
117 full_path = os.path.join(path, profile)
119 if os.path.isdir(full_path) and profile != "__pycache__":
118 if os.path.isdir(full_path) and profile != "__pycache__":
120 profiles.append(profile)
119 profiles.append(profile)
121 return profiles
120 return profiles
122
121
123
122
124 class ProfileLocate(BaseIPythonApplication):
123 class ProfileLocate(BaseIPythonApplication):
125 description = """print the path to an IPython profile dir"""
124 description = """print the path to an IPython profile dir"""
126
125
127 def parse_command_line(self, argv=None):
126 def parse_command_line(self, argv=None):
128 super(ProfileLocate, self).parse_command_line(argv)
127 super(ProfileLocate, self).parse_command_line(argv)
129 if self.extra_args:
128 if self.extra_args:
130 self.profile = self.extra_args[0]
129 self.profile = self.extra_args[0]
131
130
132 def start(self):
131 def start(self):
133 print(self.profile_dir.location)
132 print(self.profile_dir.location)
134
133
135
134
136 class ProfileList(Application):
135 class ProfileList(Application):
137 name = u'ipython-profile'
136 name = u'ipython-profile'
138 description = list_help
137 description = list_help
139 examples = _list_examples
138 examples = _list_examples
140
139
141 aliases = Dict({
140 aliases = Dict({
142 'ipython-dir' : 'ProfileList.ipython_dir',
141 'ipython-dir' : 'ProfileList.ipython_dir',
143 'log-level' : 'Application.log_level',
142 'log-level' : 'Application.log_level',
144 })
143 })
145 flags = Dict(dict(
144 flags = Dict(dict(
146 debug = ({'Application' : {'log_level' : 0}},
145 debug = ({'Application' : {'log_level' : 0}},
147 "Set Application.log_level to 0, maximizing log output."
146 "Set Application.log_level to 0, maximizing log output."
148 )
147 )
149 ))
148 ))
150
149
151 ipython_dir = Unicode(get_ipython_dir(),
150 ipython_dir = Unicode(get_ipython_dir(),
152 help="""
151 help="""
153 The name of the IPython directory. This directory is used for logging
152 The name of the IPython directory. This directory is used for logging
154 configuration (through profiles), history storage, etc. The default
153 configuration (through profiles), history storage, etc. The default
155 is usually $HOME/.ipython. This options can also be specified through
154 is usually $HOME/.ipython. This options can also be specified through
156 the environment variable IPYTHONDIR.
155 the environment variable IPYTHONDIR.
157 """
156 """
158 ).tag(config=True)
157 ).tag(config=True)
159
158
160
159
161 def _print_profiles(self, profiles):
160 def _print_profiles(self, profiles):
162 """print list of profiles, indented."""
161 """print list of profiles, indented."""
163 for profile in profiles:
162 for profile in profiles:
164 print(' %s' % profile)
163 print(' %s' % profile)
165
164
166 def list_profile_dirs(self):
165 def list_profile_dirs(self):
167 profiles = list_bundled_profiles()
166 profiles = list_bundled_profiles()
168 if profiles:
167 if profiles:
169 print()
168 print()
170 print("Available profiles in IPython:")
169 print("Available profiles in IPython:")
171 self._print_profiles(profiles)
170 self._print_profiles(profiles)
172 print()
171 print()
173 print(" The first request for a bundled profile will copy it")
172 print(" The first request for a bundled profile will copy it")
174 print(" into your IPython directory (%s)," % self.ipython_dir)
173 print(" into your IPython directory (%s)," % self.ipython_dir)
175 print(" where you can customize it.")
174 print(" where you can customize it.")
176
175
177 profiles = list_profiles_in(self.ipython_dir)
176 profiles = list_profiles_in(self.ipython_dir)
178 if profiles:
177 if profiles:
179 print()
178 print()
180 print("Available profiles in %s:" % self.ipython_dir)
179 print("Available profiles in %s:" % self.ipython_dir)
181 self._print_profiles(profiles)
180 self._print_profiles(profiles)
182
181
183 profiles = list_profiles_in(os.getcwd())
182 profiles = list_profiles_in(os.getcwd())
184 if profiles:
183 if profiles:
185 print()
184 print()
186 print("Available profiles in current directory (%s):" % os.getcwd())
185 print("Available profiles in current directory (%s):" % os.getcwd())
187 self._print_profiles(profiles)
186 self._print_profiles(profiles)
188
187
189 print()
188 print()
190 print("To use any of the above profiles, start IPython with:")
189 print("To use any of the above profiles, start IPython with:")
191 print(" ipython --profile=<name>")
190 print(" ipython --profile=<name>")
192 print()
191 print()
193
192
194 def start(self):
193 def start(self):
195 self.list_profile_dirs()
194 self.list_profile_dirs()
196
195
197
196
198 create_flags = {}
197 create_flags = {}
199 create_flags.update(base_flags)
198 create_flags.update(base_flags)
200 # don't include '--init' flag, which implies running profile create in other apps
199 # don't include '--init' flag, which implies running profile create in other apps
201 create_flags.pop('init')
200 create_flags.pop('init')
202 create_flags['reset'] = ({'ProfileCreate': {'overwrite' : True}},
201 create_flags['reset'] = ({'ProfileCreate': {'overwrite' : True}},
203 "reset config files in this profile to the defaults.")
202 "reset config files in this profile to the defaults.")
204 create_flags['parallel'] = ({'ProfileCreate': {'parallel' : True}},
203 create_flags['parallel'] = ({'ProfileCreate': {'parallel' : True}},
205 "Include the config files for parallel "
204 "Include the config files for parallel "
206 "computing apps (ipengine, ipcontroller, etc.)")
205 "computing apps (ipengine, ipcontroller, etc.)")
207
206
208
207
209 class ProfileCreate(BaseIPythonApplication):
208 class ProfileCreate(BaseIPythonApplication):
210 name = u'ipython-profile'
209 name = u'ipython-profile'
211 description = create_help
210 description = create_help
212 examples = _create_examples
211 examples = _create_examples
213 auto_create = Bool(True)
212 auto_create = Bool(True)
214 def _log_format_default(self):
213 def _log_format_default(self):
215 return "[%(name)s] %(message)s"
214 return "[%(name)s] %(message)s"
216
215
217 def _copy_config_files_default(self):
216 def _copy_config_files_default(self):
218 return True
217 return True
219
218
220 parallel = Bool(False,
219 parallel = Bool(False,
221 help="whether to include parallel computing config files"
220 help="whether to include parallel computing config files"
222 ).tag(config=True)
221 ).tag(config=True)
223
222
224 @observe('parallel')
223 @observe('parallel')
225 def _parallel_changed(self, change):
224 def _parallel_changed(self, change):
226 parallel_files = [ 'ipcontroller_config.py',
225 parallel_files = [ 'ipcontroller_config.py',
227 'ipengine_config.py',
226 'ipengine_config.py',
228 'ipcluster_config.py'
227 'ipcluster_config.py'
229 ]
228 ]
230 if change['new']:
229 if change['new']:
231 for cf in parallel_files:
230 for cf in parallel_files:
232 self.config_files.append(cf)
231 self.config_files.append(cf)
233 else:
232 else:
234 for cf in parallel_files:
233 for cf in parallel_files:
235 if cf in self.config_files:
234 if cf in self.config_files:
236 self.config_files.remove(cf)
235 self.config_files.remove(cf)
237
236
238 def parse_command_line(self, argv):
237 def parse_command_line(self, argv):
239 super(ProfileCreate, self).parse_command_line(argv)
238 super(ProfileCreate, self).parse_command_line(argv)
240 # accept positional arg as profile name
239 # accept positional arg as profile name
241 if self.extra_args:
240 if self.extra_args:
242 self.profile = self.extra_args[0]
241 self.profile = self.extra_args[0]
243
242
244 flags = Dict(create_flags)
243 flags = Dict(create_flags)
245
244
246 classes = [ProfileDir]
245 classes = [ProfileDir]
247
246
248 def _import_app(self, app_path):
247 def _import_app(self, app_path):
249 """import an app class"""
248 """import an app class"""
250 app = None
249 app = None
251 name = app_path.rsplit('.', 1)[-1]
250 name = app_path.rsplit('.', 1)[-1]
252 try:
251 try:
253 app = import_item(app_path)
252 app = import_item(app_path)
254 except ImportError:
253 except ImportError:
255 self.log.info("Couldn't import %s, config file will be excluded", name)
254 self.log.info("Couldn't import %s, config file will be excluded", name)
256 except Exception:
255 except Exception:
257 self.log.warning('Unexpected error importing %s', name, exc_info=True)
256 self.log.warning('Unexpected error importing %s', name, exc_info=True)
258 return app
257 return app
259
258
260 def init_config_files(self):
259 def init_config_files(self):
261 super(ProfileCreate, self).init_config_files()
260 super(ProfileCreate, self).init_config_files()
262 # use local imports, since these classes may import from here
261 # use local imports, since these classes may import from here
263 from IPython.terminal.ipapp import TerminalIPythonApp
262 from IPython.terminal.ipapp import TerminalIPythonApp
264 apps = [TerminalIPythonApp]
263 apps = [TerminalIPythonApp]
265 for app_path in (
264 for app_path in (
266 'ipykernel.kernelapp.IPKernelApp',
265 'ipykernel.kernelapp.IPKernelApp',
267 ):
266 ):
268 app = self._import_app(app_path)
267 app = self._import_app(app_path)
269 if app is not None:
268 if app is not None:
270 apps.append(app)
269 apps.append(app)
271 if self.parallel:
270 if self.parallel:
272 from ipyparallel.apps.ipcontrollerapp import IPControllerApp
271 from ipyparallel.apps.ipcontrollerapp import IPControllerApp
273 from ipyparallel.apps.ipengineapp import IPEngineApp
272 from ipyparallel.apps.ipengineapp import IPEngineApp
274 from ipyparallel.apps.ipclusterapp import IPClusterStart
273 from ipyparallel.apps.ipclusterapp import IPClusterStart
275 apps.extend([
274 apps.extend([
276 IPControllerApp,
275 IPControllerApp,
277 IPEngineApp,
276 IPEngineApp,
278 IPClusterStart,
277 IPClusterStart,
279 ])
278 ])
280 for App in apps:
279 for App in apps:
281 app = App()
280 app = App()
282 app.config.update(self.config)
281 app.config.update(self.config)
283 app.log = self.log
282 app.log = self.log
284 app.overwrite = self.overwrite
283 app.overwrite = self.overwrite
285 app.copy_config_files=True
284 app.copy_config_files=True
286 app.ipython_dir=self.ipython_dir
285 app.ipython_dir=self.ipython_dir
287 app.profile_dir=self.profile_dir
286 app.profile_dir=self.profile_dir
288 app.init_config_files()
287 app.init_config_files()
289
288
290 def stage_default_config_file(self):
289 def stage_default_config_file(self):
291 pass
290 pass
292
291
293
292
294 class ProfileApp(Application):
293 class ProfileApp(Application):
295 name = u'ipython profile'
294 name = u'ipython profile'
296 description = profile_help
295 description = profile_help
297 examples = _main_examples
296 examples = _main_examples
298
297
299 subcommands = Dict(dict(
298 subcommands = Dict(dict(
300 create = (ProfileCreate, ProfileCreate.description.splitlines()[0]),
299 create = (ProfileCreate, ProfileCreate.description.splitlines()[0]),
301 list = (ProfileList, ProfileList.description.splitlines()[0]),
300 list = (ProfileList, ProfileList.description.splitlines()[0]),
302 locate = (ProfileLocate, ProfileLocate.description.splitlines()[0]),
301 locate = (ProfileLocate, ProfileLocate.description.splitlines()[0]),
303 ))
302 ))
304
303
305 def start(self):
304 def start(self):
306 if self.subapp is None:
305 if self.subapp is None:
307 print("No subcommand specified. Must specify one of: %s"%(self.subcommands.keys()))
306 print("No subcommand specified. Must specify one of: %s"%(self.subcommands.keys()))
308 print()
307 print()
309 self.print_description()
308 self.print_description()
310 self.print_subcommands()
309 self.print_subcommands()
311 self.exit(1)
310 self.exit(1)
312 else:
311 else:
313 return self.subapp.start()
312 return self.subapp.start()
@@ -1,224 +1,223 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """An object for managing IPython profile directories."""
2 """An object for managing IPython profile directories."""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7 import os
7 import os
8 import shutil
8 import shutil
9 import errno
9 import errno
10
10
11 from traitlets.config.configurable import LoggingConfigurable
11 from traitlets.config.configurable import LoggingConfigurable
12 from IPython.paths import get_ipython_package_dir
12 from IPython.paths import get_ipython_package_dir
13 from IPython.utils.path import expand_path, ensure_dir_exists
13 from IPython.utils.path import expand_path, ensure_dir_exists
14 from IPython.utils import py3compat
15 from traitlets import Unicode, Bool, observe
14 from traitlets import Unicode, Bool, observe
16
15
17 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
18 # Module errors
17 # Module errors
19 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
20
19
21 class ProfileDirError(Exception):
20 class ProfileDirError(Exception):
22 pass
21 pass
23
22
24
23
25 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
26 # Class for managing profile directories
25 # Class for managing profile directories
27 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
28
27
29 class ProfileDir(LoggingConfigurable):
28 class ProfileDir(LoggingConfigurable):
30 """An object to manage the profile directory and its resources.
29 """An object to manage the profile directory and its resources.
31
30
32 The profile directory is used by all IPython applications, to manage
31 The profile directory is used by all IPython applications, to manage
33 configuration, logging and security.
32 configuration, logging and security.
34
33
35 This object knows how to find, create and manage these directories. This
34 This object knows how to find, create and manage these directories. This
36 should be used by any code that wants to handle profiles.
35 should be used by any code that wants to handle profiles.
37 """
36 """
38
37
39 security_dir_name = Unicode('security')
38 security_dir_name = Unicode('security')
40 log_dir_name = Unicode('log')
39 log_dir_name = Unicode('log')
41 startup_dir_name = Unicode('startup')
40 startup_dir_name = Unicode('startup')
42 pid_dir_name = Unicode('pid')
41 pid_dir_name = Unicode('pid')
43 static_dir_name = Unicode('static')
42 static_dir_name = Unicode('static')
44 security_dir = Unicode(u'')
43 security_dir = Unicode(u'')
45 log_dir = Unicode(u'')
44 log_dir = Unicode(u'')
46 startup_dir = Unicode(u'')
45 startup_dir = Unicode(u'')
47 pid_dir = Unicode(u'')
46 pid_dir = Unicode(u'')
48 static_dir = Unicode(u'')
47 static_dir = Unicode(u'')
49
48
50 location = Unicode(u'',
49 location = Unicode(u'',
51 help="""Set the profile location directly. This overrides the logic used by the
50 help="""Set the profile location directly. This overrides the logic used by the
52 `profile` option.""",
51 `profile` option.""",
53 ).tag(config=True)
52 ).tag(config=True)
54
53
55 _location_isset = Bool(False) # flag for detecting multiply set location
54 _location_isset = Bool(False) # flag for detecting multiply set location
56 @observe('location')
55 @observe('location')
57 def _location_changed(self, change):
56 def _location_changed(self, change):
58 if self._location_isset:
57 if self._location_isset:
59 raise RuntimeError("Cannot set profile location more than once.")
58 raise RuntimeError("Cannot set profile location more than once.")
60 self._location_isset = True
59 self._location_isset = True
61 new = change['new']
60 new = change['new']
62 ensure_dir_exists(new)
61 ensure_dir_exists(new)
63
62
64 # ensure config files exist:
63 # ensure config files exist:
65 self.security_dir = os.path.join(new, self.security_dir_name)
64 self.security_dir = os.path.join(new, self.security_dir_name)
66 self.log_dir = os.path.join(new, self.log_dir_name)
65 self.log_dir = os.path.join(new, self.log_dir_name)
67 self.startup_dir = os.path.join(new, self.startup_dir_name)
66 self.startup_dir = os.path.join(new, self.startup_dir_name)
68 self.pid_dir = os.path.join(new, self.pid_dir_name)
67 self.pid_dir = os.path.join(new, self.pid_dir_name)
69 self.static_dir = os.path.join(new, self.static_dir_name)
68 self.static_dir = os.path.join(new, self.static_dir_name)
70 self.check_dirs()
69 self.check_dirs()
71
70
72 def _mkdir(self, path, mode=None):
71 def _mkdir(self, path, mode=None):
73 """ensure a directory exists at a given path
72 """ensure a directory exists at a given path
74
73
75 This is a version of os.mkdir, with the following differences:
74 This is a version of os.mkdir, with the following differences:
76
75
77 - returns True if it created the directory, False otherwise
76 - returns True if it created the directory, False otherwise
78 - ignores EEXIST, protecting against race conditions where
77 - ignores EEXIST, protecting against race conditions where
79 the dir may have been created in between the check and
78 the dir may have been created in between the check and
80 the creation
79 the creation
81 - sets permissions if requested and the dir already exists
80 - sets permissions if requested and the dir already exists
82 """
81 """
83 if os.path.exists(path):
82 if os.path.exists(path):
84 if mode and os.stat(path).st_mode != mode:
83 if mode and os.stat(path).st_mode != mode:
85 try:
84 try:
86 os.chmod(path, mode)
85 os.chmod(path, mode)
87 except OSError:
86 except OSError:
88 self.log.warning(
87 self.log.warning(
89 "Could not set permissions on %s",
88 "Could not set permissions on %s",
90 path
89 path
91 )
90 )
92 return False
91 return False
93 try:
92 try:
94 if mode:
93 if mode:
95 os.mkdir(path, mode)
94 os.mkdir(path, mode)
96 else:
95 else:
97 os.mkdir(path)
96 os.mkdir(path)
98 except OSError as e:
97 except OSError as e:
99 if e.errno == errno.EEXIST:
98 if e.errno == errno.EEXIST:
100 return False
99 return False
101 else:
100 else:
102 raise
101 raise
103
102
104 return True
103 return True
105
104
106 @observe('log_dir')
105 @observe('log_dir')
107 def check_log_dir(self, change=None):
106 def check_log_dir(self, change=None):
108 self._mkdir(self.log_dir)
107 self._mkdir(self.log_dir)
109
108
110 @observe('startup_dir')
109 @observe('startup_dir')
111 def check_startup_dir(self, change=None):
110 def check_startup_dir(self, change=None):
112 self._mkdir(self.startup_dir)
111 self._mkdir(self.startup_dir)
113
112
114 readme = os.path.join(self.startup_dir, 'README')
113 readme = os.path.join(self.startup_dir, 'README')
115 src = os.path.join(get_ipython_package_dir(), u'core', u'profile', u'README_STARTUP')
114 src = os.path.join(get_ipython_package_dir(), u'core', u'profile', u'README_STARTUP')
116
115
117 if not os.path.exists(src):
116 if not os.path.exists(src):
118 self.log.warning("Could not copy README_STARTUP to startup dir. Source file %s does not exist.", src)
117 self.log.warning("Could not copy README_STARTUP to startup dir. Source file %s does not exist.", src)
119
118
120 if os.path.exists(src) and not os.path.exists(readme):
119 if os.path.exists(src) and not os.path.exists(readme):
121 shutil.copy(src, readme)
120 shutil.copy(src, readme)
122
121
123 @observe('security_dir')
122 @observe('security_dir')
124 def check_security_dir(self, change=None):
123 def check_security_dir(self, change=None):
125 self._mkdir(self.security_dir, 0o40700)
124 self._mkdir(self.security_dir, 0o40700)
126
125
127 @observe('pid_dir')
126 @observe('pid_dir')
128 def check_pid_dir(self, change=None):
127 def check_pid_dir(self, change=None):
129 self._mkdir(self.pid_dir, 0o40700)
128 self._mkdir(self.pid_dir, 0o40700)
130
129
131 def check_dirs(self):
130 def check_dirs(self):
132 self.check_security_dir()
131 self.check_security_dir()
133 self.check_log_dir()
132 self.check_log_dir()
134 self.check_pid_dir()
133 self.check_pid_dir()
135 self.check_startup_dir()
134 self.check_startup_dir()
136
135
137 def copy_config_file(self, config_file, path=None, overwrite=False):
136 def copy_config_file(self, config_file, path=None, overwrite=False):
138 """Copy a default config file into the active profile directory.
137 """Copy a default config file into the active profile directory.
139
138
140 Default configuration files are kept in :mod:`IPython.core.profile`.
139 Default configuration files are kept in :mod:`IPython.core.profile`.
141 This function moves these from that location to the working profile
140 This function moves these from that location to the working profile
142 directory.
141 directory.
143 """
142 """
144 dst = os.path.join(self.location, config_file)
143 dst = os.path.join(self.location, config_file)
145 if os.path.isfile(dst) and not overwrite:
144 if os.path.isfile(dst) and not overwrite:
146 return False
145 return False
147 if path is None:
146 if path is None:
148 path = os.path.join(get_ipython_package_dir(), u'core', u'profile', u'default')
147 path = os.path.join(get_ipython_package_dir(), u'core', u'profile', u'default')
149 src = os.path.join(path, config_file)
148 src = os.path.join(path, config_file)
150 shutil.copy(src, dst)
149 shutil.copy(src, dst)
151 return True
150 return True
152
151
153 @classmethod
152 @classmethod
154 def create_profile_dir(cls, profile_dir, config=None):
153 def create_profile_dir(cls, profile_dir, config=None):
155 """Create a new profile directory given a full path.
154 """Create a new profile directory given a full path.
156
155
157 Parameters
156 Parameters
158 ----------
157 ----------
159 profile_dir : str
158 profile_dir : str
160 The full path to the profile directory. If it does exist, it will
159 The full path to the profile directory. If it does exist, it will
161 be used. If not, it will be created.
160 be used. If not, it will be created.
162 """
161 """
163 return cls(location=profile_dir, config=config)
162 return cls(location=profile_dir, config=config)
164
163
165 @classmethod
164 @classmethod
166 def create_profile_dir_by_name(cls, path, name=u'default', config=None):
165 def create_profile_dir_by_name(cls, path, name=u'default', config=None):
167 """Create a profile dir by profile name and path.
166 """Create a profile dir by profile name and path.
168
167
169 Parameters
168 Parameters
170 ----------
169 ----------
171 path : unicode
170 path : unicode
172 The path (directory) to put the profile directory in.
171 The path (directory) to put the profile directory in.
173 name : unicode
172 name : unicode
174 The name of the profile. The name of the profile directory will
173 The name of the profile. The name of the profile directory will
175 be "profile_<profile>".
174 be "profile_<profile>".
176 """
175 """
177 if not os.path.isdir(path):
176 if not os.path.isdir(path):
178 raise ProfileDirError('Directory not found: %s' % path)
177 raise ProfileDirError('Directory not found: %s' % path)
179 profile_dir = os.path.join(path, u'profile_' + name)
178 profile_dir = os.path.join(path, u'profile_' + name)
180 return cls(location=profile_dir, config=config)
179 return cls(location=profile_dir, config=config)
181
180
182 @classmethod
181 @classmethod
183 def find_profile_dir_by_name(cls, ipython_dir, name=u'default', config=None):
182 def find_profile_dir_by_name(cls, ipython_dir, name=u'default', config=None):
184 """Find an existing profile dir by profile name, return its ProfileDir.
183 """Find an existing profile dir by profile name, return its ProfileDir.
185
184
186 This searches through a sequence of paths for a profile dir. If it
185 This searches through a sequence of paths for a profile dir. If it
187 is not found, a :class:`ProfileDirError` exception will be raised.
186 is not found, a :class:`ProfileDirError` exception will be raised.
188
187
189 The search path algorithm is:
188 The search path algorithm is:
190 1. ``os.getcwd()``
189 1. ``os.getcwd()``
191 2. ``ipython_dir``
190 2. ``ipython_dir``
192
191
193 Parameters
192 Parameters
194 ----------
193 ----------
195 ipython_dir : unicode or str
194 ipython_dir : unicode or str
196 The IPython directory to use.
195 The IPython directory to use.
197 name : unicode or str
196 name : unicode or str
198 The name of the profile. The name of the profile directory
197 The name of the profile. The name of the profile directory
199 will be "profile_<profile>".
198 will be "profile_<profile>".
200 """
199 """
201 dirname = u'profile_' + name
200 dirname = u'profile_' + name
202 paths = [os.getcwd(), ipython_dir]
201 paths = [os.getcwd(), ipython_dir]
203 for p in paths:
202 for p in paths:
204 profile_dir = os.path.join(p, dirname)
203 profile_dir = os.path.join(p, dirname)
205 if os.path.isdir(profile_dir):
204 if os.path.isdir(profile_dir):
206 return cls(location=profile_dir, config=config)
205 return cls(location=profile_dir, config=config)
207 else:
206 else:
208 raise ProfileDirError('Profile directory not found in paths: %s' % dirname)
207 raise ProfileDirError('Profile directory not found in paths: %s' % dirname)
209
208
210 @classmethod
209 @classmethod
211 def find_profile_dir(cls, profile_dir, config=None):
210 def find_profile_dir(cls, profile_dir, config=None):
212 """Find/create a profile dir and return its ProfileDir.
211 """Find/create a profile dir and return its ProfileDir.
213
212
214 This will create the profile directory if it doesn't exist.
213 This will create the profile directory if it doesn't exist.
215
214
216 Parameters
215 Parameters
217 ----------
216 ----------
218 profile_dir : unicode or str
217 profile_dir : unicode or str
219 The path of the profile directory.
218 The path of the profile directory.
220 """
219 """
221 profile_dir = expand_path(profile_dir)
220 profile_dir = expand_path(profile_dir)
222 if not os.path.isdir(profile_dir):
221 if not os.path.isdir(profile_dir):
223 raise ProfileDirError('Profile directory not found: %s' % profile_dir)
222 raise ProfileDirError('Profile directory not found: %s' % profile_dir)
224 return cls(location=profile_dir, config=config)
223 return cls(location=profile_dir, config=config)
@@ -1,23 +1,21 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Being removed
2 """Being removed
3 """
3 """
4
4
5 from IPython.utils import py3compat
6
7 class LazyEvaluate(object):
5 class LazyEvaluate(object):
8 """This is used for formatting strings with values that need to be updated
6 """This is used for formatting strings with values that need to be updated
9 at that time, such as the current time or working directory."""
7 at that time, such as the current time or working directory."""
10 def __init__(self, func, *args, **kwargs):
8 def __init__(self, func, *args, **kwargs):
11 self.func = func
9 self.func = func
12 self.args = args
10 self.args = args
13 self.kwargs = kwargs
11 self.kwargs = kwargs
14
12
15 def __call__(self, **kwargs):
13 def __call__(self, **kwargs):
16 self.kwargs.update(kwargs)
14 self.kwargs.update(kwargs)
17 return self.func(*self.args, **self.kwargs)
15 return self.func(*self.args, **self.kwargs)
18
16
19 def __str__(self):
17 def __str__(self):
20 return str(self())
18 return str(self())
21
19
22 def __format__(self, format_spec):
20 def __format__(self, format_spec):
23 return format(self(), format_spec)
21 return format(self(), format_spec)
@@ -1,410 +1,408 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Pylab (matplotlib) support utilities."""
2 """Pylab (matplotlib) support utilities."""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7 from io import BytesIO
7 from io import BytesIO
8
8
9 from IPython.core.display import _pngxy
9 from IPython.core.display import _pngxy
10 from IPython.utils.decorators import flag_calls
10 from IPython.utils.decorators import flag_calls
11 from IPython.utils import py3compat
12
11
13 # If user specifies a GUI, that dictates the backend, otherwise we read the
12 # If user specifies a GUI, that dictates the backend, otherwise we read the
14 # user's mpl default from the mpl rc structure
13 # user's mpl default from the mpl rc structure
15 backends = {'tk': 'TkAgg',
14 backends = {'tk': 'TkAgg',
16 'gtk': 'GTKAgg',
15 'gtk': 'GTKAgg',
17 'gtk3': 'GTK3Agg',
16 'gtk3': 'GTK3Agg',
18 'wx': 'WXAgg',
17 'wx': 'WXAgg',
19 'qt': 'Qt4Agg', # qt3 not supported
18 'qt': 'Qt4Agg', # qt3 not supported
20 'qt4': 'Qt4Agg',
19 'qt4': 'Qt4Agg',
21 'qt5': 'Qt5Agg',
20 'qt5': 'Qt5Agg',
22 'osx': 'MacOSX',
21 'osx': 'MacOSX',
23 'nbagg': 'nbAgg',
22 'nbagg': 'nbAgg',
24 'notebook': 'nbAgg',
23 'notebook': 'nbAgg',
25 'agg': 'agg',
24 'agg': 'agg',
26 'inline': 'module://ipykernel.pylab.backend_inline',
25 'inline': 'module://ipykernel.pylab.backend_inline',
27 'ipympl': 'module://ipympl.backend_nbagg',
26 'ipympl': 'module://ipympl.backend_nbagg',
28 }
27 }
29
28
30 # We also need a reverse backends2guis mapping that will properly choose which
29 # We also need a reverse backends2guis mapping that will properly choose which
31 # GUI support to activate based on the desired matplotlib backend. For the
30 # GUI support to activate based on the desired matplotlib backend. For the
32 # most part it's just a reverse of the above dict, but we also need to add a
31 # most part it's just a reverse of the above dict, but we also need to add a
33 # few others that map to the same GUI manually:
32 # few others that map to the same GUI manually:
34 backend2gui = dict(zip(backends.values(), backends.keys()))
33 backend2gui = dict(zip(backends.values(), backends.keys()))
35 # Our tests expect backend2gui to just return 'qt'
34 # Our tests expect backend2gui to just return 'qt'
36 backend2gui['Qt4Agg'] = 'qt'
35 backend2gui['Qt4Agg'] = 'qt'
37 # In the reverse mapping, there are a few extra valid matplotlib backends that
36 # In the reverse mapping, there are a few extra valid matplotlib backends that
38 # map to the same GUI support
37 # map to the same GUI support
39 backend2gui['GTK'] = backend2gui['GTKCairo'] = 'gtk'
38 backend2gui['GTK'] = backend2gui['GTKCairo'] = 'gtk'
40 backend2gui['GTK3Cairo'] = 'gtk3'
39 backend2gui['GTK3Cairo'] = 'gtk3'
41 backend2gui['WX'] = 'wx'
40 backend2gui['WX'] = 'wx'
42 backend2gui['CocoaAgg'] = 'osx'
41 backend2gui['CocoaAgg'] = 'osx'
43 # And some backends that don't need GUI integration
42 # And some backends that don't need GUI integration
44 del backend2gui['nbAgg']
43 del backend2gui['nbAgg']
45 del backend2gui['agg']
44 del backend2gui['agg']
46 del backend2gui['module://ipykernel.pylab.backend_inline']
45 del backend2gui['module://ipykernel.pylab.backend_inline']
47
46
48 #-----------------------------------------------------------------------------
47 #-----------------------------------------------------------------------------
49 # Matplotlib utilities
48 # Matplotlib utilities
50 #-----------------------------------------------------------------------------
49 #-----------------------------------------------------------------------------
51
50
52
51
53 def getfigs(*fig_nums):
52 def getfigs(*fig_nums):
54 """Get a list of matplotlib figures by figure numbers.
53 """Get a list of matplotlib figures by figure numbers.
55
54
56 If no arguments are given, all available figures are returned. If the
55 If no arguments are given, all available figures are returned. If the
57 argument list contains references to invalid figures, a warning is printed
56 argument list contains references to invalid figures, a warning is printed
58 but the function continues pasting further figures.
57 but the function continues pasting further figures.
59
58
60 Parameters
59 Parameters
61 ----------
60 ----------
62 figs : tuple
61 figs : tuple
63 A tuple of ints giving the figure numbers of the figures to return.
62 A tuple of ints giving the figure numbers of the figures to return.
64 """
63 """
65 from matplotlib._pylab_helpers import Gcf
64 from matplotlib._pylab_helpers import Gcf
66 if not fig_nums:
65 if not fig_nums:
67 fig_managers = Gcf.get_all_fig_managers()
66 fig_managers = Gcf.get_all_fig_managers()
68 return [fm.canvas.figure for fm in fig_managers]
67 return [fm.canvas.figure for fm in fig_managers]
69 else:
68 else:
70 figs = []
69 figs = []
71 for num in fig_nums:
70 for num in fig_nums:
72 f = Gcf.figs.get(num)
71 f = Gcf.figs.get(num)
73 if f is None:
72 if f is None:
74 print('Warning: figure %s not available.' % num)
73 print('Warning: figure %s not available.' % num)
75 else:
74 else:
76 figs.append(f.canvas.figure)
75 figs.append(f.canvas.figure)
77 return figs
76 return figs
78
77
79
78
80 def figsize(sizex, sizey):
79 def figsize(sizex, sizey):
81 """Set the default figure size to be [sizex, sizey].
80 """Set the default figure size to be [sizex, sizey].
82
81
83 This is just an easy to remember, convenience wrapper that sets::
82 This is just an easy to remember, convenience wrapper that sets::
84
83
85 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
84 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
86 """
85 """
87 import matplotlib
86 import matplotlib
88 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
87 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
89
88
90
89
91 def print_figure(fig, fmt='png', bbox_inches='tight', **kwargs):
90 def print_figure(fig, fmt='png', bbox_inches='tight', **kwargs):
92 """Print a figure to an image, and return the resulting file data
91 """Print a figure to an image, and return the resulting file data
93
92
94 Returned data will be bytes unless ``fmt='svg'``,
93 Returned data will be bytes unless ``fmt='svg'``,
95 in which case it will be unicode.
94 in which case it will be unicode.
96
95
97 Any keyword args are passed to fig.canvas.print_figure,
96 Any keyword args are passed to fig.canvas.print_figure,
98 such as ``quality`` or ``bbox_inches``.
97 such as ``quality`` or ``bbox_inches``.
99 """
98 """
100 from matplotlib import rcParams
101 # When there's an empty figure, we shouldn't return anything, otherwise we
99 # When there's an empty figure, we shouldn't return anything, otherwise we
102 # get big blank areas in the qt console.
100 # get big blank areas in the qt console.
103 if not fig.axes and not fig.lines:
101 if not fig.axes and not fig.lines:
104 return
102 return
105
103
106 dpi = fig.dpi
104 dpi = fig.dpi
107 if fmt == 'retina':
105 if fmt == 'retina':
108 dpi = dpi * 2
106 dpi = dpi * 2
109 fmt = 'png'
107 fmt = 'png'
110
108
111 # build keyword args
109 # build keyword args
112 kw = {
110 kw = {
113 "format":fmt,
111 "format":fmt,
114 "facecolor":fig.get_facecolor(),
112 "facecolor":fig.get_facecolor(),
115 "edgecolor":fig.get_edgecolor(),
113 "edgecolor":fig.get_edgecolor(),
116 "dpi":dpi,
114 "dpi":dpi,
117 "bbox_inches":bbox_inches,
115 "bbox_inches":bbox_inches,
118 }
116 }
119 # **kwargs get higher priority
117 # **kwargs get higher priority
120 kw.update(kwargs)
118 kw.update(kwargs)
121
119
122 bytes_io = BytesIO()
120 bytes_io = BytesIO()
123 fig.canvas.print_figure(bytes_io, **kw)
121 fig.canvas.print_figure(bytes_io, **kw)
124 data = bytes_io.getvalue()
122 data = bytes_io.getvalue()
125 if fmt == 'svg':
123 if fmt == 'svg':
126 data = data.decode('utf-8')
124 data = data.decode('utf-8')
127 return data
125 return data
128
126
129 def retina_figure(fig, **kwargs):
127 def retina_figure(fig, **kwargs):
130 """format a figure as a pixel-doubled (retina) PNG"""
128 """format a figure as a pixel-doubled (retina) PNG"""
131 pngdata = print_figure(fig, fmt='retina', **kwargs)
129 pngdata = print_figure(fig, fmt='retina', **kwargs)
132 # Make sure that retina_figure acts just like print_figure and returns
130 # Make sure that retina_figure acts just like print_figure and returns
133 # None when the figure is empty.
131 # None when the figure is empty.
134 if pngdata is None:
132 if pngdata is None:
135 return
133 return
136 w, h = _pngxy(pngdata)
134 w, h = _pngxy(pngdata)
137 metadata = {"width": w//2, "height":h//2}
135 metadata = {"width": w//2, "height":h//2}
138 return pngdata, metadata
136 return pngdata, metadata
139
137
140 # We need a little factory function here to create the closure where
138 # We need a little factory function here to create the closure where
141 # safe_execfile can live.
139 # safe_execfile can live.
142 def mpl_runner(safe_execfile):
140 def mpl_runner(safe_execfile):
143 """Factory to return a matplotlib-enabled runner for %run.
141 """Factory to return a matplotlib-enabled runner for %run.
144
142
145 Parameters
143 Parameters
146 ----------
144 ----------
147 safe_execfile : function
145 safe_execfile : function
148 This must be a function with the same interface as the
146 This must be a function with the same interface as the
149 :meth:`safe_execfile` method of IPython.
147 :meth:`safe_execfile` method of IPython.
150
148
151 Returns
149 Returns
152 -------
150 -------
153 A function suitable for use as the ``runner`` argument of the %run magic
151 A function suitable for use as the ``runner`` argument of the %run magic
154 function.
152 function.
155 """
153 """
156
154
157 def mpl_execfile(fname,*where,**kw):
155 def mpl_execfile(fname,*where,**kw):
158 """matplotlib-aware wrapper around safe_execfile.
156 """matplotlib-aware wrapper around safe_execfile.
159
157
160 Its interface is identical to that of the :func:`execfile` builtin.
158 Its interface is identical to that of the :func:`execfile` builtin.
161
159
162 This is ultimately a call to execfile(), but wrapped in safeties to
160 This is ultimately a call to execfile(), but wrapped in safeties to
163 properly handle interactive rendering."""
161 properly handle interactive rendering."""
164
162
165 import matplotlib
163 import matplotlib
166 import matplotlib.pyplot as plt
164 import matplotlib.pyplot as plt
167
165
168 #print '*** Matplotlib runner ***' # dbg
166 #print '*** Matplotlib runner ***' # dbg
169 # turn off rendering until end of script
167 # turn off rendering until end of script
170 is_interactive = matplotlib.rcParams['interactive']
168 is_interactive = matplotlib.rcParams['interactive']
171 matplotlib.interactive(False)
169 matplotlib.interactive(False)
172 safe_execfile(fname,*where,**kw)
170 safe_execfile(fname,*where,**kw)
173 matplotlib.interactive(is_interactive)
171 matplotlib.interactive(is_interactive)
174 # make rendering call now, if the user tried to do it
172 # make rendering call now, if the user tried to do it
175 if plt.draw_if_interactive.called:
173 if plt.draw_if_interactive.called:
176 plt.draw()
174 plt.draw()
177 plt.draw_if_interactive.called = False
175 plt.draw_if_interactive.called = False
178
176
179 # re-draw everything that is stale
177 # re-draw everything that is stale
180 try:
178 try:
181 da = plt.draw_all
179 da = plt.draw_all
182 except AttributeError:
180 except AttributeError:
183 pass
181 pass
184 else:
182 else:
185 da()
183 da()
186
184
187 return mpl_execfile
185 return mpl_execfile
188
186
189
187
190 def _reshow_nbagg_figure(fig):
188 def _reshow_nbagg_figure(fig):
191 """reshow an nbagg figure"""
189 """reshow an nbagg figure"""
192 try:
190 try:
193 reshow = fig.canvas.manager.reshow
191 reshow = fig.canvas.manager.reshow
194 except AttributeError:
192 except AttributeError:
195 raise NotImplementedError()
193 raise NotImplementedError()
196 else:
194 else:
197 reshow()
195 reshow()
198
196
199
197
200 def select_figure_formats(shell, formats, **kwargs):
198 def select_figure_formats(shell, formats, **kwargs):
201 """Select figure formats for the inline backend.
199 """Select figure formats for the inline backend.
202
200
203 Parameters
201 Parameters
204 ==========
202 ==========
205 shell : InteractiveShell
203 shell : InteractiveShell
206 The main IPython instance.
204 The main IPython instance.
207 formats : str or set
205 formats : str or set
208 One or a set of figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
206 One or a set of figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
209 **kwargs : any
207 **kwargs : any
210 Extra keyword arguments to be passed to fig.canvas.print_figure.
208 Extra keyword arguments to be passed to fig.canvas.print_figure.
211 """
209 """
212 import matplotlib
210 import matplotlib
213 from matplotlib.figure import Figure
211 from matplotlib.figure import Figure
214
212
215 svg_formatter = shell.display_formatter.formatters['image/svg+xml']
213 svg_formatter = shell.display_formatter.formatters['image/svg+xml']
216 png_formatter = shell.display_formatter.formatters['image/png']
214 png_formatter = shell.display_formatter.formatters['image/png']
217 jpg_formatter = shell.display_formatter.formatters['image/jpeg']
215 jpg_formatter = shell.display_formatter.formatters['image/jpeg']
218 pdf_formatter = shell.display_formatter.formatters['application/pdf']
216 pdf_formatter = shell.display_formatter.formatters['application/pdf']
219
217
220 if isinstance(formats, str):
218 if isinstance(formats, str):
221 formats = {formats}
219 formats = {formats}
222 # cast in case of list / tuple
220 # cast in case of list / tuple
223 formats = set(formats)
221 formats = set(formats)
224
222
225 [ f.pop(Figure, None) for f in shell.display_formatter.formatters.values() ]
223 [ f.pop(Figure, None) for f in shell.display_formatter.formatters.values() ]
226 mplbackend = matplotlib.get_backend().lower()
224 mplbackend = matplotlib.get_backend().lower()
227 if mplbackend == 'nbagg' or mplbackend == 'module://ipympl.backend_nbagg':
225 if mplbackend == 'nbagg' or mplbackend == 'module://ipympl.backend_nbagg':
228 formatter = shell.display_formatter.ipython_display_formatter
226 formatter = shell.display_formatter.ipython_display_formatter
229 formatter.for_type(Figure, _reshow_nbagg_figure)
227 formatter.for_type(Figure, _reshow_nbagg_figure)
230
228
231 supported = {'png', 'png2x', 'retina', 'jpg', 'jpeg', 'svg', 'pdf'}
229 supported = {'png', 'png2x', 'retina', 'jpg', 'jpeg', 'svg', 'pdf'}
232 bad = formats.difference(supported)
230 bad = formats.difference(supported)
233 if bad:
231 if bad:
234 bs = "%s" % ','.join([repr(f) for f in bad])
232 bs = "%s" % ','.join([repr(f) for f in bad])
235 gs = "%s" % ','.join([repr(f) for f in supported])
233 gs = "%s" % ','.join([repr(f) for f in supported])
236 raise ValueError("supported formats are: %s not %s" % (gs, bs))
234 raise ValueError("supported formats are: %s not %s" % (gs, bs))
237
235
238 if 'png' in formats:
236 if 'png' in formats:
239 png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png', **kwargs))
237 png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png', **kwargs))
240 if 'retina' in formats or 'png2x' in formats:
238 if 'retina' in formats or 'png2x' in formats:
241 png_formatter.for_type(Figure, lambda fig: retina_figure(fig, **kwargs))
239 png_formatter.for_type(Figure, lambda fig: retina_figure(fig, **kwargs))
242 if 'jpg' in formats or 'jpeg' in formats:
240 if 'jpg' in formats or 'jpeg' in formats:
243 jpg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'jpg', **kwargs))
241 jpg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'jpg', **kwargs))
244 if 'svg' in formats:
242 if 'svg' in formats:
245 svg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'svg', **kwargs))
243 svg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'svg', **kwargs))
246 if 'pdf' in formats:
244 if 'pdf' in formats:
247 pdf_formatter.for_type(Figure, lambda fig: print_figure(fig, 'pdf', **kwargs))
245 pdf_formatter.for_type(Figure, lambda fig: print_figure(fig, 'pdf', **kwargs))
248
246
249 #-----------------------------------------------------------------------------
247 #-----------------------------------------------------------------------------
250 # Code for initializing matplotlib and importing pylab
248 # Code for initializing matplotlib and importing pylab
251 #-----------------------------------------------------------------------------
249 #-----------------------------------------------------------------------------
252
250
253
251
254 def find_gui_and_backend(gui=None, gui_select=None):
252 def find_gui_and_backend(gui=None, gui_select=None):
255 """Given a gui string return the gui and mpl backend.
253 """Given a gui string return the gui and mpl backend.
256
254
257 Parameters
255 Parameters
258 ----------
256 ----------
259 gui : str
257 gui : str
260 Can be one of ('tk','gtk','wx','qt','qt4','inline','agg').
258 Can be one of ('tk','gtk','wx','qt','qt4','inline','agg').
261 gui_select : str
259 gui_select : str
262 Can be one of ('tk','gtk','wx','qt','qt4','inline').
260 Can be one of ('tk','gtk','wx','qt','qt4','inline').
263 This is any gui already selected by the shell.
261 This is any gui already selected by the shell.
264
262
265 Returns
263 Returns
266 -------
264 -------
267 A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg',
265 A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg',
268 'WXAgg','Qt4Agg','module://ipykernel.pylab.backend_inline','agg').
266 'WXAgg','Qt4Agg','module://ipykernel.pylab.backend_inline','agg').
269 """
267 """
270
268
271 import matplotlib
269 import matplotlib
272
270
273 if gui and gui != 'auto':
271 if gui and gui != 'auto':
274 # select backend based on requested gui
272 # select backend based on requested gui
275 backend = backends[gui]
273 backend = backends[gui]
276 if gui == 'agg':
274 if gui == 'agg':
277 gui = None
275 gui = None
278 else:
276 else:
279 # We need to read the backend from the original data structure, *not*
277 # We need to read the backend from the original data structure, *not*
280 # from mpl.rcParams, since a prior invocation of %matplotlib may have
278 # from mpl.rcParams, since a prior invocation of %matplotlib may have
281 # overwritten that.
279 # overwritten that.
282 # WARNING: this assumes matplotlib 1.1 or newer!!
280 # WARNING: this assumes matplotlib 1.1 or newer!!
283 backend = matplotlib.rcParamsOrig['backend']
281 backend = matplotlib.rcParamsOrig['backend']
284 # In this case, we need to find what the appropriate gui selection call
282 # In this case, we need to find what the appropriate gui selection call
285 # should be for IPython, so we can activate inputhook accordingly
283 # should be for IPython, so we can activate inputhook accordingly
286 gui = backend2gui.get(backend, None)
284 gui = backend2gui.get(backend, None)
287
285
288 # If we have already had a gui active, we need it and inline are the
286 # If we have already had a gui active, we need it and inline are the
289 # ones allowed.
287 # ones allowed.
290 if gui_select and gui != gui_select:
288 if gui_select and gui != gui_select:
291 gui = gui_select
289 gui = gui_select
292 backend = backends[gui]
290 backend = backends[gui]
293
291
294 return gui, backend
292 return gui, backend
295
293
296
294
297 def activate_matplotlib(backend):
295 def activate_matplotlib(backend):
298 """Activate the given backend and set interactive to True."""
296 """Activate the given backend and set interactive to True."""
299
297
300 import matplotlib
298 import matplotlib
301 matplotlib.interactive(True)
299 matplotlib.interactive(True)
302
300
303 # Matplotlib had a bug where even switch_backend could not force
301 # Matplotlib had a bug where even switch_backend could not force
304 # the rcParam to update. This needs to be set *before* the module
302 # the rcParam to update. This needs to be set *before* the module
305 # magic of switch_backend().
303 # magic of switch_backend().
306 matplotlib.rcParams['backend'] = backend
304 matplotlib.rcParams['backend'] = backend
307
305
308 import matplotlib.pyplot
306 import matplotlib.pyplot
309 matplotlib.pyplot.switch_backend(backend)
307 matplotlib.pyplot.switch_backend(backend)
310
308
311 # This must be imported last in the matplotlib series, after
309 # This must be imported last in the matplotlib series, after
312 # backend/interactivity choices have been made
310 # backend/interactivity choices have been made
313 import matplotlib.pyplot as plt
311 import matplotlib.pyplot as plt
314
312
315 plt.show._needmain = False
313 plt.show._needmain = False
316 # We need to detect at runtime whether show() is called by the user.
314 # We need to detect at runtime whether show() is called by the user.
317 # For this, we wrap it into a decorator which adds a 'called' flag.
315 # For this, we wrap it into a decorator which adds a 'called' flag.
318 plt.draw_if_interactive = flag_calls(plt.draw_if_interactive)
316 plt.draw_if_interactive = flag_calls(plt.draw_if_interactive)
319
317
320
318
321 def import_pylab(user_ns, import_all=True):
319 def import_pylab(user_ns, import_all=True):
322 """Populate the namespace with pylab-related values.
320 """Populate the namespace with pylab-related values.
323
321
324 Imports matplotlib, pylab, numpy, and everything from pylab and numpy.
322 Imports matplotlib, pylab, numpy, and everything from pylab and numpy.
325
323
326 Also imports a few names from IPython (figsize, display, getfigs)
324 Also imports a few names from IPython (figsize, display, getfigs)
327
325
328 """
326 """
329
327
330 # Import numpy as np/pyplot as plt are conventions we're trying to
328 # Import numpy as np/pyplot as plt are conventions we're trying to
331 # somewhat standardize on. Making them available to users by default
329 # somewhat standardize on. Making them available to users by default
332 # will greatly help this.
330 # will greatly help this.
333 s = ("import numpy\n"
331 s = ("import numpy\n"
334 "import matplotlib\n"
332 "import matplotlib\n"
335 "from matplotlib import pylab, mlab, pyplot\n"
333 "from matplotlib import pylab, mlab, pyplot\n"
336 "np = numpy\n"
334 "np = numpy\n"
337 "plt = pyplot\n"
335 "plt = pyplot\n"
338 )
336 )
339 exec(s, user_ns)
337 exec(s, user_ns)
340
338
341 if import_all:
339 if import_all:
342 s = ("from matplotlib.pylab import *\n"
340 s = ("from matplotlib.pylab import *\n"
343 "from numpy import *\n")
341 "from numpy import *\n")
344 exec(s, user_ns)
342 exec(s, user_ns)
345
343
346 # IPython symbols to add
344 # IPython symbols to add
347 user_ns['figsize'] = figsize
345 user_ns['figsize'] = figsize
348 from IPython.core.display import display
346 from IPython.core.display import display
349 # Add display and getfigs to the user's namespace
347 # Add display and getfigs to the user's namespace
350 user_ns['display'] = display
348 user_ns['display'] = display
351 user_ns['getfigs'] = getfigs
349 user_ns['getfigs'] = getfigs
352
350
353
351
354 def configure_inline_support(shell, backend):
352 def configure_inline_support(shell, backend):
355 """Configure an IPython shell object for matplotlib use.
353 """Configure an IPython shell object for matplotlib use.
356
354
357 Parameters
355 Parameters
358 ----------
356 ----------
359 shell : InteractiveShell instance
357 shell : InteractiveShell instance
360
358
361 backend : matplotlib backend
359 backend : matplotlib backend
362 """
360 """
363 # If using our svg payload backend, register the post-execution
361 # If using our svg payload backend, register the post-execution
364 # function that will pick up the results for display. This can only be
362 # function that will pick up the results for display. This can only be
365 # done with access to the real shell object.
363 # done with access to the real shell object.
366
364
367 # Note: if we can't load the inline backend, then there's no point
365 # Note: if we can't load the inline backend, then there's no point
368 # continuing (such as in terminal-only shells in environments without
366 # continuing (such as in terminal-only shells in environments without
369 # zeromq available).
367 # zeromq available).
370 try:
368 try:
371 from ipykernel.pylab.backend_inline import InlineBackend
369 from ipykernel.pylab.backend_inline import InlineBackend
372 except ImportError:
370 except ImportError:
373 return
371 return
374 import matplotlib
372 import matplotlib
375
373
376 cfg = InlineBackend.instance(parent=shell)
374 cfg = InlineBackend.instance(parent=shell)
377 cfg.shell = shell
375 cfg.shell = shell
378 if cfg not in shell.configurables:
376 if cfg not in shell.configurables:
379 shell.configurables.append(cfg)
377 shell.configurables.append(cfg)
380
378
381 if backend == backends['inline']:
379 if backend == backends['inline']:
382 from ipykernel.pylab.backend_inline import flush_figures
380 from ipykernel.pylab.backend_inline import flush_figures
383 shell.events.register('post_execute', flush_figures)
381 shell.events.register('post_execute', flush_figures)
384
382
385 # Save rcParams that will be overwrittern
383 # Save rcParams that will be overwrittern
386 shell._saved_rcParams = {}
384 shell._saved_rcParams = {}
387 for k in cfg.rc:
385 for k in cfg.rc:
388 shell._saved_rcParams[k] = matplotlib.rcParams[k]
386 shell._saved_rcParams[k] = matplotlib.rcParams[k]
389 # load inline_rc
387 # load inline_rc
390 matplotlib.rcParams.update(cfg.rc)
388 matplotlib.rcParams.update(cfg.rc)
391 new_backend_name = "inline"
389 new_backend_name = "inline"
392 else:
390 else:
393 from ipykernel.pylab.backend_inline import flush_figures
391 from ipykernel.pylab.backend_inline import flush_figures
394 try:
392 try:
395 shell.events.unregister('post_execute', flush_figures)
393 shell.events.unregister('post_execute', flush_figures)
396 except ValueError:
394 except ValueError:
397 pass
395 pass
398 if hasattr(shell, '_saved_rcParams'):
396 if hasattr(shell, '_saved_rcParams'):
399 matplotlib.rcParams.update(shell._saved_rcParams)
397 matplotlib.rcParams.update(shell._saved_rcParams)
400 del shell._saved_rcParams
398 del shell._saved_rcParams
401 new_backend_name = "other"
399 new_backend_name = "other"
402
400
403 # only enable the formats once -> don't change the enabled formats (which the user may
401 # only enable the formats once -> don't change the enabled formats (which the user may
404 # has changed) when getting another "%matplotlib inline" call.
402 # has changed) when getting another "%matplotlib inline" call.
405 # See https://github.com/ipython/ipykernel/issues/29
403 # See https://github.com/ipython/ipykernel/issues/29
406 cur_backend = getattr(configure_inline_support, "current_backend", "unset")
404 cur_backend = getattr(configure_inline_support, "current_backend", "unset")
407 if new_backend_name != cur_backend:
405 if new_backend_name != cur_backend:
408 # Setup the default figure format
406 # Setup the default figure format
409 select_figure_formats(shell, cfg.figure_formats, **cfg.print_figure_kwargs)
407 select_figure_formats(shell, cfg.figure_formats, **cfg.print_figure_kwargs)
410 configure_inline_support.current_backend = new_backend_name
408 configure_inline_support.current_backend = new_backend_name
@@ -1,405 +1,404 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 A mixin for :class:`~IPython.core.application.Application` classes that
3 A mixin for :class:`~IPython.core.application.Application` classes that
4 launch InteractiveShell instances, load extensions, etc.
4 launch InteractiveShell instances, load extensions, etc.
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 glob
10 import glob
11 import os
11 import os
12 import sys
12 import sys
13
13
14 from traitlets.config.application import boolean_flag
14 from traitlets.config.application import boolean_flag
15 from traitlets.config.configurable import Configurable
15 from traitlets.config.configurable import Configurable
16 from traitlets.config.loader import Config
16 from traitlets.config.loader import Config
17 from IPython.core import pylabtools
17 from IPython.core import pylabtools
18 from IPython.utils import py3compat
19 from IPython.utils.contexts import preserve_keys
18 from IPython.utils.contexts import preserve_keys
20 from IPython.utils.path import filefind
19 from IPython.utils.path import filefind
21 from traitlets import (
20 from traitlets import (
22 Unicode, Instance, List, Bool, CaselessStrEnum, observe,
21 Unicode, Instance, List, Bool, CaselessStrEnum, observe,
23 )
22 )
24 from IPython.terminal import pt_inputhooks
23 from IPython.terminal import pt_inputhooks
25
24
26 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
27 # Aliases and Flags
26 # Aliases and Flags
28 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
29
28
30 gui_keys = tuple(sorted(pt_inputhooks.backends) + sorted(pt_inputhooks.aliases))
29 gui_keys = tuple(sorted(pt_inputhooks.backends) + sorted(pt_inputhooks.aliases))
31
30
32 backend_keys = sorted(pylabtools.backends.keys())
31 backend_keys = sorted(pylabtools.backends.keys())
33 backend_keys.insert(0, 'auto')
32 backend_keys.insert(0, 'auto')
34
33
35 shell_flags = {}
34 shell_flags = {}
36
35
37 addflag = lambda *args: shell_flags.update(boolean_flag(*args))
36 addflag = lambda *args: shell_flags.update(boolean_flag(*args))
38 addflag('autoindent', 'InteractiveShell.autoindent',
37 addflag('autoindent', 'InteractiveShell.autoindent',
39 'Turn on autoindenting.', 'Turn off autoindenting.'
38 'Turn on autoindenting.', 'Turn off autoindenting.'
40 )
39 )
41 addflag('automagic', 'InteractiveShell.automagic',
40 addflag('automagic', 'InteractiveShell.automagic',
42 """Turn on the auto calling of magic commands. Type %%magic at the
41 """Turn on the auto calling of magic commands. Type %%magic at the
43 IPython prompt for more information.""",
42 IPython prompt for more information.""",
44 'Turn off the auto calling of magic commands.'
43 'Turn off the auto calling of magic commands.'
45 )
44 )
46 addflag('pdb', 'InteractiveShell.pdb',
45 addflag('pdb', 'InteractiveShell.pdb',
47 "Enable auto calling the pdb debugger after every exception.",
46 "Enable auto calling the pdb debugger after every exception.",
48 "Disable auto calling the pdb debugger after every exception."
47 "Disable auto calling the pdb debugger after every exception."
49 )
48 )
50 addflag('pprint', 'PlainTextFormatter.pprint',
49 addflag('pprint', 'PlainTextFormatter.pprint',
51 "Enable auto pretty printing of results.",
50 "Enable auto pretty printing of results.",
52 "Disable auto pretty printing of results."
51 "Disable auto pretty printing of results."
53 )
52 )
54 addflag('color-info', 'InteractiveShell.color_info',
53 addflag('color-info', 'InteractiveShell.color_info',
55 """IPython can display information about objects via a set of functions,
54 """IPython can display information about objects via a set of functions,
56 and optionally can use colors for this, syntax highlighting
55 and optionally can use colors for this, syntax highlighting
57 source code and various other elements. This is on by default, but can cause
56 source code and various other elements. This is on by default, but can cause
58 problems with some pagers. If you see such problems, you can disable the
57 problems with some pagers. If you see such problems, you can disable the
59 colours.""",
58 colours.""",
60 "Disable using colors for info related things."
59 "Disable using colors for info related things."
61 )
60 )
62 nosep_config = Config()
61 nosep_config = Config()
63 nosep_config.InteractiveShell.separate_in = ''
62 nosep_config.InteractiveShell.separate_in = ''
64 nosep_config.InteractiveShell.separate_out = ''
63 nosep_config.InteractiveShell.separate_out = ''
65 nosep_config.InteractiveShell.separate_out2 = ''
64 nosep_config.InteractiveShell.separate_out2 = ''
66
65
67 shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
66 shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
68 shell_flags['pylab'] = (
67 shell_flags['pylab'] = (
69 {'InteractiveShellApp' : {'pylab' : 'auto'}},
68 {'InteractiveShellApp' : {'pylab' : 'auto'}},
70 """Pre-load matplotlib and numpy for interactive use with
69 """Pre-load matplotlib and numpy for interactive use with
71 the default matplotlib backend."""
70 the default matplotlib backend."""
72 )
71 )
73 shell_flags['matplotlib'] = (
72 shell_flags['matplotlib'] = (
74 {'InteractiveShellApp' : {'matplotlib' : 'auto'}},
73 {'InteractiveShellApp' : {'matplotlib' : 'auto'}},
75 """Configure matplotlib for interactive use with
74 """Configure matplotlib for interactive use with
76 the default matplotlib backend."""
75 the default matplotlib backend."""
77 )
76 )
78
77
79 # it's possible we don't want short aliases for *all* of these:
78 # it's possible we don't want short aliases for *all* of these:
80 shell_aliases = dict(
79 shell_aliases = dict(
81 autocall='InteractiveShell.autocall',
80 autocall='InteractiveShell.autocall',
82 colors='InteractiveShell.colors',
81 colors='InteractiveShell.colors',
83 logfile='InteractiveShell.logfile',
82 logfile='InteractiveShell.logfile',
84 logappend='InteractiveShell.logappend',
83 logappend='InteractiveShell.logappend',
85 c='InteractiveShellApp.code_to_run',
84 c='InteractiveShellApp.code_to_run',
86 m='InteractiveShellApp.module_to_run',
85 m='InteractiveShellApp.module_to_run',
87 ext='InteractiveShellApp.extra_extension',
86 ext='InteractiveShellApp.extra_extension',
88 gui='InteractiveShellApp.gui',
87 gui='InteractiveShellApp.gui',
89 pylab='InteractiveShellApp.pylab',
88 pylab='InteractiveShellApp.pylab',
90 matplotlib='InteractiveShellApp.matplotlib',
89 matplotlib='InteractiveShellApp.matplotlib',
91 )
90 )
92 shell_aliases['cache-size'] = 'InteractiveShell.cache_size'
91 shell_aliases['cache-size'] = 'InteractiveShell.cache_size'
93
92
94 #-----------------------------------------------------------------------------
93 #-----------------------------------------------------------------------------
95 # Main classes and functions
94 # Main classes and functions
96 #-----------------------------------------------------------------------------
95 #-----------------------------------------------------------------------------
97
96
98 class InteractiveShellApp(Configurable):
97 class InteractiveShellApp(Configurable):
99 """A Mixin for applications that start InteractiveShell instances.
98 """A Mixin for applications that start InteractiveShell instances.
100
99
101 Provides configurables for loading extensions and executing files
100 Provides configurables for loading extensions and executing files
102 as part of configuring a Shell environment.
101 as part of configuring a Shell environment.
103
102
104 The following methods should be called by the :meth:`initialize` method
103 The following methods should be called by the :meth:`initialize` method
105 of the subclass:
104 of the subclass:
106
105
107 - :meth:`init_path`
106 - :meth:`init_path`
108 - :meth:`init_shell` (to be implemented by the subclass)
107 - :meth:`init_shell` (to be implemented by the subclass)
109 - :meth:`init_gui_pylab`
108 - :meth:`init_gui_pylab`
110 - :meth:`init_extensions`
109 - :meth:`init_extensions`
111 - :meth:`init_code`
110 - :meth:`init_code`
112 """
111 """
113 extensions = List(Unicode(),
112 extensions = List(Unicode(),
114 help="A list of dotted module names of IPython extensions to load."
113 help="A list of dotted module names of IPython extensions to load."
115 ).tag(config=True)
114 ).tag(config=True)
116 extra_extension = Unicode('',
115 extra_extension = Unicode('',
117 help="dotted module name of an IPython extension to load."
116 help="dotted module name of an IPython extension to load."
118 ).tag(config=True)
117 ).tag(config=True)
119
118
120 reraise_ipython_extension_failures = Bool(False,
119 reraise_ipython_extension_failures = Bool(False,
121 help="Reraise exceptions encountered loading IPython extensions?",
120 help="Reraise exceptions encountered loading IPython extensions?",
122 ).tag(config=True)
121 ).tag(config=True)
123
122
124 # Extensions that are always loaded (not configurable)
123 # Extensions that are always loaded (not configurable)
125 default_extensions = List(Unicode(), [u'storemagic']).tag(config=False)
124 default_extensions = List(Unicode(), [u'storemagic']).tag(config=False)
126
125
127 hide_initial_ns = Bool(True,
126 hide_initial_ns = Bool(True,
128 help="""Should variables loaded at startup (by startup files, exec_lines, etc.)
127 help="""Should variables loaded at startup (by startup files, exec_lines, etc.)
129 be hidden from tools like %who?"""
128 be hidden from tools like %who?"""
130 ).tag(config=True)
129 ).tag(config=True)
131
130
132 exec_files = List(Unicode(),
131 exec_files = List(Unicode(),
133 help="""List of files to run at IPython startup."""
132 help="""List of files to run at IPython startup."""
134 ).tag(config=True)
133 ).tag(config=True)
135 exec_PYTHONSTARTUP = Bool(True,
134 exec_PYTHONSTARTUP = Bool(True,
136 help="""Run the file referenced by the PYTHONSTARTUP environment
135 help="""Run the file referenced by the PYTHONSTARTUP environment
137 variable at IPython startup."""
136 variable at IPython startup."""
138 ).tag(config=True)
137 ).tag(config=True)
139 file_to_run = Unicode('',
138 file_to_run = Unicode('',
140 help="""A file to be run""").tag(config=True)
139 help="""A file to be run""").tag(config=True)
141
140
142 exec_lines = List(Unicode(),
141 exec_lines = List(Unicode(),
143 help="""lines of code to run at IPython startup."""
142 help="""lines of code to run at IPython startup."""
144 ).tag(config=True)
143 ).tag(config=True)
145 code_to_run = Unicode('',
144 code_to_run = Unicode('',
146 help="Execute the given command string."
145 help="Execute the given command string."
147 ).tag(config=True)
146 ).tag(config=True)
148 module_to_run = Unicode('',
147 module_to_run = Unicode('',
149 help="Run the module as a script."
148 help="Run the module as a script."
150 ).tag(config=True)
149 ).tag(config=True)
151 gui = CaselessStrEnum(gui_keys, allow_none=True,
150 gui = CaselessStrEnum(gui_keys, allow_none=True,
152 help="Enable GUI event loop integration with any of {0}.".format(gui_keys)
151 help="Enable GUI event loop integration with any of {0}.".format(gui_keys)
153 ).tag(config=True)
152 ).tag(config=True)
154 matplotlib = CaselessStrEnum(backend_keys, allow_none=True,
153 matplotlib = CaselessStrEnum(backend_keys, allow_none=True,
155 help="""Configure matplotlib for interactive use with
154 help="""Configure matplotlib for interactive use with
156 the default matplotlib backend."""
155 the default matplotlib backend."""
157 ).tag(config=True)
156 ).tag(config=True)
158 pylab = CaselessStrEnum(backend_keys, allow_none=True,
157 pylab = CaselessStrEnum(backend_keys, allow_none=True,
159 help="""Pre-load matplotlib and numpy for interactive use,
158 help="""Pre-load matplotlib and numpy for interactive use,
160 selecting a particular matplotlib backend and loop integration.
159 selecting a particular matplotlib backend and loop integration.
161 """
160 """
162 ).tag(config=True)
161 ).tag(config=True)
163 pylab_import_all = Bool(True,
162 pylab_import_all = Bool(True,
164 help="""If true, IPython will populate the user namespace with numpy, pylab, etc.
163 help="""If true, IPython will populate the user namespace with numpy, pylab, etc.
165 and an ``import *`` is done from numpy and pylab, when using pylab mode.
164 and an ``import *`` is done from numpy and pylab, when using pylab mode.
166
165
167 When False, pylab mode should not import any names into the user namespace.
166 When False, pylab mode should not import any names into the user namespace.
168 """
167 """
169 ).tag(config=True)
168 ).tag(config=True)
170 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
169 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
171 allow_none=True)
170 allow_none=True)
172 # whether interact-loop should start
171 # whether interact-loop should start
173 interact = Bool(True)
172 interact = Bool(True)
174
173
175 user_ns = Instance(dict, args=None, allow_none=True)
174 user_ns = Instance(dict, args=None, allow_none=True)
176 @observe('user_ns')
175 @observe('user_ns')
177 def _user_ns_changed(self, change):
176 def _user_ns_changed(self, change):
178 if self.shell is not None:
177 if self.shell is not None:
179 self.shell.user_ns = change['new']
178 self.shell.user_ns = change['new']
180 self.shell.init_user_ns()
179 self.shell.init_user_ns()
181
180
182 def init_path(self):
181 def init_path(self):
183 """Add current working directory, '', to sys.path"""
182 """Add current working directory, '', to sys.path"""
184 if sys.path[0] != '':
183 if sys.path[0] != '':
185 sys.path.insert(0, '')
184 sys.path.insert(0, '')
186
185
187 def init_shell(self):
186 def init_shell(self):
188 raise NotImplementedError("Override in subclasses")
187 raise NotImplementedError("Override in subclasses")
189
188
190 def init_gui_pylab(self):
189 def init_gui_pylab(self):
191 """Enable GUI event loop integration, taking pylab into account."""
190 """Enable GUI event loop integration, taking pylab into account."""
192 enable = False
191 enable = False
193 shell = self.shell
192 shell = self.shell
194 if self.pylab:
193 if self.pylab:
195 enable = lambda key: shell.enable_pylab(key, import_all=self.pylab_import_all)
194 enable = lambda key: shell.enable_pylab(key, import_all=self.pylab_import_all)
196 key = self.pylab
195 key = self.pylab
197 elif self.matplotlib:
196 elif self.matplotlib:
198 enable = shell.enable_matplotlib
197 enable = shell.enable_matplotlib
199 key = self.matplotlib
198 key = self.matplotlib
200 elif self.gui:
199 elif self.gui:
201 enable = shell.enable_gui
200 enable = shell.enable_gui
202 key = self.gui
201 key = self.gui
203
202
204 if not enable:
203 if not enable:
205 return
204 return
206
205
207 try:
206 try:
208 r = enable(key)
207 r = enable(key)
209 except ImportError:
208 except ImportError:
210 self.log.warning("Eventloop or matplotlib integration failed. Is matplotlib installed?")
209 self.log.warning("Eventloop or matplotlib integration failed. Is matplotlib installed?")
211 self.shell.showtraceback()
210 self.shell.showtraceback()
212 return
211 return
213 except Exception:
212 except Exception:
214 self.log.warning("GUI event loop or pylab initialization failed")
213 self.log.warning("GUI event loop or pylab initialization failed")
215 self.shell.showtraceback()
214 self.shell.showtraceback()
216 return
215 return
217
216
218 if isinstance(r, tuple):
217 if isinstance(r, tuple):
219 gui, backend = r[:2]
218 gui, backend = r[:2]
220 self.log.info("Enabling GUI event loop integration, "
219 self.log.info("Enabling GUI event loop integration, "
221 "eventloop=%s, matplotlib=%s", gui, backend)
220 "eventloop=%s, matplotlib=%s", gui, backend)
222 if key == "auto":
221 if key == "auto":
223 print("Using matplotlib backend: %s" % backend)
222 print("Using matplotlib backend: %s" % backend)
224 else:
223 else:
225 gui = r
224 gui = r
226 self.log.info("Enabling GUI event loop integration, "
225 self.log.info("Enabling GUI event loop integration, "
227 "eventloop=%s", gui)
226 "eventloop=%s", gui)
228
227
229 def init_extensions(self):
228 def init_extensions(self):
230 """Load all IPython extensions in IPythonApp.extensions.
229 """Load all IPython extensions in IPythonApp.extensions.
231
230
232 This uses the :meth:`ExtensionManager.load_extensions` to load all
231 This uses the :meth:`ExtensionManager.load_extensions` to load all
233 the extensions listed in ``self.extensions``.
232 the extensions listed in ``self.extensions``.
234 """
233 """
235 try:
234 try:
236 self.log.debug("Loading IPython extensions...")
235 self.log.debug("Loading IPython extensions...")
237 extensions = self.default_extensions + self.extensions
236 extensions = self.default_extensions + self.extensions
238 if self.extra_extension:
237 if self.extra_extension:
239 extensions.append(self.extra_extension)
238 extensions.append(self.extra_extension)
240 for ext in extensions:
239 for ext in extensions:
241 try:
240 try:
242 self.log.info("Loading IPython extension: %s" % ext)
241 self.log.info("Loading IPython extension: %s" % ext)
243 self.shell.extension_manager.load_extension(ext)
242 self.shell.extension_manager.load_extension(ext)
244 except:
243 except:
245 if self.reraise_ipython_extension_failures:
244 if self.reraise_ipython_extension_failures:
246 raise
245 raise
247 msg = ("Error in loading extension: {ext}\n"
246 msg = ("Error in loading extension: {ext}\n"
248 "Check your config files in {location}".format(
247 "Check your config files in {location}".format(
249 ext=ext,
248 ext=ext,
250 location=self.profile_dir.location
249 location=self.profile_dir.location
251 ))
250 ))
252 self.log.warning(msg, exc_info=True)
251 self.log.warning(msg, exc_info=True)
253 except:
252 except:
254 if self.reraise_ipython_extension_failures:
253 if self.reraise_ipython_extension_failures:
255 raise
254 raise
256 self.log.warning("Unknown error in loading extensions:", exc_info=True)
255 self.log.warning("Unknown error in loading extensions:", exc_info=True)
257
256
258 def init_code(self):
257 def init_code(self):
259 """run the pre-flight code, specified via exec_lines"""
258 """run the pre-flight code, specified via exec_lines"""
260 self._run_startup_files()
259 self._run_startup_files()
261 self._run_exec_lines()
260 self._run_exec_lines()
262 self._run_exec_files()
261 self._run_exec_files()
263
262
264 # Hide variables defined here from %who etc.
263 # Hide variables defined here from %who etc.
265 if self.hide_initial_ns:
264 if self.hide_initial_ns:
266 self.shell.user_ns_hidden.update(self.shell.user_ns)
265 self.shell.user_ns_hidden.update(self.shell.user_ns)
267
266
268 # command-line execution (ipython -i script.py, ipython -m module)
267 # command-line execution (ipython -i script.py, ipython -m module)
269 # should *not* be excluded from %whos
268 # should *not* be excluded from %whos
270 self._run_cmd_line_code()
269 self._run_cmd_line_code()
271 self._run_module()
270 self._run_module()
272
271
273 # flush output, so itwon't be attached to the first cell
272 # flush output, so itwon't be attached to the first cell
274 sys.stdout.flush()
273 sys.stdout.flush()
275 sys.stderr.flush()
274 sys.stderr.flush()
276
275
277 def _run_exec_lines(self):
276 def _run_exec_lines(self):
278 """Run lines of code in IPythonApp.exec_lines in the user's namespace."""
277 """Run lines of code in IPythonApp.exec_lines in the user's namespace."""
279 if not self.exec_lines:
278 if not self.exec_lines:
280 return
279 return
281 try:
280 try:
282 self.log.debug("Running code from IPythonApp.exec_lines...")
281 self.log.debug("Running code from IPythonApp.exec_lines...")
283 for line in self.exec_lines:
282 for line in self.exec_lines:
284 try:
283 try:
285 self.log.info("Running code in user namespace: %s" %
284 self.log.info("Running code in user namespace: %s" %
286 line)
285 line)
287 self.shell.run_cell(line, store_history=False)
286 self.shell.run_cell(line, store_history=False)
288 except:
287 except:
289 self.log.warning("Error in executing line in user "
288 self.log.warning("Error in executing line in user "
290 "namespace: %s" % line)
289 "namespace: %s" % line)
291 self.shell.showtraceback()
290 self.shell.showtraceback()
292 except:
291 except:
293 self.log.warning("Unknown error in handling IPythonApp.exec_lines:")
292 self.log.warning("Unknown error in handling IPythonApp.exec_lines:")
294 self.shell.showtraceback()
293 self.shell.showtraceback()
295
294
296 def _exec_file(self, fname, shell_futures=False):
295 def _exec_file(self, fname, shell_futures=False):
297 try:
296 try:
298 full_filename = filefind(fname, [u'.', self.ipython_dir])
297 full_filename = filefind(fname, [u'.', self.ipython_dir])
299 except IOError:
298 except IOError:
300 self.log.warning("File not found: %r"%fname)
299 self.log.warning("File not found: %r"%fname)
301 return
300 return
302 # Make sure that the running script gets a proper sys.argv as if it
301 # Make sure that the running script gets a proper sys.argv as if it
303 # were run from a system shell.
302 # were run from a system shell.
304 save_argv = sys.argv
303 save_argv = sys.argv
305 sys.argv = [full_filename] + self.extra_args[1:]
304 sys.argv = [full_filename] + self.extra_args[1:]
306 try:
305 try:
307 if os.path.isfile(full_filename):
306 if os.path.isfile(full_filename):
308 self.log.info("Running file in user namespace: %s" %
307 self.log.info("Running file in user namespace: %s" %
309 full_filename)
308 full_filename)
310 # Ensure that __file__ is always defined to match Python
309 # Ensure that __file__ is always defined to match Python
311 # behavior.
310 # behavior.
312 with preserve_keys(self.shell.user_ns, '__file__'):
311 with preserve_keys(self.shell.user_ns, '__file__'):
313 self.shell.user_ns['__file__'] = fname
312 self.shell.user_ns['__file__'] = fname
314 if full_filename.endswith('.ipy'):
313 if full_filename.endswith('.ipy'):
315 self.shell.safe_execfile_ipy(full_filename,
314 self.shell.safe_execfile_ipy(full_filename,
316 shell_futures=shell_futures)
315 shell_futures=shell_futures)
317 else:
316 else:
318 # default to python, even without extension
317 # default to python, even without extension
319 self.shell.safe_execfile(full_filename,
318 self.shell.safe_execfile(full_filename,
320 self.shell.user_ns,
319 self.shell.user_ns,
321 shell_futures=shell_futures,
320 shell_futures=shell_futures,
322 raise_exceptions=True)
321 raise_exceptions=True)
323 finally:
322 finally:
324 sys.argv = save_argv
323 sys.argv = save_argv
325
324
326 def _run_startup_files(self):
325 def _run_startup_files(self):
327 """Run files from profile startup directory"""
326 """Run files from profile startup directory"""
328 startup_dir = self.profile_dir.startup_dir
327 startup_dir = self.profile_dir.startup_dir
329 startup_files = []
328 startup_files = []
330
329
331 if self.exec_PYTHONSTARTUP and os.environ.get('PYTHONSTARTUP', False) and \
330 if self.exec_PYTHONSTARTUP and os.environ.get('PYTHONSTARTUP', False) and \
332 not (self.file_to_run or self.code_to_run or self.module_to_run):
331 not (self.file_to_run or self.code_to_run or self.module_to_run):
333 python_startup = os.environ['PYTHONSTARTUP']
332 python_startup = os.environ['PYTHONSTARTUP']
334 self.log.debug("Running PYTHONSTARTUP file %s...", python_startup)
333 self.log.debug("Running PYTHONSTARTUP file %s...", python_startup)
335 try:
334 try:
336 self._exec_file(python_startup)
335 self._exec_file(python_startup)
337 except:
336 except:
338 self.log.warning("Unknown error in handling PYTHONSTARTUP file %s:", python_startup)
337 self.log.warning("Unknown error in handling PYTHONSTARTUP file %s:", python_startup)
339 self.shell.showtraceback()
338 self.shell.showtraceback()
340
339
341 startup_files += glob.glob(os.path.join(startup_dir, '*.py'))
340 startup_files += glob.glob(os.path.join(startup_dir, '*.py'))
342 startup_files += glob.glob(os.path.join(startup_dir, '*.ipy'))
341 startup_files += glob.glob(os.path.join(startup_dir, '*.ipy'))
343 if not startup_files:
342 if not startup_files:
344 return
343 return
345
344
346 self.log.debug("Running startup files from %s...", startup_dir)
345 self.log.debug("Running startup files from %s...", startup_dir)
347 try:
346 try:
348 for fname in sorted(startup_files):
347 for fname in sorted(startup_files):
349 self._exec_file(fname)
348 self._exec_file(fname)
350 except:
349 except:
351 self.log.warning("Unknown error in handling startup files:")
350 self.log.warning("Unknown error in handling startup files:")
352 self.shell.showtraceback()
351 self.shell.showtraceback()
353
352
354 def _run_exec_files(self):
353 def _run_exec_files(self):
355 """Run files from IPythonApp.exec_files"""
354 """Run files from IPythonApp.exec_files"""
356 if not self.exec_files:
355 if not self.exec_files:
357 return
356 return
358
357
359 self.log.debug("Running files in IPythonApp.exec_files...")
358 self.log.debug("Running files in IPythonApp.exec_files...")
360 try:
359 try:
361 for fname in self.exec_files:
360 for fname in self.exec_files:
362 self._exec_file(fname)
361 self._exec_file(fname)
363 except:
362 except:
364 self.log.warning("Unknown error in handling IPythonApp.exec_files:")
363 self.log.warning("Unknown error in handling IPythonApp.exec_files:")
365 self.shell.showtraceback()
364 self.shell.showtraceback()
366
365
367 def _run_cmd_line_code(self):
366 def _run_cmd_line_code(self):
368 """Run code or file specified at the command-line"""
367 """Run code or file specified at the command-line"""
369 if self.code_to_run:
368 if self.code_to_run:
370 line = self.code_to_run
369 line = self.code_to_run
371 try:
370 try:
372 self.log.info("Running code given at command line (c=): %s" %
371 self.log.info("Running code given at command line (c=): %s" %
373 line)
372 line)
374 self.shell.run_cell(line, store_history=False)
373 self.shell.run_cell(line, store_history=False)
375 except:
374 except:
376 self.log.warning("Error in executing line in user namespace: %s" %
375 self.log.warning("Error in executing line in user namespace: %s" %
377 line)
376 line)
378 self.shell.showtraceback()
377 self.shell.showtraceback()
379 if not self.interact:
378 if not self.interact:
380 self.exit(1)
379 self.exit(1)
381
380
382 # Like Python itself, ignore the second if the first of these is present
381 # Like Python itself, ignore the second if the first of these is present
383 elif self.file_to_run:
382 elif self.file_to_run:
384 fname = self.file_to_run
383 fname = self.file_to_run
385 if os.path.isdir(fname):
384 if os.path.isdir(fname):
386 fname = os.path.join(fname, "__main__.py")
385 fname = os.path.join(fname, "__main__.py")
387 try:
386 try:
388 self._exec_file(fname, shell_futures=True)
387 self._exec_file(fname, shell_futures=True)
389 except:
388 except:
390 self.shell.showtraceback(tb_offset=4)
389 self.shell.showtraceback(tb_offset=4)
391 if not self.interact:
390 if not self.interact:
392 self.exit(1)
391 self.exit(1)
393
392
394 def _run_module(self):
393 def _run_module(self):
395 """Run module specified at the command-line."""
394 """Run module specified at the command-line."""
396 if self.module_to_run:
395 if self.module_to_run:
397 # Make sure that the module gets a proper sys.argv as if it were
396 # Make sure that the module gets a proper sys.argv as if it were
398 # run using `python -m`.
397 # run using `python -m`.
399 save_argv = sys.argv
398 save_argv = sys.argv
400 sys.argv = [sys.executable] + self.extra_args
399 sys.argv = [sys.executable] + self.extra_args
401 try:
400 try:
402 self.shell.safe_run_module(self.module_to_run,
401 self.shell.safe_run_module(self.module_to_run,
403 self.shell.user_ns)
402 self.shell.user_ns)
404 finally:
403 finally:
405 sys.argv = save_argv
404 sys.argv = save_argv
@@ -1,1460 +1,1459 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 unencryted
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 import types
104
103
105 try: # Python 2
104 try: # Python 2
106 generate_tokens = tokenize.generate_tokens
105 generate_tokens = tokenize.generate_tokens
107 except AttributeError: # Python 3
106 except AttributeError: # Python 3
108 generate_tokens = tokenize.tokenize
107 generate_tokens = tokenize.tokenize
109
108
110 # For purposes of monkeypatching inspect to fix a bug in it.
109 # For purposes of monkeypatching inspect to fix a bug in it.
111 from inspect import getsourcefile, getfile, getmodule, \
110 from inspect import getsourcefile, getfile, getmodule, \
112 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
111 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
113
112
114 # IPython's own modules
113 # IPython's own modules
115 from IPython import get_ipython
114 from IPython import get_ipython
116 from IPython.core import debugger
115 from IPython.core import debugger
117 from IPython.core.display_trap import DisplayTrap
116 from IPython.core.display_trap import DisplayTrap
118 from IPython.core.excolors import exception_colors
117 from IPython.core.excolors import exception_colors
119 from IPython.utils import PyColorize
118 from IPython.utils import PyColorize
120 from IPython.utils import openpy
119 from IPython.utils import openpy
121 from IPython.utils import path as util_path
120 from IPython.utils import path as util_path
122 from IPython.utils import py3compat
121 from IPython.utils import py3compat
123 from IPython.utils.data import uniq_stable
122 from IPython.utils.data import uniq_stable
124 from IPython.utils.terminal import get_terminal_size
123 from IPython.utils.terminal import get_terminal_size
125 from logging import info, error
124 from logging import info, error
126
125
127 import IPython.utils.colorable as colorable
126 import IPython.utils.colorable as colorable
128
127
129 # Globals
128 # Globals
130 # amount of space to put line numbers before verbose tracebacks
129 # amount of space to put line numbers before verbose tracebacks
131 INDENT_SIZE = 8
130 INDENT_SIZE = 8
132
131
133 # Default color scheme. This is used, for example, by the traceback
132 # Default color scheme. This is used, for example, by the traceback
134 # formatter. When running in an actual IPython instance, the user's rc.colors
133 # formatter. When running in an actual IPython instance, the user's rc.colors
135 # value is used, but having a module global makes this functionality available
134 # value is used, but having a module global makes this functionality available
136 # to users of ultratb who are NOT running inside ipython.
135 # to users of ultratb who are NOT running inside ipython.
137 DEFAULT_SCHEME = 'NoColor'
136 DEFAULT_SCHEME = 'NoColor'
138
137
139 # ---------------------------------------------------------------------------
138 # ---------------------------------------------------------------------------
140 # Code begins
139 # Code begins
141
140
142 # Utility functions
141 # Utility functions
143 def inspect_error():
142 def inspect_error():
144 """Print a message about internal inspect errors.
143 """Print a message about internal inspect errors.
145
144
146 These are unfortunately quite common."""
145 These are unfortunately quite common."""
147
146
148 error('Internal Python error in the inspect module.\n'
147 error('Internal Python error in the inspect module.\n'
149 'Below is the traceback from this internal error.\n')
148 'Below is the traceback from this internal error.\n')
150
149
151
150
152 # This function is a monkeypatch we apply to the Python inspect module. We have
151 # This function is a monkeypatch we apply to the Python inspect module. We have
153 # now found when it's needed (see discussion on issue gh-1456), and we have a
152 # now found when it's needed (see discussion on issue gh-1456), and we have a
154 # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
153 # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
155 # the monkeypatch is not applied. TK, Aug 2012.
154 # the monkeypatch is not applied. TK, Aug 2012.
156 def findsource(object):
155 def findsource(object):
157 """Return the entire source file and starting line number for an object.
156 """Return the entire source file and starting line number for an object.
158
157
159 The argument may be a module, class, method, function, traceback, frame,
158 The argument may be a module, class, method, function, traceback, frame,
160 or code object. The source code is returned as a list of all the lines
159 or code object. The source code is returned as a list of all the lines
161 in the file and the line number indexes a line in that list. An IOError
160 in the file and the line number indexes a line in that list. An IOError
162 is raised if the source code cannot be retrieved.
161 is raised if the source code cannot be retrieved.
163
162
164 FIXED version with which we monkeypatch the stdlib to work around a bug."""
163 FIXED version with which we monkeypatch the stdlib to work around a bug."""
165
164
166 file = getsourcefile(object) or getfile(object)
165 file = getsourcefile(object) or getfile(object)
167 # If the object is a frame, then trying to get the globals dict from its
166 # If the object is a frame, then trying to get the globals dict from its
168 # module won't work. Instead, the frame object itself has the globals
167 # module won't work. Instead, the frame object itself has the globals
169 # dictionary.
168 # dictionary.
170 globals_dict = None
169 globals_dict = None
171 if inspect.isframe(object):
170 if inspect.isframe(object):
172 # XXX: can this ever be false?
171 # XXX: can this ever be false?
173 globals_dict = object.f_globals
172 globals_dict = object.f_globals
174 else:
173 else:
175 module = getmodule(object, file)
174 module = getmodule(object, file)
176 if module:
175 if module:
177 globals_dict = module.__dict__
176 globals_dict = module.__dict__
178 lines = linecache.getlines(file, globals_dict)
177 lines = linecache.getlines(file, globals_dict)
179 if not lines:
178 if not lines:
180 raise IOError('could not get source code')
179 raise IOError('could not get source code')
181
180
182 if ismodule(object):
181 if ismodule(object):
183 return lines, 0
182 return lines, 0
184
183
185 if isclass(object):
184 if isclass(object):
186 name = object.__name__
185 name = object.__name__
187 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
186 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
188 # make some effort to find the best matching class definition:
187 # make some effort to find the best matching class definition:
189 # use the one with the least indentation, which is the one
188 # use the one with the least indentation, which is the one
190 # that's most probably not inside a function definition.
189 # that's most probably not inside a function definition.
191 candidates = []
190 candidates = []
192 for i, line in enumerate(lines):
191 for i, line in enumerate(lines):
193 match = pat.match(line)
192 match = pat.match(line)
194 if match:
193 if match:
195 # if it's at toplevel, it's already the best one
194 # if it's at toplevel, it's already the best one
196 if line[0] == 'c':
195 if line[0] == 'c':
197 return lines, i
196 return lines, i
198 # else add whitespace to candidate list
197 # else add whitespace to candidate list
199 candidates.append((match.group(1), i))
198 candidates.append((match.group(1), i))
200 if candidates:
199 if candidates:
201 # this will sort by whitespace, and by line number,
200 # this will sort by whitespace, and by line number,
202 # less whitespace first
201 # less whitespace first
203 candidates.sort()
202 candidates.sort()
204 return lines, candidates[0][1]
203 return lines, candidates[0][1]
205 else:
204 else:
206 raise IOError('could not find class definition')
205 raise IOError('could not find class definition')
207
206
208 if ismethod(object):
207 if ismethod(object):
209 object = object.__func__
208 object = object.__func__
210 if isfunction(object):
209 if isfunction(object):
211 object = object.__code__
210 object = object.__code__
212 if istraceback(object):
211 if istraceback(object):
213 object = object.tb_frame
212 object = object.tb_frame
214 if isframe(object):
213 if isframe(object):
215 object = object.f_code
214 object = object.f_code
216 if iscode(object):
215 if iscode(object):
217 if not hasattr(object, 'co_firstlineno'):
216 if not hasattr(object, 'co_firstlineno'):
218 raise IOError('could not find function definition')
217 raise IOError('could not find function definition')
219 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
218 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
220 pmatch = pat.match
219 pmatch = pat.match
221 # fperez - fix: sometimes, co_firstlineno can give a number larger than
220 # fperez - fix: sometimes, co_firstlineno can give a number larger than
222 # the length of lines, which causes an error. Safeguard against that.
221 # the length of lines, which causes an error. Safeguard against that.
223 lnum = min(object.co_firstlineno, len(lines)) - 1
222 lnum = min(object.co_firstlineno, len(lines)) - 1
224 while lnum > 0:
223 while lnum > 0:
225 if pmatch(lines[lnum]):
224 if pmatch(lines[lnum]):
226 break
225 break
227 lnum -= 1
226 lnum -= 1
228
227
229 return lines, lnum
228 return lines, lnum
230 raise IOError('could not find code object')
229 raise IOError('could not find code object')
231
230
232
231
233 # This is a patched version of inspect.getargs that applies the (unmerged)
232 # This is a patched version of inspect.getargs that applies the (unmerged)
234 # patch for http://bugs.python.org/issue14611 by Stefano Taschini. This fixes
233 # patch for http://bugs.python.org/issue14611 by Stefano Taschini. This fixes
235 # https://github.com/ipython/ipython/issues/8205 and
234 # https://github.com/ipython/ipython/issues/8205 and
236 # https://github.com/ipython/ipython/issues/8293
235 # https://github.com/ipython/ipython/issues/8293
237 def getargs(co):
236 def getargs(co):
238 """Get information about the arguments accepted by a code object.
237 """Get information about the arguments accepted by a code object.
239
238
240 Three things are returned: (args, varargs, varkw), where 'args' is
239 Three things are returned: (args, varargs, varkw), where 'args' is
241 a list of argument names (possibly containing nested lists), and
240 a list of argument names (possibly containing nested lists), and
242 'varargs' and 'varkw' are the names of the * and ** arguments or None."""
241 'varargs' and 'varkw' are the names of the * and ** arguments or None."""
243 if not iscode(co):
242 if not iscode(co):
244 raise TypeError('{!r} is not a code object'.format(co))
243 raise TypeError('{!r} is not a code object'.format(co))
245
244
246 nargs = co.co_argcount
245 nargs = co.co_argcount
247 names = co.co_varnames
246 names = co.co_varnames
248 args = list(names[:nargs])
247 args = list(names[:nargs])
249 step = 0
248 step = 0
250
249
251 # The following acrobatics are for anonymous (tuple) arguments.
250 # The following acrobatics are for anonymous (tuple) arguments.
252 for i in range(nargs):
251 for i in range(nargs):
253 if args[i][:1] in ('', '.'):
252 if args[i][:1] in ('', '.'):
254 stack, remain, count = [], [], []
253 stack, remain, count = [], [], []
255 while step < len(co.co_code):
254 while step < len(co.co_code):
256 op = ord(co.co_code[step])
255 op = ord(co.co_code[step])
257 step = step + 1
256 step = step + 1
258 if op >= dis.HAVE_ARGUMENT:
257 if op >= dis.HAVE_ARGUMENT:
259 opname = dis.opname[op]
258 opname = dis.opname[op]
260 value = ord(co.co_code[step]) + ord(co.co_code[step+1])*256
259 value = ord(co.co_code[step]) + ord(co.co_code[step+1])*256
261 step = step + 2
260 step = step + 2
262 if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'):
261 if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'):
263 remain.append(value)
262 remain.append(value)
264 count.append(value)
263 count.append(value)
265 elif opname in ('STORE_FAST', 'STORE_DEREF'):
264 elif opname in ('STORE_FAST', 'STORE_DEREF'):
266 if op in dis.haslocal:
265 if op in dis.haslocal:
267 stack.append(co.co_varnames[value])
266 stack.append(co.co_varnames[value])
268 elif op in dis.hasfree:
267 elif op in dis.hasfree:
269 stack.append((co.co_cellvars + co.co_freevars)[value])
268 stack.append((co.co_cellvars + co.co_freevars)[value])
270 # Special case for sublists of length 1: def foo((bar))
269 # Special case for sublists of length 1: def foo((bar))
271 # doesn't generate the UNPACK_TUPLE bytecode, so if
270 # doesn't generate the UNPACK_TUPLE bytecode, so if
272 # `remain` is empty here, we have such a sublist.
271 # `remain` is empty here, we have such a sublist.
273 if not remain:
272 if not remain:
274 stack[0] = [stack[0]]
273 stack[0] = [stack[0]]
275 break
274 break
276 else:
275 else:
277 remain[-1] = remain[-1] - 1
276 remain[-1] = remain[-1] - 1
278 while remain[-1] == 0:
277 while remain[-1] == 0:
279 remain.pop()
278 remain.pop()
280 size = count.pop()
279 size = count.pop()
281 stack[-size:] = [stack[-size:]]
280 stack[-size:] = [stack[-size:]]
282 if not remain:
281 if not remain:
283 break
282 break
284 remain[-1] = remain[-1] - 1
283 remain[-1] = remain[-1] - 1
285 if not remain:
284 if not remain:
286 break
285 break
287 args[i] = stack[0]
286 args[i] = stack[0]
288
287
289 varargs = None
288 varargs = None
290 if co.co_flags & inspect.CO_VARARGS:
289 if co.co_flags & inspect.CO_VARARGS:
291 varargs = co.co_varnames[nargs]
290 varargs = co.co_varnames[nargs]
292 nargs = nargs + 1
291 nargs = nargs + 1
293 varkw = None
292 varkw = None
294 if co.co_flags & inspect.CO_VARKEYWORDS:
293 if co.co_flags & inspect.CO_VARKEYWORDS:
295 varkw = co.co_varnames[nargs]
294 varkw = co.co_varnames[nargs]
296 return inspect.Arguments(args, varargs, varkw)
295 return inspect.Arguments(args, varargs, varkw)
297
296
298
297
299 # Monkeypatch inspect to apply our bugfix.
298 # Monkeypatch inspect to apply our bugfix.
300 def with_patch_inspect(f):
299 def with_patch_inspect(f):
301 """
300 """
302 Deprecated since IPython 6.0
301 Deprecated since IPython 6.0
303 decorator for monkeypatching inspect.findsource
302 decorator for monkeypatching inspect.findsource
304 """
303 """
305
304
306 def wrapped(*args, **kwargs):
305 def wrapped(*args, **kwargs):
307 save_findsource = inspect.findsource
306 save_findsource = inspect.findsource
308 save_getargs = inspect.getargs
307 save_getargs = inspect.getargs
309 inspect.findsource = findsource
308 inspect.findsource = findsource
310 inspect.getargs = getargs
309 inspect.getargs = getargs
311 try:
310 try:
312 return f(*args, **kwargs)
311 return f(*args, **kwargs)
313 finally:
312 finally:
314 inspect.findsource = save_findsource
313 inspect.findsource = save_findsource
315 inspect.getargs = save_getargs
314 inspect.getargs = save_getargs
316
315
317 return wrapped
316 return wrapped
318
317
319
318
320 def fix_frame_records_filenames(records):
319 def fix_frame_records_filenames(records):
321 """Try to fix the filenames in each record from inspect.getinnerframes().
320 """Try to fix the filenames in each record from inspect.getinnerframes().
322
321
323 Particularly, modules loaded from within zip files have useless filenames
322 Particularly, modules loaded from within zip files have useless filenames
324 attached to their code object, and inspect.getinnerframes() just uses it.
323 attached to their code object, and inspect.getinnerframes() just uses it.
325 """
324 """
326 fixed_records = []
325 fixed_records = []
327 for frame, filename, line_no, func_name, lines, index in records:
326 for frame, filename, line_no, func_name, lines, index in records:
328 # Look inside the frame's globals dictionary for __file__,
327 # Look inside the frame's globals dictionary for __file__,
329 # which should be better. However, keep Cython filenames since
328 # which should be better. However, keep Cython filenames since
330 # we prefer the source filenames over the compiled .so file.
329 # we prefer the source filenames over the compiled .so file.
331 if not filename.endswith(('.pyx', '.pxd', '.pxi')):
330 if not filename.endswith(('.pyx', '.pxd', '.pxi')):
332 better_fn = frame.f_globals.get('__file__', None)
331 better_fn = frame.f_globals.get('__file__', None)
333 if isinstance(better_fn, str):
332 if isinstance(better_fn, str):
334 # Check the type just in case someone did something weird with
333 # Check the type just in case someone did something weird with
335 # __file__. It might also be None if the error occurred during
334 # __file__. It might also be None if the error occurred during
336 # import.
335 # import.
337 filename = better_fn
336 filename = better_fn
338 fixed_records.append((frame, filename, line_no, func_name, lines, index))
337 fixed_records.append((frame, filename, line_no, func_name, lines, index))
339 return fixed_records
338 return fixed_records
340
339
341
340
342 @with_patch_inspect
341 @with_patch_inspect
343 def _fixed_getinnerframes(etb, context=1, tb_offset=0):
342 def _fixed_getinnerframes(etb, context=1, tb_offset=0):
344 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
343 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
345
344
346 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
345 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
347 # If the error is at the console, don't build any context, since it would
346 # If the error is at the console, don't build any context, since it would
348 # otherwise produce 5 blank lines printed out (there is no file at the
347 # otherwise produce 5 blank lines printed out (there is no file at the
349 # console)
348 # console)
350 rec_check = records[tb_offset:]
349 rec_check = records[tb_offset:]
351 try:
350 try:
352 rname = rec_check[0][1]
351 rname = rec_check[0][1]
353 if rname == '<ipython console>' or rname.endswith('<string>'):
352 if rname == '<ipython console>' or rname.endswith('<string>'):
354 return rec_check
353 return rec_check
355 except IndexError:
354 except IndexError:
356 pass
355 pass
357
356
358 aux = traceback.extract_tb(etb)
357 aux = traceback.extract_tb(etb)
359 assert len(records) == len(aux)
358 assert len(records) == len(aux)
360 for i, (file, lnum, _, _) in enumerate(aux):
359 for i, (file, lnum, _, _) in enumerate(aux):
361 maybeStart = lnum - 1 - context // 2
360 maybeStart = lnum - 1 - context // 2
362 start = max(maybeStart, 0)
361 start = max(maybeStart, 0)
363 end = start + context
362 end = start + context
364 lines = linecache.getlines(file)[start:end]
363 lines = linecache.getlines(file)[start:end]
365 buf = list(records[i])
364 buf = list(records[i])
366 buf[LNUM_POS] = lnum
365 buf[LNUM_POS] = lnum
367 buf[INDEX_POS] = lnum - 1 - start
366 buf[INDEX_POS] = lnum - 1 - start
368 buf[LINES_POS] = lines
367 buf[LINES_POS] = lines
369 records[i] = tuple(buf)
368 records[i] = tuple(buf)
370 return records[tb_offset:]
369 return records[tb_offset:]
371
370
372 # Helper function -- largely belongs to VerboseTB, but we need the same
371 # Helper function -- largely belongs to VerboseTB, but we need the same
373 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
372 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
374 # can be recognized properly by ipython.el's py-traceback-line-re
373 # can be recognized properly by ipython.el's py-traceback-line-re
375 # (SyntaxErrors have to be treated specially because they have no traceback)
374 # (SyntaxErrors have to be treated specially because they have no traceback)
376
375
377
376
378 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None, _line_format=(lambda x,_:x,None)):
377 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None, _line_format=(lambda x,_:x,None)):
379 numbers_width = INDENT_SIZE - 1
378 numbers_width = INDENT_SIZE - 1
380 res = []
379 res = []
381 i = lnum - index
380 i = lnum - index
382
381
383 for line in lines:
382 for line in lines:
384 line = py3compat.cast_unicode(line)
383 line = py3compat.cast_unicode(line)
385
384
386 new_line, err = _line_format(line, 'str')
385 new_line, err = _line_format(line, 'str')
387 if not err: line = new_line
386 if not err: line = new_line
388
387
389 if i == lnum:
388 if i == lnum:
390 # This is the line with the error
389 # This is the line with the error
391 pad = numbers_width - len(str(i))
390 pad = numbers_width - len(str(i))
392 num = '%s%s' % (debugger.make_arrow(pad), str(lnum))
391 num = '%s%s' % (debugger.make_arrow(pad), str(lnum))
393 line = '%s%s%s %s%s' % (Colors.linenoEm, num,
392 line = '%s%s%s %s%s' % (Colors.linenoEm, num,
394 Colors.line, line, Colors.Normal)
393 Colors.line, line, Colors.Normal)
395 else:
394 else:
396 num = '%*s' % (numbers_width, i)
395 num = '%*s' % (numbers_width, i)
397 line = '%s%s%s %s' % (Colors.lineno, num,
396 line = '%s%s%s %s' % (Colors.lineno, num,
398 Colors.Normal, line)
397 Colors.Normal, line)
399
398
400 res.append(line)
399 res.append(line)
401 if lvals and i == lnum:
400 if lvals and i == lnum:
402 res.append(lvals + '\n')
401 res.append(lvals + '\n')
403 i = i + 1
402 i = i + 1
404 return res
403 return res
405
404
406 def is_recursion_error(etype, value, records):
405 def is_recursion_error(etype, value, records):
407 try:
406 try:
408 # RecursionError is new in Python 3.5
407 # RecursionError is new in Python 3.5
409 recursion_error_type = RecursionError
408 recursion_error_type = RecursionError
410 except NameError:
409 except NameError:
411 recursion_error_type = RuntimeError
410 recursion_error_type = RuntimeError
412
411
413 # The default recursion limit is 1000, but some of that will be taken up
412 # The default recursion limit is 1000, but some of that will be taken up
414 # by stack frames in IPython itself. >500 frames probably indicates
413 # by stack frames in IPython itself. >500 frames probably indicates
415 # a recursion error.
414 # a recursion error.
416 return (etype is recursion_error_type) \
415 return (etype is recursion_error_type) \
417 and "recursion" in str(value).lower() \
416 and "recursion" in str(value).lower() \
418 and len(records) > 500
417 and len(records) > 500
419
418
420 def find_recursion(etype, value, records):
419 def find_recursion(etype, value, records):
421 """Identify the repeating stack frames from a RecursionError traceback
420 """Identify the repeating stack frames from a RecursionError traceback
422
421
423 'records' is a list as returned by VerboseTB.get_records()
422 'records' is a list as returned by VerboseTB.get_records()
424
423
425 Returns (last_unique, repeat_length)
424 Returns (last_unique, repeat_length)
426 """
425 """
427 # This involves a bit of guesswork - we want to show enough of the traceback
426 # This involves a bit of guesswork - we want to show enough of the traceback
428 # to indicate where the recursion is occurring. We guess that the innermost
427 # to indicate where the recursion is occurring. We guess that the innermost
429 # quarter of the traceback (250 frames by default) is repeats, and find the
428 # quarter of the traceback (250 frames by default) is repeats, and find the
430 # first frame (from in to out) that looks different.
429 # first frame (from in to out) that looks different.
431 if not is_recursion_error(etype, value, records):
430 if not is_recursion_error(etype, value, records):
432 return len(records), 0
431 return len(records), 0
433
432
434 # Select filename, lineno, func_name to track frames with
433 # Select filename, lineno, func_name to track frames with
435 records = [r[1:4] for r in records]
434 records = [r[1:4] for r in records]
436 inner_frames = records[-(len(records)//4):]
435 inner_frames = records[-(len(records)//4):]
437 frames_repeated = set(inner_frames)
436 frames_repeated = set(inner_frames)
438
437
439 last_seen_at = {}
438 last_seen_at = {}
440 longest_repeat = 0
439 longest_repeat = 0
441 i = len(records)
440 i = len(records)
442 for frame in reversed(records):
441 for frame in reversed(records):
443 i -= 1
442 i -= 1
444 if frame not in frames_repeated:
443 if frame not in frames_repeated:
445 last_unique = i
444 last_unique = i
446 break
445 break
447
446
448 if frame in last_seen_at:
447 if frame in last_seen_at:
449 distance = last_seen_at[frame] - i
448 distance = last_seen_at[frame] - i
450 longest_repeat = max(longest_repeat, distance)
449 longest_repeat = max(longest_repeat, distance)
451
450
452 last_seen_at[frame] = i
451 last_seen_at[frame] = i
453 else:
452 else:
454 last_unique = 0 # The whole traceback was recursion
453 last_unique = 0 # The whole traceback was recursion
455
454
456 return last_unique, longest_repeat
455 return last_unique, longest_repeat
457
456
458 #---------------------------------------------------------------------------
457 #---------------------------------------------------------------------------
459 # Module classes
458 # Module classes
460 class TBTools(colorable.Colorable):
459 class TBTools(colorable.Colorable):
461 """Basic tools used by all traceback printer classes."""
460 """Basic tools used by all traceback printer classes."""
462
461
463 # Number of frames to skip when reporting tracebacks
462 # Number of frames to skip when reporting tracebacks
464 tb_offset = 0
463 tb_offset = 0
465
464
466 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
465 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
467 # Whether to call the interactive pdb debugger after printing
466 # Whether to call the interactive pdb debugger after printing
468 # tracebacks or not
467 # tracebacks or not
469 super(TBTools, self).__init__(parent=parent, config=config)
468 super(TBTools, self).__init__(parent=parent, config=config)
470 self.call_pdb = call_pdb
469 self.call_pdb = call_pdb
471
470
472 # Output stream to write to. Note that we store the original value in
471 # Output stream to write to. Note that we store the original value in
473 # a private attribute and then make the public ostream a property, so
472 # a private attribute and then make the public ostream a property, so
474 # that we can delay accessing sys.stdout until runtime. The way
473 # that we can delay accessing sys.stdout until runtime. The way
475 # things are written now, the sys.stdout object is dynamically managed
474 # things are written now, the sys.stdout object is dynamically managed
476 # so a reference to it should NEVER be stored statically. This
475 # so a reference to it should NEVER be stored statically. This
477 # property approach confines this detail to a single location, and all
476 # property approach confines this detail to a single location, and all
478 # subclasses can simply access self.ostream for writing.
477 # subclasses can simply access self.ostream for writing.
479 self._ostream = ostream
478 self._ostream = ostream
480
479
481 # Create color table
480 # Create color table
482 self.color_scheme_table = exception_colors()
481 self.color_scheme_table = exception_colors()
483
482
484 self.set_colors(color_scheme)
483 self.set_colors(color_scheme)
485 self.old_scheme = color_scheme # save initial value for toggles
484 self.old_scheme = color_scheme # save initial value for toggles
486
485
487 if call_pdb:
486 if call_pdb:
488 self.pdb = debugger.Pdb()
487 self.pdb = debugger.Pdb()
489 else:
488 else:
490 self.pdb = None
489 self.pdb = None
491
490
492 def _get_ostream(self):
491 def _get_ostream(self):
493 """Output stream that exceptions are written to.
492 """Output stream that exceptions are written to.
494
493
495 Valid values are:
494 Valid values are:
496
495
497 - None: the default, which means that IPython will dynamically resolve
496 - None: the default, which means that IPython will dynamically resolve
498 to sys.stdout. This ensures compatibility with most tools, including
497 to sys.stdout. This ensures compatibility with most tools, including
499 Windows (where plain stdout doesn't recognize ANSI escapes).
498 Windows (where plain stdout doesn't recognize ANSI escapes).
500
499
501 - Any object with 'write' and 'flush' attributes.
500 - Any object with 'write' and 'flush' attributes.
502 """
501 """
503 return sys.stdout if self._ostream is None else self._ostream
502 return sys.stdout if self._ostream is None else self._ostream
504
503
505 def _set_ostream(self, val):
504 def _set_ostream(self, val):
506 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
505 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
507 self._ostream = val
506 self._ostream = val
508
507
509 ostream = property(_get_ostream, _set_ostream)
508 ostream = property(_get_ostream, _set_ostream)
510
509
511 def set_colors(self, *args, **kw):
510 def set_colors(self, *args, **kw):
512 """Shorthand access to the color table scheme selector method."""
511 """Shorthand access to the color table scheme selector method."""
513
512
514 # Set own color table
513 # Set own color table
515 self.color_scheme_table.set_active_scheme(*args, **kw)
514 self.color_scheme_table.set_active_scheme(*args, **kw)
516 # for convenience, set Colors to the active scheme
515 # for convenience, set Colors to the active scheme
517 self.Colors = self.color_scheme_table.active_colors
516 self.Colors = self.color_scheme_table.active_colors
518 # Also set colors of debugger
517 # Also set colors of debugger
519 if hasattr(self, 'pdb') and self.pdb is not None:
518 if hasattr(self, 'pdb') and self.pdb is not None:
520 self.pdb.set_colors(*args, **kw)
519 self.pdb.set_colors(*args, **kw)
521
520
522 def color_toggle(self):
521 def color_toggle(self):
523 """Toggle between the currently active color scheme and NoColor."""
522 """Toggle between the currently active color scheme and NoColor."""
524
523
525 if self.color_scheme_table.active_scheme_name == 'NoColor':
524 if self.color_scheme_table.active_scheme_name == 'NoColor':
526 self.color_scheme_table.set_active_scheme(self.old_scheme)
525 self.color_scheme_table.set_active_scheme(self.old_scheme)
527 self.Colors = self.color_scheme_table.active_colors
526 self.Colors = self.color_scheme_table.active_colors
528 else:
527 else:
529 self.old_scheme = self.color_scheme_table.active_scheme_name
528 self.old_scheme = self.color_scheme_table.active_scheme_name
530 self.color_scheme_table.set_active_scheme('NoColor')
529 self.color_scheme_table.set_active_scheme('NoColor')
531 self.Colors = self.color_scheme_table.active_colors
530 self.Colors = self.color_scheme_table.active_colors
532
531
533 def stb2text(self, stb):
532 def stb2text(self, stb):
534 """Convert a structured traceback (a list) to a string."""
533 """Convert a structured traceback (a list) to a string."""
535 return '\n'.join(stb)
534 return '\n'.join(stb)
536
535
537 def text(self, etype, value, tb, tb_offset=None, context=5):
536 def text(self, etype, value, tb, tb_offset=None, context=5):
538 """Return formatted traceback.
537 """Return formatted traceback.
539
538
540 Subclasses may override this if they add extra arguments.
539 Subclasses may override this if they add extra arguments.
541 """
540 """
542 tb_list = self.structured_traceback(etype, value, tb,
541 tb_list = self.structured_traceback(etype, value, tb,
543 tb_offset, context)
542 tb_offset, context)
544 return self.stb2text(tb_list)
543 return self.stb2text(tb_list)
545
544
546 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
545 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
547 context=5, mode=None):
546 context=5, mode=None):
548 """Return a list of traceback frames.
547 """Return a list of traceback frames.
549
548
550 Must be implemented by each class.
549 Must be implemented by each class.
551 """
550 """
552 raise NotImplementedError()
551 raise NotImplementedError()
553
552
554
553
555 #---------------------------------------------------------------------------
554 #---------------------------------------------------------------------------
556 class ListTB(TBTools):
555 class ListTB(TBTools):
557 """Print traceback information from a traceback list, with optional color.
556 """Print traceback information from a traceback list, with optional color.
558
557
559 Calling requires 3 arguments: (etype, evalue, elist)
558 Calling requires 3 arguments: (etype, evalue, elist)
560 as would be obtained by::
559 as would be obtained by::
561
560
562 etype, evalue, tb = sys.exc_info()
561 etype, evalue, tb = sys.exc_info()
563 if tb:
562 if tb:
564 elist = traceback.extract_tb(tb)
563 elist = traceback.extract_tb(tb)
565 else:
564 else:
566 elist = None
565 elist = None
567
566
568 It can thus be used by programs which need to process the traceback before
567 It can thus be used by programs which need to process the traceback before
569 printing (such as console replacements based on the code module from the
568 printing (such as console replacements based on the code module from the
570 standard library).
569 standard library).
571
570
572 Because they are meant to be called without a full traceback (only a
571 Because they are meant to be called without a full traceback (only a
573 list), instances of this class can't call the interactive pdb debugger."""
572 list), instances of this class can't call the interactive pdb debugger."""
574
573
575 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
574 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
576 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
575 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
577 ostream=ostream, parent=parent,config=config)
576 ostream=ostream, parent=parent,config=config)
578
577
579 def __call__(self, etype, value, elist):
578 def __call__(self, etype, value, elist):
580 self.ostream.flush()
579 self.ostream.flush()
581 self.ostream.write(self.text(etype, value, elist))
580 self.ostream.write(self.text(etype, value, elist))
582 self.ostream.write('\n')
581 self.ostream.write('\n')
583
582
584 def structured_traceback(self, etype, value, elist, tb_offset=None,
583 def structured_traceback(self, etype, value, elist, tb_offset=None,
585 context=5):
584 context=5):
586 """Return a color formatted string with the traceback info.
585 """Return a color formatted string with the traceback info.
587
586
588 Parameters
587 Parameters
589 ----------
588 ----------
590 etype : exception type
589 etype : exception type
591 Type of the exception raised.
590 Type of the exception raised.
592
591
593 value : object
592 value : object
594 Data stored in the exception
593 Data stored in the exception
595
594
596 elist : list
595 elist : list
597 List of frames, see class docstring for details.
596 List of frames, see class docstring for details.
598
597
599 tb_offset : int, optional
598 tb_offset : int, optional
600 Number of frames in the traceback to skip. If not given, the
599 Number of frames in the traceback to skip. If not given, the
601 instance value is used (set in constructor).
600 instance value is used (set in constructor).
602
601
603 context : int, optional
602 context : int, optional
604 Number of lines of context information to print.
603 Number of lines of context information to print.
605
604
606 Returns
605 Returns
607 -------
606 -------
608 String with formatted exception.
607 String with formatted exception.
609 """
608 """
610 tb_offset = self.tb_offset if tb_offset is None else tb_offset
609 tb_offset = self.tb_offset if tb_offset is None else tb_offset
611 Colors = self.Colors
610 Colors = self.Colors
612 out_list = []
611 out_list = []
613 if elist:
612 if elist:
614
613
615 if tb_offset and len(elist) > tb_offset:
614 if tb_offset and len(elist) > tb_offset:
616 elist = elist[tb_offset:]
615 elist = elist[tb_offset:]
617
616
618 out_list.append('Traceback %s(most recent call last)%s:' %
617 out_list.append('Traceback %s(most recent call last)%s:' %
619 (Colors.normalEm, Colors.Normal) + '\n')
618 (Colors.normalEm, Colors.Normal) + '\n')
620 out_list.extend(self._format_list(elist))
619 out_list.extend(self._format_list(elist))
621 # The exception info should be a single entry in the list.
620 # The exception info should be a single entry in the list.
622 lines = ''.join(self._format_exception_only(etype, value))
621 lines = ''.join(self._format_exception_only(etype, value))
623 out_list.append(lines)
622 out_list.append(lines)
624
623
625 # Note: this code originally read:
624 # Note: this code originally read:
626
625
627 ## for line in lines[:-1]:
626 ## for line in lines[:-1]:
628 ## out_list.append(" "+line)
627 ## out_list.append(" "+line)
629 ## out_list.append(lines[-1])
628 ## out_list.append(lines[-1])
630
629
631 # This means it was indenting everything but the last line by a little
630 # This means it was indenting everything but the last line by a little
632 # bit. I've disabled this for now, but if we see ugliness somewhere we
631 # bit. I've disabled this for now, but if we see ugliness somewhere we
633 # can restore it.
632 # can restore it.
634
633
635 return out_list
634 return out_list
636
635
637 def _format_list(self, extracted_list):
636 def _format_list(self, extracted_list):
638 """Format a list of traceback entry tuples for printing.
637 """Format a list of traceback entry tuples for printing.
639
638
640 Given a list of tuples as returned by extract_tb() or
639 Given a list of tuples as returned by extract_tb() or
641 extract_stack(), return a list of strings ready for printing.
640 extract_stack(), return a list of strings ready for printing.
642 Each string in the resulting list corresponds to the item with the
641 Each string in the resulting list corresponds to the item with the
643 same index in the argument list. Each string ends in a newline;
642 same index in the argument list. Each string ends in a newline;
644 the strings may contain internal newlines as well, for those items
643 the strings may contain internal newlines as well, for those items
645 whose source text line is not None.
644 whose source text line is not None.
646
645
647 Lifted almost verbatim from traceback.py
646 Lifted almost verbatim from traceback.py
648 """
647 """
649
648
650 Colors = self.Colors
649 Colors = self.Colors
651 list = []
650 list = []
652 for filename, lineno, name, line in extracted_list[:-1]:
651 for filename, lineno, name, line in extracted_list[:-1]:
653 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
652 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
654 (Colors.filename, filename, Colors.Normal,
653 (Colors.filename, filename, Colors.Normal,
655 Colors.lineno, lineno, Colors.Normal,
654 Colors.lineno, lineno, Colors.Normal,
656 Colors.name, name, Colors.Normal)
655 Colors.name, name, Colors.Normal)
657 if line:
656 if line:
658 item += ' %s\n' % line.strip()
657 item += ' %s\n' % line.strip()
659 list.append(item)
658 list.append(item)
660 # Emphasize the last entry
659 # Emphasize the last entry
661 filename, lineno, name, line = extracted_list[-1]
660 filename, lineno, name, line = extracted_list[-1]
662 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
661 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
663 (Colors.normalEm,
662 (Colors.normalEm,
664 Colors.filenameEm, filename, Colors.normalEm,
663 Colors.filenameEm, filename, Colors.normalEm,
665 Colors.linenoEm, lineno, Colors.normalEm,
664 Colors.linenoEm, lineno, Colors.normalEm,
666 Colors.nameEm, name, Colors.normalEm,
665 Colors.nameEm, name, Colors.normalEm,
667 Colors.Normal)
666 Colors.Normal)
668 if line:
667 if line:
669 item += '%s %s%s\n' % (Colors.line, line.strip(),
668 item += '%s %s%s\n' % (Colors.line, line.strip(),
670 Colors.Normal)
669 Colors.Normal)
671 list.append(item)
670 list.append(item)
672 return list
671 return list
673
672
674 def _format_exception_only(self, etype, value):
673 def _format_exception_only(self, etype, value):
675 """Format the exception part of a traceback.
674 """Format the exception part of a traceback.
676
675
677 The arguments are the exception type and value such as given by
676 The arguments are the exception type and value such as given by
678 sys.exc_info()[:2]. The return value is a list of strings, each ending
677 sys.exc_info()[:2]. The return value is a list of strings, each ending
679 in a newline. Normally, the list contains a single string; however,
678 in a newline. Normally, the list contains a single string; however,
680 for SyntaxError exceptions, it contains several lines that (when
679 for SyntaxError exceptions, it contains several lines that (when
681 printed) display detailed information about where the syntax error
680 printed) display detailed information about where the syntax error
682 occurred. The message indicating which exception occurred is the
681 occurred. The message indicating which exception occurred is the
683 always last string in the list.
682 always last string in the list.
684
683
685 Also lifted nearly verbatim from traceback.py
684 Also lifted nearly verbatim from traceback.py
686 """
685 """
687 have_filedata = False
686 have_filedata = False
688 Colors = self.Colors
687 Colors = self.Colors
689 list = []
688 list = []
690 stype = py3compat.cast_unicode(Colors.excName + etype.__name__ + Colors.Normal)
689 stype = py3compat.cast_unicode(Colors.excName + etype.__name__ + Colors.Normal)
691 if value is None:
690 if value is None:
692 # Not sure if this can still happen in Python 2.6 and above
691 # Not sure if this can still happen in Python 2.6 and above
693 list.append(stype + '\n')
692 list.append(stype + '\n')
694 else:
693 else:
695 if issubclass(etype, SyntaxError):
694 if issubclass(etype, SyntaxError):
696 have_filedata = True
695 have_filedata = True
697 if not value.filename: value.filename = "<string>"
696 if not value.filename: value.filename = "<string>"
698 if value.lineno:
697 if value.lineno:
699 lineno = value.lineno
698 lineno = value.lineno
700 textline = linecache.getline(value.filename, value.lineno)
699 textline = linecache.getline(value.filename, value.lineno)
701 else:
700 else:
702 lineno = 'unknown'
701 lineno = 'unknown'
703 textline = ''
702 textline = ''
704 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
703 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
705 (Colors.normalEm,
704 (Colors.normalEm,
706 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
705 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
707 Colors.linenoEm, lineno, Colors.Normal ))
706 Colors.linenoEm, lineno, Colors.Normal ))
708 if textline == '':
707 if textline == '':
709 textline = py3compat.cast_unicode(value.text, "utf-8")
708 textline = py3compat.cast_unicode(value.text, "utf-8")
710
709
711 if textline is not None:
710 if textline is not None:
712 i = 0
711 i = 0
713 while i < len(textline) and textline[i].isspace():
712 while i < len(textline) and textline[i].isspace():
714 i += 1
713 i += 1
715 list.append('%s %s%s\n' % (Colors.line,
714 list.append('%s %s%s\n' % (Colors.line,
716 textline.strip(),
715 textline.strip(),
717 Colors.Normal))
716 Colors.Normal))
718 if value.offset is not None:
717 if value.offset is not None:
719 s = ' '
718 s = ' '
720 for c in textline[i:value.offset - 1]:
719 for c in textline[i:value.offset - 1]:
721 if c.isspace():
720 if c.isspace():
722 s += c
721 s += c
723 else:
722 else:
724 s += ' '
723 s += ' '
725 list.append('%s%s^%s\n' % (Colors.caret, s,
724 list.append('%s%s^%s\n' % (Colors.caret, s,
726 Colors.Normal))
725 Colors.Normal))
727
726
728 try:
727 try:
729 s = value.msg
728 s = value.msg
730 except Exception:
729 except Exception:
731 s = self._some_str(value)
730 s = self._some_str(value)
732 if s:
731 if s:
733 list.append('%s%s:%s %s\n' % (stype, Colors.excName,
732 list.append('%s%s:%s %s\n' % (stype, Colors.excName,
734 Colors.Normal, s))
733 Colors.Normal, s))
735 else:
734 else:
736 list.append('%s\n' % stype)
735 list.append('%s\n' % stype)
737
736
738 # sync with user hooks
737 # sync with user hooks
739 if have_filedata:
738 if have_filedata:
740 ipinst = get_ipython()
739 ipinst = get_ipython()
741 if ipinst is not None:
740 if ipinst is not None:
742 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
741 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
743
742
744 return list
743 return list
745
744
746 def get_exception_only(self, etype, value):
745 def get_exception_only(self, etype, value):
747 """Only print the exception type and message, without a traceback.
746 """Only print the exception type and message, without a traceback.
748
747
749 Parameters
748 Parameters
750 ----------
749 ----------
751 etype : exception type
750 etype : exception type
752 value : exception value
751 value : exception value
753 """
752 """
754 return ListTB.structured_traceback(self, etype, value, [])
753 return ListTB.structured_traceback(self, etype, value, [])
755
754
756 def show_exception_only(self, etype, evalue):
755 def show_exception_only(self, etype, evalue):
757 """Only print the exception type and message, without a traceback.
756 """Only print the exception type and message, without a traceback.
758
757
759 Parameters
758 Parameters
760 ----------
759 ----------
761 etype : exception type
760 etype : exception type
762 value : exception value
761 value : exception value
763 """
762 """
764 # This method needs to use __call__ from *this* class, not the one from
763 # This method needs to use __call__ from *this* class, not the one from
765 # a subclass whose signature or behavior may be different
764 # a subclass whose signature or behavior may be different
766 ostream = self.ostream
765 ostream = self.ostream
767 ostream.flush()
766 ostream.flush()
768 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
767 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
769 ostream.flush()
768 ostream.flush()
770
769
771 def _some_str(self, value):
770 def _some_str(self, value):
772 # Lifted from traceback.py
771 # Lifted from traceback.py
773 try:
772 try:
774 return py3compat.cast_unicode(str(value))
773 return py3compat.cast_unicode(str(value))
775 except:
774 except:
776 return u'<unprintable %s object>' % type(value).__name__
775 return u'<unprintable %s object>' % type(value).__name__
777
776
778
777
779 #----------------------------------------------------------------------------
778 #----------------------------------------------------------------------------
780 class VerboseTB(TBTools):
779 class VerboseTB(TBTools):
781 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
780 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
782 of HTML. Requires inspect and pydoc. Crazy, man.
781 of HTML. Requires inspect and pydoc. Crazy, man.
783
782
784 Modified version which optionally strips the topmost entries from the
783 Modified version which optionally strips the topmost entries from the
785 traceback, to be used with alternate interpreters (because their own code
784 traceback, to be used with alternate interpreters (because their own code
786 would appear in the traceback)."""
785 would appear in the traceback)."""
787
786
788 def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None,
787 def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None,
789 tb_offset=0, long_header=False, include_vars=True,
788 tb_offset=0, long_header=False, include_vars=True,
790 check_cache=None, debugger_cls = None,
789 check_cache=None, debugger_cls = None,
791 parent=None, config=None):
790 parent=None, config=None):
792 """Specify traceback offset, headers and color scheme.
791 """Specify traceback offset, headers and color scheme.
793
792
794 Define how many frames to drop from the tracebacks. Calling it with
793 Define how many frames to drop from the tracebacks. Calling it with
795 tb_offset=1 allows use of this handler in interpreters which will have
794 tb_offset=1 allows use of this handler in interpreters which will have
796 their own code at the top of the traceback (VerboseTB will first
795 their own code at the top of the traceback (VerboseTB will first
797 remove that frame before printing the traceback info)."""
796 remove that frame before printing the traceback info)."""
798 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
797 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
799 ostream=ostream, parent=parent, config=config)
798 ostream=ostream, parent=parent, config=config)
800 self.tb_offset = tb_offset
799 self.tb_offset = tb_offset
801 self.long_header = long_header
800 self.long_header = long_header
802 self.include_vars = include_vars
801 self.include_vars = include_vars
803 # By default we use linecache.checkcache, but the user can provide a
802 # By default we use linecache.checkcache, but the user can provide a
804 # different check_cache implementation. This is used by the IPython
803 # different check_cache implementation. This is used by the IPython
805 # kernel to provide tracebacks for interactive code that is cached,
804 # kernel to provide tracebacks for interactive code that is cached,
806 # by a compiler instance that flushes the linecache but preserves its
805 # by a compiler instance that flushes the linecache but preserves its
807 # own code cache.
806 # own code cache.
808 if check_cache is None:
807 if check_cache is None:
809 check_cache = linecache.checkcache
808 check_cache = linecache.checkcache
810 self.check_cache = check_cache
809 self.check_cache = check_cache
811
810
812 self.debugger_cls = debugger_cls or debugger.Pdb
811 self.debugger_cls = debugger_cls or debugger.Pdb
813
812
814 def format_records(self, records, last_unique, recursion_repeat):
813 def format_records(self, records, last_unique, recursion_repeat):
815 """Format the stack frames of the traceback"""
814 """Format the stack frames of the traceback"""
816 frames = []
815 frames = []
817 for r in records[:last_unique+recursion_repeat+1]:
816 for r in records[:last_unique+recursion_repeat+1]:
818 #print '*** record:',file,lnum,func,lines,index # dbg
817 #print '*** record:',file,lnum,func,lines,index # dbg
819 frames.append(self.format_record(*r))
818 frames.append(self.format_record(*r))
820
819
821 if recursion_repeat:
820 if recursion_repeat:
822 frames.append('... last %d frames repeated, from the frame below ...\n' % recursion_repeat)
821 frames.append('... last %d frames repeated, from the frame below ...\n' % recursion_repeat)
823 frames.append(self.format_record(*records[last_unique+recursion_repeat+1]))
822 frames.append(self.format_record(*records[last_unique+recursion_repeat+1]))
824
823
825 return frames
824 return frames
826
825
827 def format_record(self, frame, file, lnum, func, lines, index):
826 def format_record(self, frame, file, lnum, func, lines, index):
828 """Format a single stack frame"""
827 """Format a single stack frame"""
829 Colors = self.Colors # just a shorthand + quicker name lookup
828 Colors = self.Colors # just a shorthand + quicker name lookup
830 ColorsNormal = Colors.Normal # used a lot
829 ColorsNormal = Colors.Normal # used a lot
831 col_scheme = self.color_scheme_table.active_scheme_name
830 col_scheme = self.color_scheme_table.active_scheme_name
832 indent = ' ' * INDENT_SIZE
831 indent = ' ' * INDENT_SIZE
833 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
832 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
834 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
833 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
835 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
834 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
836 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
835 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
837 ColorsNormal)
836 ColorsNormal)
838 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
837 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
839 (Colors.vName, Colors.valEm, ColorsNormal)
838 (Colors.vName, Colors.valEm, ColorsNormal)
840 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
839 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
841 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
840 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
842 Colors.vName, ColorsNormal)
841 Colors.vName, ColorsNormal)
843 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
842 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
844
843
845 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
844 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
846 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm, Colors.line,
845 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm, Colors.line,
847 ColorsNormal)
846 ColorsNormal)
848
847
849 abspath = os.path.abspath
848 abspath = os.path.abspath
850
849
851
850
852 if not file:
851 if not file:
853 file = '?'
852 file = '?'
854 elif file.startswith(str("<")) and file.endswith(str(">")):
853 elif file.startswith(str("<")) and file.endswith(str(">")):
855 # Not a real filename, no problem...
854 # Not a real filename, no problem...
856 pass
855 pass
857 elif not os.path.isabs(file):
856 elif not os.path.isabs(file):
858 # Try to make the filename absolute by trying all
857 # Try to make the filename absolute by trying all
859 # sys.path entries (which is also what linecache does)
858 # sys.path entries (which is also what linecache does)
860 for dirname in sys.path:
859 for dirname in sys.path:
861 try:
860 try:
862 fullname = os.path.join(dirname, file)
861 fullname = os.path.join(dirname, file)
863 if os.path.isfile(fullname):
862 if os.path.isfile(fullname):
864 file = os.path.abspath(fullname)
863 file = os.path.abspath(fullname)
865 break
864 break
866 except Exception:
865 except Exception:
867 # Just in case that sys.path contains very
866 # Just in case that sys.path contains very
868 # strange entries...
867 # strange entries...
869 pass
868 pass
870
869
871 file = py3compat.cast_unicode(file, util_path.fs_encoding)
870 file = py3compat.cast_unicode(file, util_path.fs_encoding)
872 link = tpl_link % util_path.compress_user(file)
871 link = tpl_link % util_path.compress_user(file)
873 args, varargs, varkw, locals = inspect.getargvalues(frame)
872 args, varargs, varkw, locals = inspect.getargvalues(frame)
874
873
875 if func == '?':
874 if func == '?':
876 call = ''
875 call = ''
877 else:
876 else:
878 # Decide whether to include variable details or not
877 # Decide whether to include variable details or not
879 var_repr = self.include_vars and eqrepr or nullrepr
878 var_repr = self.include_vars and eqrepr or nullrepr
880 try:
879 try:
881 call = tpl_call % (func, inspect.formatargvalues(args,
880 call = tpl_call % (func, inspect.formatargvalues(args,
882 varargs, varkw,
881 varargs, varkw,
883 locals, formatvalue=var_repr))
882 locals, formatvalue=var_repr))
884 except KeyError:
883 except KeyError:
885 # This happens in situations like errors inside generator
884 # This happens in situations like errors inside generator
886 # expressions, where local variables are listed in the
885 # expressions, where local variables are listed in the
887 # line, but can't be extracted from the frame. I'm not
886 # line, but can't be extracted from the frame. I'm not
888 # 100% sure this isn't actually a bug in inspect itself,
887 # 100% sure this isn't actually a bug in inspect itself,
889 # but since there's no info for us to compute with, the
888 # but since there's no info for us to compute with, the
890 # best we can do is report the failure and move on. Here
889 # best we can do is report the failure and move on. Here
891 # we must *not* call any traceback construction again,
890 # we must *not* call any traceback construction again,
892 # because that would mess up use of %debug later on. So we
891 # because that would mess up use of %debug later on. So we
893 # simply report the failure and move on. The only
892 # simply report the failure and move on. The only
894 # limitation will be that this frame won't have locals
893 # limitation will be that this frame won't have locals
895 # listed in the call signature. Quite subtle problem...
894 # listed in the call signature. Quite subtle problem...
896 # I can't think of a good way to validate this in a unit
895 # I can't think of a good way to validate this in a unit
897 # test, but running a script consisting of:
896 # test, but running a script consisting of:
898 # dict( (k,v.strip()) for (k,v) in range(10) )
897 # dict( (k,v.strip()) for (k,v) in range(10) )
899 # will illustrate the error, if this exception catch is
898 # will illustrate the error, if this exception catch is
900 # disabled.
899 # disabled.
901 call = tpl_call_fail % func
900 call = tpl_call_fail % func
902
901
903 # Don't attempt to tokenize binary files.
902 # Don't attempt to tokenize binary files.
904 if file.endswith(('.so', '.pyd', '.dll')):
903 if file.endswith(('.so', '.pyd', '.dll')):
905 return '%s %s\n' % (link, call)
904 return '%s %s\n' % (link, call)
906
905
907 elif file.endswith(('.pyc', '.pyo')):
906 elif file.endswith(('.pyc', '.pyo')):
908 # Look up the corresponding source file.
907 # Look up the corresponding source file.
909 try:
908 try:
910 file = openpy.source_from_cache(file)
909 file = openpy.source_from_cache(file)
911 except ValueError:
910 except ValueError:
912 # Failed to get the source file for some reason
911 # Failed to get the source file for some reason
913 # E.g. https://github.com/ipython/ipython/issues/9486
912 # E.g. https://github.com/ipython/ipython/issues/9486
914 return '%s %s\n' % (link, call)
913 return '%s %s\n' % (link, call)
915
914
916 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
915 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
917 line = getline(file, lnum[0])
916 line = getline(file, lnum[0])
918 lnum[0] += 1
917 lnum[0] += 1
919 return line
918 return line
920
919
921 # Build the list of names on this line of code where the exception
920 # Build the list of names on this line of code where the exception
922 # occurred.
921 # occurred.
923 try:
922 try:
924 names = []
923 names = []
925 name_cont = False
924 name_cont = False
926
925
927 for token_type, token, start, end, line in generate_tokens(linereader):
926 for token_type, token, start, end, line in generate_tokens(linereader):
928 # build composite names
927 # build composite names
929 if token_type == tokenize.NAME and token not in keyword.kwlist:
928 if token_type == tokenize.NAME and token not in keyword.kwlist:
930 if name_cont:
929 if name_cont:
931 # Continuation of a dotted name
930 # Continuation of a dotted name
932 try:
931 try:
933 names[-1].append(token)
932 names[-1].append(token)
934 except IndexError:
933 except IndexError:
935 names.append([token])
934 names.append([token])
936 name_cont = False
935 name_cont = False
937 else:
936 else:
938 # Regular new names. We append everything, the caller
937 # Regular new names. We append everything, the caller
939 # will be responsible for pruning the list later. It's
938 # will be responsible for pruning the list later. It's
940 # very tricky to try to prune as we go, b/c composite
939 # very tricky to try to prune as we go, b/c composite
941 # names can fool us. The pruning at the end is easy
940 # names can fool us. The pruning at the end is easy
942 # to do (or the caller can print a list with repeated
941 # to do (or the caller can print a list with repeated
943 # names if so desired.
942 # names if so desired.
944 names.append([token])
943 names.append([token])
945 elif token == '.':
944 elif token == '.':
946 name_cont = True
945 name_cont = True
947 elif token_type == tokenize.NEWLINE:
946 elif token_type == tokenize.NEWLINE:
948 break
947 break
949
948
950 except (IndexError, UnicodeDecodeError, SyntaxError):
949 except (IndexError, UnicodeDecodeError, SyntaxError):
951 # signals exit of tokenizer
950 # signals exit of tokenizer
952 # SyntaxError can occur if the file is not actually Python
951 # SyntaxError can occur if the file is not actually Python
953 # - see gh-6300
952 # - see gh-6300
954 pass
953 pass
955 except tokenize.TokenError as msg:
954 except tokenize.TokenError as msg:
956 _m = ("An unexpected error occurred while tokenizing input\n"
955 _m = ("An unexpected error occurred while tokenizing input\n"
957 "The following traceback may be corrupted or invalid\n"
956 "The following traceback may be corrupted or invalid\n"
958 "The error message is: %s\n" % msg)
957 "The error message is: %s\n" % msg)
959 error(_m)
958 error(_m)
960
959
961 # Join composite names (e.g. "dict.fromkeys")
960 # Join composite names (e.g. "dict.fromkeys")
962 names = ['.'.join(n) for n in names]
961 names = ['.'.join(n) for n in names]
963 # prune names list of duplicates, but keep the right order
962 # prune names list of duplicates, but keep the right order
964 unique_names = uniq_stable(names)
963 unique_names = uniq_stable(names)
965
964
966 # Start loop over vars
965 # Start loop over vars
967 lvals = []
966 lvals = []
968 if self.include_vars:
967 if self.include_vars:
969 for name_full in unique_names:
968 for name_full in unique_names:
970 name_base = name_full.split('.', 1)[0]
969 name_base = name_full.split('.', 1)[0]
971 if name_base in frame.f_code.co_varnames:
970 if name_base in frame.f_code.co_varnames:
972 if name_base in locals:
971 if name_base in locals:
973 try:
972 try:
974 value = repr(eval(name_full, locals))
973 value = repr(eval(name_full, locals))
975 except:
974 except:
976 value = undefined
975 value = undefined
977 else:
976 else:
978 value = undefined
977 value = undefined
979 name = tpl_local_var % name_full
978 name = tpl_local_var % name_full
980 else:
979 else:
981 if name_base in frame.f_globals:
980 if name_base in frame.f_globals:
982 try:
981 try:
983 value = repr(eval(name_full, frame.f_globals))
982 value = repr(eval(name_full, frame.f_globals))
984 except:
983 except:
985 value = undefined
984 value = undefined
986 else:
985 else:
987 value = undefined
986 value = undefined
988 name = tpl_global_var % name_full
987 name = tpl_global_var % name_full
989 lvals.append(tpl_name_val % (name, value))
988 lvals.append(tpl_name_val % (name, value))
990 if lvals:
989 if lvals:
991 lvals = '%s%s' % (indent, em_normal.join(lvals))
990 lvals = '%s%s' % (indent, em_normal.join(lvals))
992 else:
991 else:
993 lvals = ''
992 lvals = ''
994
993
995 level = '%s %s\n' % (link, call)
994 level = '%s %s\n' % (link, call)
996
995
997 if index is None:
996 if index is None:
998 return level
997 return level
999 else:
998 else:
1000 _line_format = PyColorize.Parser(style=col_scheme, parent=self).format2
999 _line_format = PyColorize.Parser(style=col_scheme, parent=self).format2
1001 return '%s%s' % (level, ''.join(
1000 return '%s%s' % (level, ''.join(
1002 _format_traceback_lines(lnum, index, lines, Colors, lvals,
1001 _format_traceback_lines(lnum, index, lines, Colors, lvals,
1003 _line_format)))
1002 _line_format)))
1004
1003
1005 def prepare_chained_exception_message(self, cause):
1004 def prepare_chained_exception_message(self, cause):
1006 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
1005 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
1007 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
1006 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
1008
1007
1009 if cause:
1008 if cause:
1010 message = [[direct_cause]]
1009 message = [[direct_cause]]
1011 else:
1010 else:
1012 message = [[exception_during_handling]]
1011 message = [[exception_during_handling]]
1013 return message
1012 return message
1014
1013
1015 def prepare_header(self, etype, long_version=False):
1014 def prepare_header(self, etype, long_version=False):
1016 colors = self.Colors # just a shorthand + quicker name lookup
1015 colors = self.Colors # just a shorthand + quicker name lookup
1017 colorsnormal = colors.Normal # used a lot
1016 colorsnormal = colors.Normal # used a lot
1018 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
1017 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
1019 width = min(75, get_terminal_size()[0])
1018 width = min(75, get_terminal_size()[0])
1020 if long_version:
1019 if long_version:
1021 # Header with the exception type, python version, and date
1020 # Header with the exception type, python version, and date
1022 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
1021 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
1023 date = time.ctime(time.time())
1022 date = time.ctime(time.time())
1024
1023
1025 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * width, colorsnormal,
1024 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * width, colorsnormal,
1026 exc, ' ' * (width - len(str(etype)) - len(pyver)),
1025 exc, ' ' * (width - len(str(etype)) - len(pyver)),
1027 pyver, date.rjust(width) )
1026 pyver, date.rjust(width) )
1028 head += "\nA problem occurred executing Python code. Here is the sequence of function" \
1027 head += "\nA problem occurred executing Python code. Here is the sequence of function" \
1029 "\ncalls leading up to the error, with the most recent (innermost) call last."
1028 "\ncalls leading up to the error, with the most recent (innermost) call last."
1030 else:
1029 else:
1031 # Simplified header
1030 # Simplified header
1032 head = '%s%s' % (exc, 'Traceback (most recent call last)'. \
1031 head = '%s%s' % (exc, 'Traceback (most recent call last)'. \
1033 rjust(width - len(str(etype))) )
1032 rjust(width - len(str(etype))) )
1034
1033
1035 return head
1034 return head
1036
1035
1037 def format_exception(self, etype, evalue):
1036 def format_exception(self, etype, evalue):
1038 colors = self.Colors # just a shorthand + quicker name lookup
1037 colors = self.Colors # just a shorthand + quicker name lookup
1039 colorsnormal = colors.Normal # used a lot
1038 colorsnormal = colors.Normal # used a lot
1040 indent = ' ' * INDENT_SIZE
1039 indent = ' ' * INDENT_SIZE
1041 # Get (safely) a string form of the exception info
1040 # Get (safely) a string form of the exception info
1042 try:
1041 try:
1043 etype_str, evalue_str = map(str, (etype, evalue))
1042 etype_str, evalue_str = map(str, (etype, evalue))
1044 except:
1043 except:
1045 # User exception is improperly defined.
1044 # User exception is improperly defined.
1046 etype, evalue = str, sys.exc_info()[:2]
1045 etype, evalue = str, sys.exc_info()[:2]
1047 etype_str, evalue_str = map(str, (etype, evalue))
1046 etype_str, evalue_str = map(str, (etype, evalue))
1048 # ... and format it
1047 # ... and format it
1049 return ['%s%s%s: %s' % (colors.excName, etype_str,
1048 return ['%s%s%s: %s' % (colors.excName, etype_str,
1050 colorsnormal, py3compat.cast_unicode(evalue_str))]
1049 colorsnormal, py3compat.cast_unicode(evalue_str))]
1051
1050
1052 def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset):
1051 def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset):
1053 """Formats the header, traceback and exception message for a single exception.
1052 """Formats the header, traceback and exception message for a single exception.
1054
1053
1055 This may be called multiple times by Python 3 exception chaining
1054 This may be called multiple times by Python 3 exception chaining
1056 (PEP 3134).
1055 (PEP 3134).
1057 """
1056 """
1058 # some locals
1057 # some locals
1059 orig_etype = etype
1058 orig_etype = etype
1060 try:
1059 try:
1061 etype = etype.__name__
1060 etype = etype.__name__
1062 except AttributeError:
1061 except AttributeError:
1063 pass
1062 pass
1064
1063
1065 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1064 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1066 head = self.prepare_header(etype, self.long_header)
1065 head = self.prepare_header(etype, self.long_header)
1067 records = self.get_records(etb, number_of_lines_of_context, tb_offset)
1066 records = self.get_records(etb, number_of_lines_of_context, tb_offset)
1068
1067
1069 if records is None:
1068 if records is None:
1070 return ""
1069 return ""
1071
1070
1072 last_unique, recursion_repeat = find_recursion(orig_etype, evalue, records)
1071 last_unique, recursion_repeat = find_recursion(orig_etype, evalue, records)
1073
1072
1074 frames = self.format_records(records, last_unique, recursion_repeat)
1073 frames = self.format_records(records, last_unique, recursion_repeat)
1075
1074
1076 formatted_exception = self.format_exception(etype, evalue)
1075 formatted_exception = self.format_exception(etype, evalue)
1077 if records:
1076 if records:
1078 filepath, lnum = records[-1][1:3]
1077 filepath, lnum = records[-1][1:3]
1079 filepath = os.path.abspath(filepath)
1078 filepath = os.path.abspath(filepath)
1080 ipinst = get_ipython()
1079 ipinst = get_ipython()
1081 if ipinst is not None:
1080 if ipinst is not None:
1082 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
1081 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
1083
1082
1084 return [[head] + frames + [''.join(formatted_exception[0])]]
1083 return [[head] + frames + [''.join(formatted_exception[0])]]
1085
1084
1086 def get_records(self, etb, number_of_lines_of_context, tb_offset):
1085 def get_records(self, etb, number_of_lines_of_context, tb_offset):
1087 try:
1086 try:
1088 # Try the default getinnerframes and Alex's: Alex's fixes some
1087 # Try the default getinnerframes and Alex's: Alex's fixes some
1089 # problems, but it generates empty tracebacks for console errors
1088 # problems, but it generates empty tracebacks for console errors
1090 # (5 blanks lines) where none should be returned.
1089 # (5 blanks lines) where none should be returned.
1091 return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset)
1090 return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset)
1092 except UnicodeDecodeError:
1091 except UnicodeDecodeError:
1093 # This can occur if a file's encoding magic comment is wrong.
1092 # This can occur if a file's encoding magic comment is wrong.
1094 # I can't see a way to recover without duplicating a bunch of code
1093 # I can't see a way to recover without duplicating a bunch of code
1095 # from the stdlib traceback module. --TK
1094 # from the stdlib traceback module. --TK
1096 error('\nUnicodeDecodeError while processing traceback.\n')
1095 error('\nUnicodeDecodeError while processing traceback.\n')
1097 return None
1096 return None
1098 except:
1097 except:
1099 # FIXME: I've been getting many crash reports from python 2.3
1098 # FIXME: I've been getting many crash reports from python 2.3
1100 # users, traceable to inspect.py. If I can find a small test-case
1099 # users, traceable to inspect.py. If I can find a small test-case
1101 # to reproduce this, I should either write a better workaround or
1100 # to reproduce this, I should either write a better workaround or
1102 # file a bug report against inspect (if that's the real problem).
1101 # file a bug report against inspect (if that's the real problem).
1103 # So far, I haven't been able to find an isolated example to
1102 # So far, I haven't been able to find an isolated example to
1104 # reproduce the problem.
1103 # reproduce the problem.
1105 inspect_error()
1104 inspect_error()
1106 traceback.print_exc(file=self.ostream)
1105 traceback.print_exc(file=self.ostream)
1107 info('\nUnfortunately, your original traceback can not be constructed.\n')
1106 info('\nUnfortunately, your original traceback can not be constructed.\n')
1108 return None
1107 return None
1109
1108
1110 def get_parts_of_chained_exception(self, evalue):
1109 def get_parts_of_chained_exception(self, evalue):
1111 def get_chained_exception(exception_value):
1110 def get_chained_exception(exception_value):
1112 cause = getattr(exception_value, '__cause__', None)
1111 cause = getattr(exception_value, '__cause__', None)
1113 if cause:
1112 if cause:
1114 return cause
1113 return cause
1115 if getattr(exception_value, '__suppress_context__', False):
1114 if getattr(exception_value, '__suppress_context__', False):
1116 return None
1115 return None
1117 return getattr(exception_value, '__context__', None)
1116 return getattr(exception_value, '__context__', None)
1118
1117
1119 chained_evalue = get_chained_exception(evalue)
1118 chained_evalue = get_chained_exception(evalue)
1120
1119
1121 if chained_evalue:
1120 if chained_evalue:
1122 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
1121 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
1123
1122
1124 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
1123 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
1125 number_of_lines_of_context=5):
1124 number_of_lines_of_context=5):
1126 """Return a nice text document describing the traceback."""
1125 """Return a nice text document describing the traceback."""
1127
1126
1128 formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
1127 formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
1129 tb_offset)
1128 tb_offset)
1130
1129
1131 colors = self.Colors # just a shorthand + quicker name lookup
1130 colors = self.Colors # just a shorthand + quicker name lookup
1132 colorsnormal = colors.Normal # used a lot
1131 colorsnormal = colors.Normal # used a lot
1133 head = '%s%s%s' % (colors.topline, '-' * min(75, get_terminal_size()[0]), colorsnormal)
1132 head = '%s%s%s' % (colors.topline, '-' * min(75, get_terminal_size()[0]), colorsnormal)
1134 structured_traceback_parts = [head]
1133 structured_traceback_parts = [head]
1135 if py3compat.PY3:
1134 if py3compat.PY3:
1136 chained_exceptions_tb_offset = 0
1135 chained_exceptions_tb_offset = 0
1137 lines_of_context = 3
1136 lines_of_context = 3
1138 formatted_exceptions = formatted_exception
1137 formatted_exceptions = formatted_exception
1139 exception = self.get_parts_of_chained_exception(evalue)
1138 exception = self.get_parts_of_chained_exception(evalue)
1140 if exception:
1139 if exception:
1141 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1140 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1142 etype, evalue, etb = exception
1141 etype, evalue, etb = exception
1143 else:
1142 else:
1144 evalue = None
1143 evalue = None
1145 chained_exc_ids = set()
1144 chained_exc_ids = set()
1146 while evalue:
1145 while evalue:
1147 formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context,
1146 formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context,
1148 chained_exceptions_tb_offset)
1147 chained_exceptions_tb_offset)
1149 exception = self.get_parts_of_chained_exception(evalue)
1148 exception = self.get_parts_of_chained_exception(evalue)
1150
1149
1151 if exception and not id(exception[1]) in chained_exc_ids:
1150 if exception and not id(exception[1]) in chained_exc_ids:
1152 chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop
1151 chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop
1153 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1152 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1154 etype, evalue, etb = exception
1153 etype, evalue, etb = exception
1155 else:
1154 else:
1156 evalue = None
1155 evalue = None
1157
1156
1158 # we want to see exceptions in a reversed order:
1157 # we want to see exceptions in a reversed order:
1159 # the first exception should be on top
1158 # the first exception should be on top
1160 for formatted_exception in reversed(formatted_exceptions):
1159 for formatted_exception in reversed(formatted_exceptions):
1161 structured_traceback_parts += formatted_exception
1160 structured_traceback_parts += formatted_exception
1162 else:
1161 else:
1163 structured_traceback_parts += formatted_exception[0]
1162 structured_traceback_parts += formatted_exception[0]
1164
1163
1165 return structured_traceback_parts
1164 return structured_traceback_parts
1166
1165
1167 def debugger(self, force=False):
1166 def debugger(self, force=False):
1168 """Call up the pdb debugger if desired, always clean up the tb
1167 """Call up the pdb debugger if desired, always clean up the tb
1169 reference.
1168 reference.
1170
1169
1171 Keywords:
1170 Keywords:
1172
1171
1173 - force(False): by default, this routine checks the instance call_pdb
1172 - force(False): by default, this routine checks the instance call_pdb
1174 flag and does not actually invoke the debugger if the flag is false.
1173 flag and does not actually invoke the debugger if the flag is false.
1175 The 'force' option forces the debugger to activate even if the flag
1174 The 'force' option forces the debugger to activate even if the flag
1176 is false.
1175 is false.
1177
1176
1178 If the call_pdb flag is set, the pdb interactive debugger is
1177 If the call_pdb flag is set, the pdb interactive debugger is
1179 invoked. In all cases, the self.tb reference to the current traceback
1178 invoked. In all cases, the self.tb reference to the current traceback
1180 is deleted to prevent lingering references which hamper memory
1179 is deleted to prevent lingering references which hamper memory
1181 management.
1180 management.
1182
1181
1183 Note that each call to pdb() does an 'import readline', so if your app
1182 Note that each call to pdb() does an 'import readline', so if your app
1184 requires a special setup for the readline completers, you'll have to
1183 requires a special setup for the readline completers, you'll have to
1185 fix that by hand after invoking the exception handler."""
1184 fix that by hand after invoking the exception handler."""
1186
1185
1187 if force or self.call_pdb:
1186 if force or self.call_pdb:
1188 if self.pdb is None:
1187 if self.pdb is None:
1189 self.pdb = self.debugger_cls()
1188 self.pdb = self.debugger_cls()
1190 # the system displayhook may have changed, restore the original
1189 # the system displayhook may have changed, restore the original
1191 # for pdb
1190 # for pdb
1192 display_trap = DisplayTrap(hook=sys.__displayhook__)
1191 display_trap = DisplayTrap(hook=sys.__displayhook__)
1193 with display_trap:
1192 with display_trap:
1194 self.pdb.reset()
1193 self.pdb.reset()
1195 # Find the right frame so we don't pop up inside ipython itself
1194 # Find the right frame so we don't pop up inside ipython itself
1196 if hasattr(self, 'tb') and self.tb is not None:
1195 if hasattr(self, 'tb') and self.tb is not None:
1197 etb = self.tb
1196 etb = self.tb
1198 else:
1197 else:
1199 etb = self.tb = sys.last_traceback
1198 etb = self.tb = sys.last_traceback
1200 while self.tb is not None and self.tb.tb_next is not None:
1199 while self.tb is not None and self.tb.tb_next is not None:
1201 self.tb = self.tb.tb_next
1200 self.tb = self.tb.tb_next
1202 if etb and etb.tb_next:
1201 if etb and etb.tb_next:
1203 etb = etb.tb_next
1202 etb = etb.tb_next
1204 self.pdb.botframe = etb.tb_frame
1203 self.pdb.botframe = etb.tb_frame
1205 self.pdb.interaction(self.tb.tb_frame, self.tb)
1204 self.pdb.interaction(self.tb.tb_frame, self.tb)
1206
1205
1207 if hasattr(self, 'tb'):
1206 if hasattr(self, 'tb'):
1208 del self.tb
1207 del self.tb
1209
1208
1210 def handler(self, info=None):
1209 def handler(self, info=None):
1211 (etype, evalue, etb) = info or sys.exc_info()
1210 (etype, evalue, etb) = info or sys.exc_info()
1212 self.tb = etb
1211 self.tb = etb
1213 ostream = self.ostream
1212 ostream = self.ostream
1214 ostream.flush()
1213 ostream.flush()
1215 ostream.write(self.text(etype, evalue, etb))
1214 ostream.write(self.text(etype, evalue, etb))
1216 ostream.write('\n')
1215 ostream.write('\n')
1217 ostream.flush()
1216 ostream.flush()
1218
1217
1219 # Changed so an instance can just be called as VerboseTB_inst() and print
1218 # Changed so an instance can just be called as VerboseTB_inst() and print
1220 # out the right info on its own.
1219 # out the right info on its own.
1221 def __call__(self, etype=None, evalue=None, etb=None):
1220 def __call__(self, etype=None, evalue=None, etb=None):
1222 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1221 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1223 if etb is None:
1222 if etb is None:
1224 self.handler()
1223 self.handler()
1225 else:
1224 else:
1226 self.handler((etype, evalue, etb))
1225 self.handler((etype, evalue, etb))
1227 try:
1226 try:
1228 self.debugger()
1227 self.debugger()
1229 except KeyboardInterrupt:
1228 except KeyboardInterrupt:
1230 print("\nKeyboardInterrupt")
1229 print("\nKeyboardInterrupt")
1231
1230
1232
1231
1233 #----------------------------------------------------------------------------
1232 #----------------------------------------------------------------------------
1234 class FormattedTB(VerboseTB, ListTB):
1233 class FormattedTB(VerboseTB, ListTB):
1235 """Subclass ListTB but allow calling with a traceback.
1234 """Subclass ListTB but allow calling with a traceback.
1236
1235
1237 It can thus be used as a sys.excepthook for Python > 2.1.
1236 It can thus be used as a sys.excepthook for Python > 2.1.
1238
1237
1239 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1238 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1240
1239
1241 Allows a tb_offset to be specified. This is useful for situations where
1240 Allows a tb_offset to be specified. This is useful for situations where
1242 one needs to remove a number of topmost frames from the traceback (such as
1241 one needs to remove a number of topmost frames from the traceback (such as
1243 occurs with python programs that themselves execute other python code,
1242 occurs with python programs that themselves execute other python code,
1244 like Python shells). """
1243 like Python shells). """
1245
1244
1246 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1245 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1247 ostream=None,
1246 ostream=None,
1248 tb_offset=0, long_header=False, include_vars=False,
1247 tb_offset=0, long_header=False, include_vars=False,
1249 check_cache=None, debugger_cls=None,
1248 check_cache=None, debugger_cls=None,
1250 parent=None, config=None):
1249 parent=None, config=None):
1251
1250
1252 # NEVER change the order of this list. Put new modes at the end:
1251 # NEVER change the order of this list. Put new modes at the end:
1253 self.valid_modes = ['Plain', 'Context', 'Verbose']
1252 self.valid_modes = ['Plain', 'Context', 'Verbose']
1254 self.verbose_modes = self.valid_modes[1:3]
1253 self.verbose_modes = self.valid_modes[1:3]
1255
1254
1256 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1255 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1257 ostream=ostream, tb_offset=tb_offset,
1256 ostream=ostream, tb_offset=tb_offset,
1258 long_header=long_header, include_vars=include_vars,
1257 long_header=long_header, include_vars=include_vars,
1259 check_cache=check_cache, debugger_cls=debugger_cls,
1258 check_cache=check_cache, debugger_cls=debugger_cls,
1260 parent=parent, config=config)
1259 parent=parent, config=config)
1261
1260
1262 # Different types of tracebacks are joined with different separators to
1261 # Different types of tracebacks are joined with different separators to
1263 # form a single string. They are taken from this dict
1262 # form a single string. They are taken from this dict
1264 self._join_chars = dict(Plain='', Context='\n', Verbose='\n')
1263 self._join_chars = dict(Plain='', Context='\n', Verbose='\n')
1265 # set_mode also sets the tb_join_char attribute
1264 # set_mode also sets the tb_join_char attribute
1266 self.set_mode(mode)
1265 self.set_mode(mode)
1267
1266
1268 def _extract_tb(self, tb):
1267 def _extract_tb(self, tb):
1269 if tb:
1268 if tb:
1270 return traceback.extract_tb(tb)
1269 return traceback.extract_tb(tb)
1271 else:
1270 else:
1272 return None
1271 return None
1273
1272
1274 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
1273 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
1275 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1274 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1276 mode = self.mode
1275 mode = self.mode
1277 if mode in self.verbose_modes:
1276 if mode in self.verbose_modes:
1278 # Verbose modes need a full traceback
1277 # Verbose modes need a full traceback
1279 return VerboseTB.structured_traceback(
1278 return VerboseTB.structured_traceback(
1280 self, etype, value, tb, tb_offset, number_of_lines_of_context
1279 self, etype, value, tb, tb_offset, number_of_lines_of_context
1281 )
1280 )
1282 else:
1281 else:
1283 # We must check the source cache because otherwise we can print
1282 # We must check the source cache because otherwise we can print
1284 # out-of-date source code.
1283 # out-of-date source code.
1285 self.check_cache()
1284 self.check_cache()
1286 # Now we can extract and format the exception
1285 # Now we can extract and format the exception
1287 elist = self._extract_tb(tb)
1286 elist = self._extract_tb(tb)
1288 return ListTB.structured_traceback(
1287 return ListTB.structured_traceback(
1289 self, etype, value, elist, tb_offset, number_of_lines_of_context
1288 self, etype, value, elist, tb_offset, number_of_lines_of_context
1290 )
1289 )
1291
1290
1292 def stb2text(self, stb):
1291 def stb2text(self, stb):
1293 """Convert a structured traceback (a list) to a string."""
1292 """Convert a structured traceback (a list) to a string."""
1294 return self.tb_join_char.join(stb)
1293 return self.tb_join_char.join(stb)
1295
1294
1296
1295
1297 def set_mode(self, mode=None):
1296 def set_mode(self, mode=None):
1298 """Switch to the desired mode.
1297 """Switch to the desired mode.
1299
1298
1300 If mode is not specified, cycles through the available modes."""
1299 If mode is not specified, cycles through the available modes."""
1301
1300
1302 if not mode:
1301 if not mode:
1303 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
1302 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
1304 len(self.valid_modes)
1303 len(self.valid_modes)
1305 self.mode = self.valid_modes[new_idx]
1304 self.mode = self.valid_modes[new_idx]
1306 elif mode not in self.valid_modes:
1305 elif mode not in self.valid_modes:
1307 raise ValueError('Unrecognized mode in FormattedTB: <' + mode + '>\n'
1306 raise ValueError('Unrecognized mode in FormattedTB: <' + mode + '>\n'
1308 'Valid modes: ' + str(self.valid_modes))
1307 'Valid modes: ' + str(self.valid_modes))
1309 else:
1308 else:
1310 self.mode = mode
1309 self.mode = mode
1311 # include variable details only in 'Verbose' mode
1310 # include variable details only in 'Verbose' mode
1312 self.include_vars = (self.mode == self.valid_modes[2])
1311 self.include_vars = (self.mode == self.valid_modes[2])
1313 # Set the join character for generating text tracebacks
1312 # Set the join character for generating text tracebacks
1314 self.tb_join_char = self._join_chars[self.mode]
1313 self.tb_join_char = self._join_chars[self.mode]
1315
1314
1316 # some convenient shortcuts
1315 # some convenient shortcuts
1317 def plain(self):
1316 def plain(self):
1318 self.set_mode(self.valid_modes[0])
1317 self.set_mode(self.valid_modes[0])
1319
1318
1320 def context(self):
1319 def context(self):
1321 self.set_mode(self.valid_modes[1])
1320 self.set_mode(self.valid_modes[1])
1322
1321
1323 def verbose(self):
1322 def verbose(self):
1324 self.set_mode(self.valid_modes[2])
1323 self.set_mode(self.valid_modes[2])
1325
1324
1326
1325
1327 #----------------------------------------------------------------------------
1326 #----------------------------------------------------------------------------
1328 class AutoFormattedTB(FormattedTB):
1327 class AutoFormattedTB(FormattedTB):
1329 """A traceback printer which can be called on the fly.
1328 """A traceback printer which can be called on the fly.
1330
1329
1331 It will find out about exceptions by itself.
1330 It will find out about exceptions by itself.
1332
1331
1333 A brief example::
1332 A brief example::
1334
1333
1335 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1334 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1336 try:
1335 try:
1337 ...
1336 ...
1338 except:
1337 except:
1339 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1338 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1340 """
1339 """
1341
1340
1342 def __call__(self, etype=None, evalue=None, etb=None,
1341 def __call__(self, etype=None, evalue=None, etb=None,
1343 out=None, tb_offset=None):
1342 out=None, tb_offset=None):
1344 """Print out a formatted exception traceback.
1343 """Print out a formatted exception traceback.
1345
1344
1346 Optional arguments:
1345 Optional arguments:
1347 - out: an open file-like object to direct output to.
1346 - out: an open file-like object to direct output to.
1348
1347
1349 - tb_offset: the number of frames to skip over in the stack, on a
1348 - tb_offset: the number of frames to skip over in the stack, on a
1350 per-call basis (this overrides temporarily the instance's tb_offset
1349 per-call basis (this overrides temporarily the instance's tb_offset
1351 given at initialization time. """
1350 given at initialization time. """
1352
1351
1353 if out is None:
1352 if out is None:
1354 out = self.ostream
1353 out = self.ostream
1355 out.flush()
1354 out.flush()
1356 out.write(self.text(etype, evalue, etb, tb_offset))
1355 out.write(self.text(etype, evalue, etb, tb_offset))
1357 out.write('\n')
1356 out.write('\n')
1358 out.flush()
1357 out.flush()
1359 # FIXME: we should remove the auto pdb behavior from here and leave
1358 # FIXME: we should remove the auto pdb behavior from here and leave
1360 # that to the clients.
1359 # that to the clients.
1361 try:
1360 try:
1362 self.debugger()
1361 self.debugger()
1363 except KeyboardInterrupt:
1362 except KeyboardInterrupt:
1364 print("\nKeyboardInterrupt")
1363 print("\nKeyboardInterrupt")
1365
1364
1366 def structured_traceback(self, etype=None, value=None, tb=None,
1365 def structured_traceback(self, etype=None, value=None, tb=None,
1367 tb_offset=None, number_of_lines_of_context=5):
1366 tb_offset=None, number_of_lines_of_context=5):
1368 if etype is None:
1367 if etype is None:
1369 etype, value, tb = sys.exc_info()
1368 etype, value, tb = sys.exc_info()
1370 self.tb = tb
1369 self.tb = tb
1371 return FormattedTB.structured_traceback(
1370 return FormattedTB.structured_traceback(
1372 self, etype, value, tb, tb_offset, number_of_lines_of_context)
1371 self, etype, value, tb, tb_offset, number_of_lines_of_context)
1373
1372
1374
1373
1375 #---------------------------------------------------------------------------
1374 #---------------------------------------------------------------------------
1376
1375
1377 # A simple class to preserve Nathan's original functionality.
1376 # A simple class to preserve Nathan's original functionality.
1378 class ColorTB(FormattedTB):
1377 class ColorTB(FormattedTB):
1379 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1378 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1380
1379
1381 def __init__(self, color_scheme='Linux', call_pdb=0, **kwargs):
1380 def __init__(self, color_scheme='Linux', call_pdb=0, **kwargs):
1382 FormattedTB.__init__(self, color_scheme=color_scheme,
1381 FormattedTB.__init__(self, color_scheme=color_scheme,
1383 call_pdb=call_pdb, **kwargs)
1382 call_pdb=call_pdb, **kwargs)
1384
1383
1385
1384
1386 class SyntaxTB(ListTB):
1385 class SyntaxTB(ListTB):
1387 """Extension which holds some state: the last exception value"""
1386 """Extension which holds some state: the last exception value"""
1388
1387
1389 def __init__(self, color_scheme='NoColor', parent=None, config=None):
1388 def __init__(self, color_scheme='NoColor', parent=None, config=None):
1390 ListTB.__init__(self, color_scheme, parent=parent, config=config)
1389 ListTB.__init__(self, color_scheme, parent=parent, config=config)
1391 self.last_syntax_error = None
1390 self.last_syntax_error = None
1392
1391
1393 def __call__(self, etype, value, elist):
1392 def __call__(self, etype, value, elist):
1394 self.last_syntax_error = value
1393 self.last_syntax_error = value
1395
1394
1396 ListTB.__call__(self, etype, value, elist)
1395 ListTB.__call__(self, etype, value, elist)
1397
1396
1398 def structured_traceback(self, etype, value, elist, tb_offset=None,
1397 def structured_traceback(self, etype, value, elist, tb_offset=None,
1399 context=5):
1398 context=5):
1400 # If the source file has been edited, the line in the syntax error can
1399 # If the source file has been edited, the line in the syntax error can
1401 # be wrong (retrieved from an outdated cache). This replaces it with
1400 # be wrong (retrieved from an outdated cache). This replaces it with
1402 # the current value.
1401 # the current value.
1403 if isinstance(value, SyntaxError) \
1402 if isinstance(value, SyntaxError) \
1404 and isinstance(value.filename, str) \
1403 and isinstance(value.filename, str) \
1405 and isinstance(value.lineno, int):
1404 and isinstance(value.lineno, int):
1406 linecache.checkcache(value.filename)
1405 linecache.checkcache(value.filename)
1407 newtext = linecache.getline(value.filename, value.lineno)
1406 newtext = linecache.getline(value.filename, value.lineno)
1408 if newtext:
1407 if newtext:
1409 value.text = newtext
1408 value.text = newtext
1410 self.last_syntax_error = value
1409 self.last_syntax_error = value
1411 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1410 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1412 tb_offset=tb_offset, context=context)
1411 tb_offset=tb_offset, context=context)
1413
1412
1414 def clear_err_state(self):
1413 def clear_err_state(self):
1415 """Return the current error state and clear it"""
1414 """Return the current error state and clear it"""
1416 e = self.last_syntax_error
1415 e = self.last_syntax_error
1417 self.last_syntax_error = None
1416 self.last_syntax_error = None
1418 return e
1417 return e
1419
1418
1420 def stb2text(self, stb):
1419 def stb2text(self, stb):
1421 """Convert a structured traceback (a list) to a string."""
1420 """Convert a structured traceback (a list) to a string."""
1422 return ''.join(stb)
1421 return ''.join(stb)
1423
1422
1424
1423
1425 # some internal-use functions
1424 # some internal-use functions
1426 def text_repr(value):
1425 def text_repr(value):
1427 """Hopefully pretty robust repr equivalent."""
1426 """Hopefully pretty robust repr equivalent."""
1428 # this is pretty horrible but should always return *something*
1427 # this is pretty horrible but should always return *something*
1429 try:
1428 try:
1430 return pydoc.text.repr(value)
1429 return pydoc.text.repr(value)
1431 except KeyboardInterrupt:
1430 except KeyboardInterrupt:
1432 raise
1431 raise
1433 except:
1432 except:
1434 try:
1433 try:
1435 return repr(value)
1434 return repr(value)
1436 except KeyboardInterrupt:
1435 except KeyboardInterrupt:
1437 raise
1436 raise
1438 except:
1437 except:
1439 try:
1438 try:
1440 # all still in an except block so we catch
1439 # all still in an except block so we catch
1441 # getattr raising
1440 # getattr raising
1442 name = getattr(value, '__name__', None)
1441 name = getattr(value, '__name__', None)
1443 if name:
1442 if name:
1444 # ick, recursion
1443 # ick, recursion
1445 return text_repr(name)
1444 return text_repr(name)
1446 klass = getattr(value, '__class__', None)
1445 klass = getattr(value, '__class__', None)
1447 if klass:
1446 if klass:
1448 return '%s instance' % text_repr(klass)
1447 return '%s instance' % text_repr(klass)
1449 except KeyboardInterrupt:
1448 except KeyboardInterrupt:
1450 raise
1449 raise
1451 except:
1450 except:
1452 return 'UNRECOVERABLE REPR FAILURE'
1451 return 'UNRECOVERABLE REPR FAILURE'
1453
1452
1454
1453
1455 def eqrepr(value, repr=text_repr):
1454 def eqrepr(value, repr=text_repr):
1456 return '=%s' % repr(value)
1455 return '=%s' % repr(value)
1457
1456
1458
1457
1459 def nullrepr(value, repr=text_repr):
1458 def nullrepr(value, repr=text_repr):
1460 return ''
1459 return ''
@@ -1,860 +1,859 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Python advanced pretty printer. This pretty printer is intended to
3 Python advanced pretty printer. This pretty printer is intended to
4 replace the old `pprint` python module which does not allow developers
4 replace the old `pprint` python module which does not allow developers
5 to provide their own pretty print callbacks.
5 to provide their own pretty print callbacks.
6
6
7 This module is based on ruby's `prettyprint.rb` library by `Tanaka Akira`.
7 This module is based on ruby's `prettyprint.rb` library by `Tanaka Akira`.
8
8
9
9
10 Example Usage
10 Example Usage
11 -------------
11 -------------
12
12
13 To directly print the representation of an object use `pprint`::
13 To directly print the representation of an object use `pprint`::
14
14
15 from pretty import pprint
15 from pretty import pprint
16 pprint(complex_object)
16 pprint(complex_object)
17
17
18 To get a string of the output use `pretty`::
18 To get a string of the output use `pretty`::
19
19
20 from pretty import pretty
20 from pretty import pretty
21 string = pretty(complex_object)
21 string = pretty(complex_object)
22
22
23
23
24 Extending
24 Extending
25 ---------
25 ---------
26
26
27 The pretty library allows developers to add pretty printing rules for their
27 The pretty library allows developers to add pretty printing rules for their
28 own objects. This process is straightforward. All you have to do is to
28 own objects. This process is straightforward. All you have to do is to
29 add a `_repr_pretty_` method to your object and call the methods on the
29 add a `_repr_pretty_` method to your object and call the methods on the
30 pretty printer passed::
30 pretty printer passed::
31
31
32 class MyObject(object):
32 class MyObject(object):
33
33
34 def _repr_pretty_(self, p, cycle):
34 def _repr_pretty_(self, p, cycle):
35 ...
35 ...
36
36
37 Here is an example implementation of a `_repr_pretty_` method for a list
37 Here is an example implementation of a `_repr_pretty_` method for a list
38 subclass::
38 subclass::
39
39
40 class MyList(list):
40 class MyList(list):
41
41
42 def _repr_pretty_(self, p, cycle):
42 def _repr_pretty_(self, p, cycle):
43 if cycle:
43 if cycle:
44 p.text('MyList(...)')
44 p.text('MyList(...)')
45 else:
45 else:
46 with p.group(8, 'MyList([', '])'):
46 with p.group(8, 'MyList([', '])'):
47 for idx, item in enumerate(self):
47 for idx, item in enumerate(self):
48 if idx:
48 if idx:
49 p.text(',')
49 p.text(',')
50 p.breakable()
50 p.breakable()
51 p.pretty(item)
51 p.pretty(item)
52
52
53 The `cycle` parameter is `True` if pretty detected a cycle. You *have* to
53 The `cycle` parameter is `True` if pretty detected a cycle. You *have* to
54 react to that or the result is an infinite loop. `p.text()` just adds
54 react to that or the result is an infinite loop. `p.text()` just adds
55 non breaking text to the output, `p.breakable()` either adds a whitespace
55 non breaking text to the output, `p.breakable()` either adds a whitespace
56 or breaks here. If you pass it an argument it's used instead of the
56 or breaks here. If you pass it an argument it's used instead of the
57 default space. `p.pretty` prettyprints another object using the pretty print
57 default space. `p.pretty` prettyprints another object using the pretty print
58 method.
58 method.
59
59
60 The first parameter to the `group` function specifies the extra indentation
60 The first parameter to the `group` function specifies the extra indentation
61 of the next line. In this example the next item will either be on the same
61 of the next line. In this example the next item will either be on the same
62 line (if the items are short enough) or aligned with the right edge of the
62 line (if the items are short enough) or aligned with the right edge of the
63 opening bracket of `MyList`.
63 opening bracket of `MyList`.
64
64
65 If you just want to indent something you can use the group function
65 If you just want to indent something you can use the group function
66 without open / close parameters. You can also use this code::
66 without open / close parameters. You can also use this code::
67
67
68 with p.indent(2):
68 with p.indent(2):
69 ...
69 ...
70
70
71 Inheritance diagram:
71 Inheritance diagram:
72
72
73 .. inheritance-diagram:: IPython.lib.pretty
73 .. inheritance-diagram:: IPython.lib.pretty
74 :parts: 3
74 :parts: 3
75
75
76 :copyright: 2007 by Armin Ronacher.
76 :copyright: 2007 by Armin Ronacher.
77 Portions (c) 2009 by Robert Kern.
77 Portions (c) 2009 by Robert Kern.
78 :license: BSD License.
78 :license: BSD License.
79 """
79 """
80 from contextlib import contextmanager
80 from contextlib import contextmanager
81 import sys
81 import sys
82 import types
82 import types
83 import re
83 import re
84 import datetime
84 import datetime
85 from collections import deque
85 from collections import deque
86 from io import StringIO
86 from io import StringIO
87 from warnings import warn
87 from warnings import warn
88
88
89 from IPython.utils.decorators import undoc
89 from IPython.utils.decorators import undoc
90 from IPython.utils.py3compat import PYPY, cast_unicode
90 from IPython.utils.py3compat import PYPY
91 from IPython.utils.encoding import get_stream_enc
92
91
93
92
94 __all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter',
93 __all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter',
95 'for_type', 'for_type_by_name']
94 'for_type', 'for_type_by_name']
96
95
97
96
98 MAX_SEQ_LENGTH = 1000
97 MAX_SEQ_LENGTH = 1000
99 _re_pattern_type = type(re.compile(''))
98 _re_pattern_type = type(re.compile(''))
100
99
101 def _safe_getattr(obj, attr, default=None):
100 def _safe_getattr(obj, attr, default=None):
102 """Safe version of getattr.
101 """Safe version of getattr.
103
102
104 Same as getattr, but will return ``default`` on any Exception,
103 Same as getattr, but will return ``default`` on any Exception,
105 rather than raising.
104 rather than raising.
106 """
105 """
107 try:
106 try:
108 return getattr(obj, attr, default)
107 return getattr(obj, attr, default)
109 except Exception:
108 except Exception:
110 return default
109 return default
111
110
112 @undoc
111 @undoc
113 class CUnicodeIO(StringIO):
112 class CUnicodeIO(StringIO):
114 def __init__(self, *args, **kwargs):
113 def __init__(self, *args, **kwargs):
115 super().__init__(*args, **kwargs)
114 super().__init__(*args, **kwargs)
116 warn(("CUnicodeIO is deprecated since IPython 6.0. "
115 warn(("CUnicodeIO is deprecated since IPython 6.0. "
117 "Please use io.StringIO instead."),
116 "Please use io.StringIO instead."),
118 DeprecationWarning, stacklevel=2)
117 DeprecationWarning, stacklevel=2)
119
118
120 def pretty(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
119 def pretty(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
121 """
120 """
122 Pretty print the object's representation.
121 Pretty print the object's representation.
123 """
122 """
124 stream = StringIO()
123 stream = StringIO()
125 printer = RepresentationPrinter(stream, verbose, max_width, newline, max_seq_length=max_seq_length)
124 printer = RepresentationPrinter(stream, verbose, max_width, newline, max_seq_length=max_seq_length)
126 printer.pretty(obj)
125 printer.pretty(obj)
127 printer.flush()
126 printer.flush()
128 return stream.getvalue()
127 return stream.getvalue()
129
128
130
129
131 def pprint(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
130 def pprint(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
132 """
131 """
133 Like `pretty` but print to stdout.
132 Like `pretty` but print to stdout.
134 """
133 """
135 printer = RepresentationPrinter(sys.stdout, verbose, max_width, newline, max_seq_length=max_seq_length)
134 printer = RepresentationPrinter(sys.stdout, verbose, max_width, newline, max_seq_length=max_seq_length)
136 printer.pretty(obj)
135 printer.pretty(obj)
137 printer.flush()
136 printer.flush()
138 sys.stdout.write(newline)
137 sys.stdout.write(newline)
139 sys.stdout.flush()
138 sys.stdout.flush()
140
139
141 class _PrettyPrinterBase(object):
140 class _PrettyPrinterBase(object):
142
141
143 @contextmanager
142 @contextmanager
144 def indent(self, indent):
143 def indent(self, indent):
145 """with statement support for indenting/dedenting."""
144 """with statement support for indenting/dedenting."""
146 self.indentation += indent
145 self.indentation += indent
147 try:
146 try:
148 yield
147 yield
149 finally:
148 finally:
150 self.indentation -= indent
149 self.indentation -= indent
151
150
152 @contextmanager
151 @contextmanager
153 def group(self, indent=0, open='', close=''):
152 def group(self, indent=0, open='', close=''):
154 """like begin_group / end_group but for the with statement."""
153 """like begin_group / end_group but for the with statement."""
155 self.begin_group(indent, open)
154 self.begin_group(indent, open)
156 try:
155 try:
157 yield
156 yield
158 finally:
157 finally:
159 self.end_group(indent, close)
158 self.end_group(indent, close)
160
159
161 class PrettyPrinter(_PrettyPrinterBase):
160 class PrettyPrinter(_PrettyPrinterBase):
162 """
161 """
163 Baseclass for the `RepresentationPrinter` prettyprinter that is used to
162 Baseclass for the `RepresentationPrinter` prettyprinter that is used to
164 generate pretty reprs of objects. Contrary to the `RepresentationPrinter`
163 generate pretty reprs of objects. Contrary to the `RepresentationPrinter`
165 this printer knows nothing about the default pprinters or the `_repr_pretty_`
164 this printer knows nothing about the default pprinters or the `_repr_pretty_`
166 callback method.
165 callback method.
167 """
166 """
168
167
169 def __init__(self, output, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
168 def __init__(self, output, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
170 self.output = output
169 self.output = output
171 self.max_width = max_width
170 self.max_width = max_width
172 self.newline = newline
171 self.newline = newline
173 self.max_seq_length = max_seq_length
172 self.max_seq_length = max_seq_length
174 self.output_width = 0
173 self.output_width = 0
175 self.buffer_width = 0
174 self.buffer_width = 0
176 self.buffer = deque()
175 self.buffer = deque()
177
176
178 root_group = Group(0)
177 root_group = Group(0)
179 self.group_stack = [root_group]
178 self.group_stack = [root_group]
180 self.group_queue = GroupQueue(root_group)
179 self.group_queue = GroupQueue(root_group)
181 self.indentation = 0
180 self.indentation = 0
182
181
183 def _break_outer_groups(self):
182 def _break_outer_groups(self):
184 while self.max_width < self.output_width + self.buffer_width:
183 while self.max_width < self.output_width + self.buffer_width:
185 group = self.group_queue.deq()
184 group = self.group_queue.deq()
186 if not group:
185 if not group:
187 return
186 return
188 while group.breakables:
187 while group.breakables:
189 x = self.buffer.popleft()
188 x = self.buffer.popleft()
190 self.output_width = x.output(self.output, self.output_width)
189 self.output_width = x.output(self.output, self.output_width)
191 self.buffer_width -= x.width
190 self.buffer_width -= x.width
192 while self.buffer and isinstance(self.buffer[0], Text):
191 while self.buffer and isinstance(self.buffer[0], Text):
193 x = self.buffer.popleft()
192 x = self.buffer.popleft()
194 self.output_width = x.output(self.output, self.output_width)
193 self.output_width = x.output(self.output, self.output_width)
195 self.buffer_width -= x.width
194 self.buffer_width -= x.width
196
195
197 def text(self, obj):
196 def text(self, obj):
198 """Add literal text to the output."""
197 """Add literal text to the output."""
199 width = len(obj)
198 width = len(obj)
200 if self.buffer:
199 if self.buffer:
201 text = self.buffer[-1]
200 text = self.buffer[-1]
202 if not isinstance(text, Text):
201 if not isinstance(text, Text):
203 text = Text()
202 text = Text()
204 self.buffer.append(text)
203 self.buffer.append(text)
205 text.add(obj, width)
204 text.add(obj, width)
206 self.buffer_width += width
205 self.buffer_width += width
207 self._break_outer_groups()
206 self._break_outer_groups()
208 else:
207 else:
209 self.output.write(obj)
208 self.output.write(obj)
210 self.output_width += width
209 self.output_width += width
211
210
212 def breakable(self, sep=' '):
211 def breakable(self, sep=' '):
213 """
212 """
214 Add a breakable separator to the output. This does not mean that it
213 Add a breakable separator to the output. This does not mean that it
215 will automatically break here. If no breaking on this position takes
214 will automatically break here. If no breaking on this position takes
216 place the `sep` is inserted which default to one space.
215 place the `sep` is inserted which default to one space.
217 """
216 """
218 width = len(sep)
217 width = len(sep)
219 group = self.group_stack[-1]
218 group = self.group_stack[-1]
220 if group.want_break:
219 if group.want_break:
221 self.flush()
220 self.flush()
222 self.output.write(self.newline)
221 self.output.write(self.newline)
223 self.output.write(' ' * self.indentation)
222 self.output.write(' ' * self.indentation)
224 self.output_width = self.indentation
223 self.output_width = self.indentation
225 self.buffer_width = 0
224 self.buffer_width = 0
226 else:
225 else:
227 self.buffer.append(Breakable(sep, width, self))
226 self.buffer.append(Breakable(sep, width, self))
228 self.buffer_width += width
227 self.buffer_width += width
229 self._break_outer_groups()
228 self._break_outer_groups()
230
229
231 def break_(self):
230 def break_(self):
232 """
231 """
233 Explicitly insert a newline into the output, maintaining correct indentation.
232 Explicitly insert a newline into the output, maintaining correct indentation.
234 """
233 """
235 self.flush()
234 self.flush()
236 self.output.write(self.newline)
235 self.output.write(self.newline)
237 self.output.write(' ' * self.indentation)
236 self.output.write(' ' * self.indentation)
238 self.output_width = self.indentation
237 self.output_width = self.indentation
239 self.buffer_width = 0
238 self.buffer_width = 0
240
239
241
240
242 def begin_group(self, indent=0, open=''):
241 def begin_group(self, indent=0, open=''):
243 """
242 """
244 Begin a group. If you want support for python < 2.5 which doesn't has
243 Begin a group. If you want support for python < 2.5 which doesn't has
245 the with statement this is the preferred way:
244 the with statement this is the preferred way:
246
245
247 p.begin_group(1, '{')
246 p.begin_group(1, '{')
248 ...
247 ...
249 p.end_group(1, '}')
248 p.end_group(1, '}')
250
249
251 The python 2.5 expression would be this:
250 The python 2.5 expression would be this:
252
251
253 with p.group(1, '{', '}'):
252 with p.group(1, '{', '}'):
254 ...
253 ...
255
254
256 The first parameter specifies the indentation for the next line (usually
255 The first parameter specifies the indentation for the next line (usually
257 the width of the opening text), the second the opening text. All
256 the width of the opening text), the second the opening text. All
258 parameters are optional.
257 parameters are optional.
259 """
258 """
260 if open:
259 if open:
261 self.text(open)
260 self.text(open)
262 group = Group(self.group_stack[-1].depth + 1)
261 group = Group(self.group_stack[-1].depth + 1)
263 self.group_stack.append(group)
262 self.group_stack.append(group)
264 self.group_queue.enq(group)
263 self.group_queue.enq(group)
265 self.indentation += indent
264 self.indentation += indent
266
265
267 def _enumerate(self, seq):
266 def _enumerate(self, seq):
268 """like enumerate, but with an upper limit on the number of items"""
267 """like enumerate, but with an upper limit on the number of items"""
269 for idx, x in enumerate(seq):
268 for idx, x in enumerate(seq):
270 if self.max_seq_length and idx >= self.max_seq_length:
269 if self.max_seq_length and idx >= self.max_seq_length:
271 self.text(',')
270 self.text(',')
272 self.breakable()
271 self.breakable()
273 self.text('...')
272 self.text('...')
274 return
273 return
275 yield idx, x
274 yield idx, x
276
275
277 def end_group(self, dedent=0, close=''):
276 def end_group(self, dedent=0, close=''):
278 """End a group. See `begin_group` for more details."""
277 """End a group. See `begin_group` for more details."""
279 self.indentation -= dedent
278 self.indentation -= dedent
280 group = self.group_stack.pop()
279 group = self.group_stack.pop()
281 if not group.breakables:
280 if not group.breakables:
282 self.group_queue.remove(group)
281 self.group_queue.remove(group)
283 if close:
282 if close:
284 self.text(close)
283 self.text(close)
285
284
286 def flush(self):
285 def flush(self):
287 """Flush data that is left in the buffer."""
286 """Flush data that is left in the buffer."""
288 for data in self.buffer:
287 for data in self.buffer:
289 self.output_width += data.output(self.output, self.output_width)
288 self.output_width += data.output(self.output, self.output_width)
290 self.buffer.clear()
289 self.buffer.clear()
291 self.buffer_width = 0
290 self.buffer_width = 0
292
291
293
292
294 def _get_mro(obj_class):
293 def _get_mro(obj_class):
295 """ Get a reasonable method resolution order of a class and its superclasses
294 """ Get a reasonable method resolution order of a class and its superclasses
296 for both old-style and new-style classes.
295 for both old-style and new-style classes.
297 """
296 """
298 if not hasattr(obj_class, '__mro__'):
297 if not hasattr(obj_class, '__mro__'):
299 # Old-style class. Mix in object to make a fake new-style class.
298 # Old-style class. Mix in object to make a fake new-style class.
300 try:
299 try:
301 obj_class = type(obj_class.__name__, (obj_class, object), {})
300 obj_class = type(obj_class.__name__, (obj_class, object), {})
302 except TypeError:
301 except TypeError:
303 # Old-style extension type that does not descend from object.
302 # Old-style extension type that does not descend from object.
304 # FIXME: try to construct a more thorough MRO.
303 # FIXME: try to construct a more thorough MRO.
305 mro = [obj_class]
304 mro = [obj_class]
306 else:
305 else:
307 mro = obj_class.__mro__[1:-1]
306 mro = obj_class.__mro__[1:-1]
308 else:
307 else:
309 mro = obj_class.__mro__
308 mro = obj_class.__mro__
310 return mro
309 return mro
311
310
312
311
313 class RepresentationPrinter(PrettyPrinter):
312 class RepresentationPrinter(PrettyPrinter):
314 """
313 """
315 Special pretty printer that has a `pretty` method that calls the pretty
314 Special pretty printer that has a `pretty` method that calls the pretty
316 printer for a python object.
315 printer for a python object.
317
316
318 This class stores processing data on `self` so you must *never* use
317 This class stores processing data on `self` so you must *never* use
319 this class in a threaded environment. Always lock it or reinstanciate
318 this class in a threaded environment. Always lock it or reinstanciate
320 it.
319 it.
321
320
322 Instances also have a verbose flag callbacks can access to control their
321 Instances also have a verbose flag callbacks can access to control their
323 output. For example the default instance repr prints all attributes and
322 output. For example the default instance repr prints all attributes and
324 methods that are not prefixed by an underscore if the printer is in
323 methods that are not prefixed by an underscore if the printer is in
325 verbose mode.
324 verbose mode.
326 """
325 """
327
326
328 def __init__(self, output, verbose=False, max_width=79, newline='\n',
327 def __init__(self, output, verbose=False, max_width=79, newline='\n',
329 singleton_pprinters=None, type_pprinters=None, deferred_pprinters=None,
328 singleton_pprinters=None, type_pprinters=None, deferred_pprinters=None,
330 max_seq_length=MAX_SEQ_LENGTH):
329 max_seq_length=MAX_SEQ_LENGTH):
331
330
332 PrettyPrinter.__init__(self, output, max_width, newline, max_seq_length=max_seq_length)
331 PrettyPrinter.__init__(self, output, max_width, newline, max_seq_length=max_seq_length)
333 self.verbose = verbose
332 self.verbose = verbose
334 self.stack = []
333 self.stack = []
335 if singleton_pprinters is None:
334 if singleton_pprinters is None:
336 singleton_pprinters = _singleton_pprinters.copy()
335 singleton_pprinters = _singleton_pprinters.copy()
337 self.singleton_pprinters = singleton_pprinters
336 self.singleton_pprinters = singleton_pprinters
338 if type_pprinters is None:
337 if type_pprinters is None:
339 type_pprinters = _type_pprinters.copy()
338 type_pprinters = _type_pprinters.copy()
340 self.type_pprinters = type_pprinters
339 self.type_pprinters = type_pprinters
341 if deferred_pprinters is None:
340 if deferred_pprinters is None:
342 deferred_pprinters = _deferred_type_pprinters.copy()
341 deferred_pprinters = _deferred_type_pprinters.copy()
343 self.deferred_pprinters = deferred_pprinters
342 self.deferred_pprinters = deferred_pprinters
344
343
345 def pretty(self, obj):
344 def pretty(self, obj):
346 """Pretty print the given object."""
345 """Pretty print the given object."""
347 obj_id = id(obj)
346 obj_id = id(obj)
348 cycle = obj_id in self.stack
347 cycle = obj_id in self.stack
349 self.stack.append(obj_id)
348 self.stack.append(obj_id)
350 self.begin_group()
349 self.begin_group()
351 try:
350 try:
352 obj_class = _safe_getattr(obj, '__class__', None) or type(obj)
351 obj_class = _safe_getattr(obj, '__class__', None) or type(obj)
353 # First try to find registered singleton printers for the type.
352 # First try to find registered singleton printers for the type.
354 try:
353 try:
355 printer = self.singleton_pprinters[obj_id]
354 printer = self.singleton_pprinters[obj_id]
356 except (TypeError, KeyError):
355 except (TypeError, KeyError):
357 pass
356 pass
358 else:
357 else:
359 return printer(obj, self, cycle)
358 return printer(obj, self, cycle)
360 # Next walk the mro and check for either:
359 # Next walk the mro and check for either:
361 # 1) a registered printer
360 # 1) a registered printer
362 # 2) a _repr_pretty_ method
361 # 2) a _repr_pretty_ method
363 for cls in _get_mro(obj_class):
362 for cls in _get_mro(obj_class):
364 if cls in self.type_pprinters:
363 if cls in self.type_pprinters:
365 # printer registered in self.type_pprinters
364 # printer registered in self.type_pprinters
366 return self.type_pprinters[cls](obj, self, cycle)
365 return self.type_pprinters[cls](obj, self, cycle)
367 else:
366 else:
368 # deferred printer
367 # deferred printer
369 printer = self._in_deferred_types(cls)
368 printer = self._in_deferred_types(cls)
370 if printer is not None:
369 if printer is not None:
371 return printer(obj, self, cycle)
370 return printer(obj, self, cycle)
372 else:
371 else:
373 # Finally look for special method names.
372 # Finally look for special method names.
374 # Some objects automatically create any requested
373 # Some objects automatically create any requested
375 # attribute. Try to ignore most of them by checking for
374 # attribute. Try to ignore most of them by checking for
376 # callability.
375 # callability.
377 if '_repr_pretty_' in cls.__dict__:
376 if '_repr_pretty_' in cls.__dict__:
378 meth = cls._repr_pretty_
377 meth = cls._repr_pretty_
379 if callable(meth):
378 if callable(meth):
380 return meth(obj, self, cycle)
379 return meth(obj, self, cycle)
381 return _default_pprint(obj, self, cycle)
380 return _default_pprint(obj, self, cycle)
382 finally:
381 finally:
383 self.end_group()
382 self.end_group()
384 self.stack.pop()
383 self.stack.pop()
385
384
386 def _in_deferred_types(self, cls):
385 def _in_deferred_types(self, cls):
387 """
386 """
388 Check if the given class is specified in the deferred type registry.
387 Check if the given class is specified in the deferred type registry.
389
388
390 Returns the printer from the registry if it exists, and None if the
389 Returns the printer from the registry if it exists, and None if the
391 class is not in the registry. Successful matches will be moved to the
390 class is not in the registry. Successful matches will be moved to the
392 regular type registry for future use.
391 regular type registry for future use.
393 """
392 """
394 mod = _safe_getattr(cls, '__module__', None)
393 mod = _safe_getattr(cls, '__module__', None)
395 name = _safe_getattr(cls, '__name__', None)
394 name = _safe_getattr(cls, '__name__', None)
396 key = (mod, name)
395 key = (mod, name)
397 printer = None
396 printer = None
398 if key in self.deferred_pprinters:
397 if key in self.deferred_pprinters:
399 # Move the printer over to the regular registry.
398 # Move the printer over to the regular registry.
400 printer = self.deferred_pprinters.pop(key)
399 printer = self.deferred_pprinters.pop(key)
401 self.type_pprinters[cls] = printer
400 self.type_pprinters[cls] = printer
402 return printer
401 return printer
403
402
404
403
405 class Printable(object):
404 class Printable(object):
406
405
407 def output(self, stream, output_width):
406 def output(self, stream, output_width):
408 return output_width
407 return output_width
409
408
410
409
411 class Text(Printable):
410 class Text(Printable):
412
411
413 def __init__(self):
412 def __init__(self):
414 self.objs = []
413 self.objs = []
415 self.width = 0
414 self.width = 0
416
415
417 def output(self, stream, output_width):
416 def output(self, stream, output_width):
418 for obj in self.objs:
417 for obj in self.objs:
419 stream.write(obj)
418 stream.write(obj)
420 return output_width + self.width
419 return output_width + self.width
421
420
422 def add(self, obj, width):
421 def add(self, obj, width):
423 self.objs.append(obj)
422 self.objs.append(obj)
424 self.width += width
423 self.width += width
425
424
426
425
427 class Breakable(Printable):
426 class Breakable(Printable):
428
427
429 def __init__(self, seq, width, pretty):
428 def __init__(self, seq, width, pretty):
430 self.obj = seq
429 self.obj = seq
431 self.width = width
430 self.width = width
432 self.pretty = pretty
431 self.pretty = pretty
433 self.indentation = pretty.indentation
432 self.indentation = pretty.indentation
434 self.group = pretty.group_stack[-1]
433 self.group = pretty.group_stack[-1]
435 self.group.breakables.append(self)
434 self.group.breakables.append(self)
436
435
437 def output(self, stream, output_width):
436 def output(self, stream, output_width):
438 self.group.breakables.popleft()
437 self.group.breakables.popleft()
439 if self.group.want_break:
438 if self.group.want_break:
440 stream.write(self.pretty.newline)
439 stream.write(self.pretty.newline)
441 stream.write(' ' * self.indentation)
440 stream.write(' ' * self.indentation)
442 return self.indentation
441 return self.indentation
443 if not self.group.breakables:
442 if not self.group.breakables:
444 self.pretty.group_queue.remove(self.group)
443 self.pretty.group_queue.remove(self.group)
445 stream.write(self.obj)
444 stream.write(self.obj)
446 return output_width + self.width
445 return output_width + self.width
447
446
448
447
449 class Group(Printable):
448 class Group(Printable):
450
449
451 def __init__(self, depth):
450 def __init__(self, depth):
452 self.depth = depth
451 self.depth = depth
453 self.breakables = deque()
452 self.breakables = deque()
454 self.want_break = False
453 self.want_break = False
455
454
456
455
457 class GroupQueue(object):
456 class GroupQueue(object):
458
457
459 def __init__(self, *groups):
458 def __init__(self, *groups):
460 self.queue = []
459 self.queue = []
461 for group in groups:
460 for group in groups:
462 self.enq(group)
461 self.enq(group)
463
462
464 def enq(self, group):
463 def enq(self, group):
465 depth = group.depth
464 depth = group.depth
466 while depth > len(self.queue) - 1:
465 while depth > len(self.queue) - 1:
467 self.queue.append([])
466 self.queue.append([])
468 self.queue[depth].append(group)
467 self.queue[depth].append(group)
469
468
470 def deq(self):
469 def deq(self):
471 for stack in self.queue:
470 for stack in self.queue:
472 for idx, group in enumerate(reversed(stack)):
471 for idx, group in enumerate(reversed(stack)):
473 if group.breakables:
472 if group.breakables:
474 del stack[idx]
473 del stack[idx]
475 group.want_break = True
474 group.want_break = True
476 return group
475 return group
477 for group in stack:
476 for group in stack:
478 group.want_break = True
477 group.want_break = True
479 del stack[:]
478 del stack[:]
480
479
481 def remove(self, group):
480 def remove(self, group):
482 try:
481 try:
483 self.queue[group.depth].remove(group)
482 self.queue[group.depth].remove(group)
484 except ValueError:
483 except ValueError:
485 pass
484 pass
486
485
487
486
488 def _default_pprint(obj, p, cycle):
487 def _default_pprint(obj, p, cycle):
489 """
488 """
490 The default print function. Used if an object does not provide one and
489 The default print function. Used if an object does not provide one and
491 it's none of the builtin objects.
490 it's none of the builtin objects.
492 """
491 """
493 klass = _safe_getattr(obj, '__class__', None) or type(obj)
492 klass = _safe_getattr(obj, '__class__', None) or type(obj)
494 if _safe_getattr(klass, '__repr__', None) is not object.__repr__:
493 if _safe_getattr(klass, '__repr__', None) is not object.__repr__:
495 # A user-provided repr. Find newlines and replace them with p.break_()
494 # A user-provided repr. Find newlines and replace them with p.break_()
496 _repr_pprint(obj, p, cycle)
495 _repr_pprint(obj, p, cycle)
497 return
496 return
498 p.begin_group(1, '<')
497 p.begin_group(1, '<')
499 p.pretty(klass)
498 p.pretty(klass)
500 p.text(' at 0x%x' % id(obj))
499 p.text(' at 0x%x' % id(obj))
501 if cycle:
500 if cycle:
502 p.text(' ...')
501 p.text(' ...')
503 elif p.verbose:
502 elif p.verbose:
504 first = True
503 first = True
505 for key in dir(obj):
504 for key in dir(obj):
506 if not key.startswith('_'):
505 if not key.startswith('_'):
507 try:
506 try:
508 value = getattr(obj, key)
507 value = getattr(obj, key)
509 except AttributeError:
508 except AttributeError:
510 continue
509 continue
511 if isinstance(value, types.MethodType):
510 if isinstance(value, types.MethodType):
512 continue
511 continue
513 if not first:
512 if not first:
514 p.text(',')
513 p.text(',')
515 p.breakable()
514 p.breakable()
516 p.text(key)
515 p.text(key)
517 p.text('=')
516 p.text('=')
518 step = len(key) + 1
517 step = len(key) + 1
519 p.indentation += step
518 p.indentation += step
520 p.pretty(value)
519 p.pretty(value)
521 p.indentation -= step
520 p.indentation -= step
522 first = False
521 first = False
523 p.end_group(1, '>')
522 p.end_group(1, '>')
524
523
525
524
526 def _seq_pprinter_factory(start, end, basetype):
525 def _seq_pprinter_factory(start, end, basetype):
527 """
526 """
528 Factory that returns a pprint function useful for sequences. Used by
527 Factory that returns a pprint function useful for sequences. Used by
529 the default pprint for tuples, dicts, and lists.
528 the default pprint for tuples, dicts, and lists.
530 """
529 """
531 def inner(obj, p, cycle):
530 def inner(obj, p, cycle):
532 typ = type(obj)
531 typ = type(obj)
533 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
532 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
534 # If the subclass provides its own repr, use it instead.
533 # If the subclass provides its own repr, use it instead.
535 return p.text(typ.__repr__(obj))
534 return p.text(typ.__repr__(obj))
536
535
537 if cycle:
536 if cycle:
538 return p.text(start + '...' + end)
537 return p.text(start + '...' + end)
539 step = len(start)
538 step = len(start)
540 p.begin_group(step, start)
539 p.begin_group(step, start)
541 for idx, x in p._enumerate(obj):
540 for idx, x in p._enumerate(obj):
542 if idx:
541 if idx:
543 p.text(',')
542 p.text(',')
544 p.breakable()
543 p.breakable()
545 p.pretty(x)
544 p.pretty(x)
546 if len(obj) == 1 and type(obj) is tuple:
545 if len(obj) == 1 and type(obj) is tuple:
547 # Special case for 1-item tuples.
546 # Special case for 1-item tuples.
548 p.text(',')
547 p.text(',')
549 p.end_group(step, end)
548 p.end_group(step, end)
550 return inner
549 return inner
551
550
552
551
553 def _set_pprinter_factory(start, end, basetype):
552 def _set_pprinter_factory(start, end, basetype):
554 """
553 """
555 Factory that returns a pprint function useful for sets and frozensets.
554 Factory that returns a pprint function useful for sets and frozensets.
556 """
555 """
557 def inner(obj, p, cycle):
556 def inner(obj, p, cycle):
558 typ = type(obj)
557 typ = type(obj)
559 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
558 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
560 # If the subclass provides its own repr, use it instead.
559 # If the subclass provides its own repr, use it instead.
561 return p.text(typ.__repr__(obj))
560 return p.text(typ.__repr__(obj))
562
561
563 if cycle:
562 if cycle:
564 return p.text(start + '...' + end)
563 return p.text(start + '...' + end)
565 if len(obj) == 0:
564 if len(obj) == 0:
566 # Special case.
565 # Special case.
567 p.text(basetype.__name__ + '()')
566 p.text(basetype.__name__ + '()')
568 else:
567 else:
569 step = len(start)
568 step = len(start)
570 p.begin_group(step, start)
569 p.begin_group(step, start)
571 # Like dictionary keys, we will try to sort the items if there aren't too many
570 # Like dictionary keys, we will try to sort the items if there aren't too many
572 items = obj
571 items = obj
573 if not (p.max_seq_length and len(obj) >= p.max_seq_length):
572 if not (p.max_seq_length and len(obj) >= p.max_seq_length):
574 try:
573 try:
575 items = sorted(obj)
574 items = sorted(obj)
576 except Exception:
575 except Exception:
577 # Sometimes the items don't sort.
576 # Sometimes the items don't sort.
578 pass
577 pass
579 for idx, x in p._enumerate(items):
578 for idx, x in p._enumerate(items):
580 if idx:
579 if idx:
581 p.text(',')
580 p.text(',')
582 p.breakable()
581 p.breakable()
583 p.pretty(x)
582 p.pretty(x)
584 p.end_group(step, end)
583 p.end_group(step, end)
585 return inner
584 return inner
586
585
587
586
588 def _dict_pprinter_factory(start, end, basetype=None):
587 def _dict_pprinter_factory(start, end, basetype=None):
589 """
588 """
590 Factory that returns a pprint function used by the default pprint of
589 Factory that returns a pprint function used by the default pprint of
591 dicts and dict proxies.
590 dicts and dict proxies.
592 """
591 """
593 def inner(obj, p, cycle):
592 def inner(obj, p, cycle):
594 typ = type(obj)
593 typ = type(obj)
595 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
594 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
596 # If the subclass provides its own repr, use it instead.
595 # If the subclass provides its own repr, use it instead.
597 return p.text(typ.__repr__(obj))
596 return p.text(typ.__repr__(obj))
598
597
599 if cycle:
598 if cycle:
600 return p.text('{...}')
599 return p.text('{...}')
601 step = len(start)
600 step = len(start)
602 p.begin_group(step, start)
601 p.begin_group(step, start)
603 keys = obj.keys()
602 keys = obj.keys()
604 # if dict isn't large enough to be truncated, sort keys before displaying
603 # if dict isn't large enough to be truncated, sort keys before displaying
605 if not (p.max_seq_length and len(obj) >= p.max_seq_length):
604 if not (p.max_seq_length and len(obj) >= p.max_seq_length):
606 try:
605 try:
607 keys = sorted(keys)
606 keys = sorted(keys)
608 except Exception:
607 except Exception:
609 # Sometimes the keys don't sort.
608 # Sometimes the keys don't sort.
610 pass
609 pass
611 for idx, key in p._enumerate(keys):
610 for idx, key in p._enumerate(keys):
612 if idx:
611 if idx:
613 p.text(',')
612 p.text(',')
614 p.breakable()
613 p.breakable()
615 p.pretty(key)
614 p.pretty(key)
616 p.text(': ')
615 p.text(': ')
617 p.pretty(obj[key])
616 p.pretty(obj[key])
618 p.end_group(step, end)
617 p.end_group(step, end)
619 return inner
618 return inner
620
619
621
620
622 def _super_pprint(obj, p, cycle):
621 def _super_pprint(obj, p, cycle):
623 """The pprint for the super type."""
622 """The pprint for the super type."""
624 p.begin_group(8, '<super: ')
623 p.begin_group(8, '<super: ')
625 p.pretty(obj.__thisclass__)
624 p.pretty(obj.__thisclass__)
626 p.text(',')
625 p.text(',')
627 p.breakable()
626 p.breakable()
628 if PYPY: # In PyPy, super() objects don't have __self__ attributes
627 if PYPY: # In PyPy, super() objects don't have __self__ attributes
629 dself = obj.__repr__.__self__
628 dself = obj.__repr__.__self__
630 p.pretty(None if dself is obj else dself)
629 p.pretty(None if dself is obj else dself)
631 else:
630 else:
632 p.pretty(obj.__self__)
631 p.pretty(obj.__self__)
633 p.end_group(8, '>')
632 p.end_group(8, '>')
634
633
635
634
636 def _re_pattern_pprint(obj, p, cycle):
635 def _re_pattern_pprint(obj, p, cycle):
637 """The pprint function for regular expression patterns."""
636 """The pprint function for regular expression patterns."""
638 p.text('re.compile(')
637 p.text('re.compile(')
639 pattern = repr(obj.pattern)
638 pattern = repr(obj.pattern)
640 if pattern[:1] in 'uU':
639 if pattern[:1] in 'uU':
641 pattern = pattern[1:]
640 pattern = pattern[1:]
642 prefix = 'ur'
641 prefix = 'ur'
643 else:
642 else:
644 prefix = 'r'
643 prefix = 'r'
645 pattern = prefix + pattern.replace('\\\\', '\\')
644 pattern = prefix + pattern.replace('\\\\', '\\')
646 p.text(pattern)
645 p.text(pattern)
647 if obj.flags:
646 if obj.flags:
648 p.text(',')
647 p.text(',')
649 p.breakable()
648 p.breakable()
650 done_one = False
649 done_one = False
651 for flag in ('TEMPLATE', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL',
650 for flag in ('TEMPLATE', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL',
652 'UNICODE', 'VERBOSE', 'DEBUG'):
651 'UNICODE', 'VERBOSE', 'DEBUG'):
653 if obj.flags & getattr(re, flag):
652 if obj.flags & getattr(re, flag):
654 if done_one:
653 if done_one:
655 p.text('|')
654 p.text('|')
656 p.text('re.' + flag)
655 p.text('re.' + flag)
657 done_one = True
656 done_one = True
658 p.text(')')
657 p.text(')')
659
658
660
659
661 def _type_pprint(obj, p, cycle):
660 def _type_pprint(obj, p, cycle):
662 """The pprint for classes and types."""
661 """The pprint for classes and types."""
663 # Heap allocated types might not have the module attribute,
662 # Heap allocated types might not have the module attribute,
664 # and others may set it to None.
663 # and others may set it to None.
665
664
666 # Checks for a __repr__ override in the metaclass. Can't compare the
665 # Checks for a __repr__ override in the metaclass. Can't compare the
667 # type(obj).__repr__ directly because in PyPy the representation function
666 # type(obj).__repr__ directly because in PyPy the representation function
668 # inherited from type isn't the same type.__repr__
667 # inherited from type isn't the same type.__repr__
669 if [m for m in _get_mro(type(obj)) if "__repr__" in vars(m)][:1] != [type]:
668 if [m for m in _get_mro(type(obj)) if "__repr__" in vars(m)][:1] != [type]:
670 _repr_pprint(obj, p, cycle)
669 _repr_pprint(obj, p, cycle)
671 return
670 return
672
671
673 mod = _safe_getattr(obj, '__module__', None)
672 mod = _safe_getattr(obj, '__module__', None)
674 try:
673 try:
675 name = obj.__qualname__
674 name = obj.__qualname__
676 if not isinstance(name, str):
675 if not isinstance(name, str):
677 # This can happen if the type implements __qualname__ as a property
676 # This can happen if the type implements __qualname__ as a property
678 # or other descriptor in Python 2.
677 # or other descriptor in Python 2.
679 raise Exception("Try __name__")
678 raise Exception("Try __name__")
680 except Exception:
679 except Exception:
681 name = obj.__name__
680 name = obj.__name__
682 if not isinstance(name, str):
681 if not isinstance(name, str):
683 name = '<unknown type>'
682 name = '<unknown type>'
684
683
685 if mod in (None, '__builtin__', 'builtins', 'exceptions'):
684 if mod in (None, '__builtin__', 'builtins', 'exceptions'):
686 p.text(name)
685 p.text(name)
687 else:
686 else:
688 p.text(mod + '.' + name)
687 p.text(mod + '.' + name)
689
688
690
689
691 def _repr_pprint(obj, p, cycle):
690 def _repr_pprint(obj, p, cycle):
692 """A pprint that just redirects to the normal repr function."""
691 """A pprint that just redirects to the normal repr function."""
693 # Find newlines and replace them with p.break_()
692 # Find newlines and replace them with p.break_()
694 output = repr(obj)
693 output = repr(obj)
695 for idx,output_line in enumerate(output.splitlines()):
694 for idx,output_line in enumerate(output.splitlines()):
696 if idx:
695 if idx:
697 p.break_()
696 p.break_()
698 p.text(output_line)
697 p.text(output_line)
699
698
700
699
701 def _function_pprint(obj, p, cycle):
700 def _function_pprint(obj, p, cycle):
702 """Base pprint for all functions and builtin functions."""
701 """Base pprint for all functions and builtin functions."""
703 name = _safe_getattr(obj, '__qualname__', obj.__name__)
702 name = _safe_getattr(obj, '__qualname__', obj.__name__)
704 mod = obj.__module__
703 mod = obj.__module__
705 if mod and mod not in ('__builtin__', 'builtins', 'exceptions'):
704 if mod and mod not in ('__builtin__', 'builtins', 'exceptions'):
706 name = mod + '.' + name
705 name = mod + '.' + name
707 p.text('<function %s>' % name)
706 p.text('<function %s>' % name)
708
707
709
708
710 def _exception_pprint(obj, p, cycle):
709 def _exception_pprint(obj, p, cycle):
711 """Base pprint for all exceptions."""
710 """Base pprint for all exceptions."""
712 name = getattr(obj.__class__, '__qualname__', obj.__class__.__name__)
711 name = getattr(obj.__class__, '__qualname__', obj.__class__.__name__)
713 if obj.__class__.__module__ not in ('exceptions', 'builtins'):
712 if obj.__class__.__module__ not in ('exceptions', 'builtins'):
714 name = '%s.%s' % (obj.__class__.__module__, name)
713 name = '%s.%s' % (obj.__class__.__module__, name)
715 step = len(name) + 1
714 step = len(name) + 1
716 p.begin_group(step, name + '(')
715 p.begin_group(step, name + '(')
717 for idx, arg in enumerate(getattr(obj, 'args', ())):
716 for idx, arg in enumerate(getattr(obj, 'args', ())):
718 if idx:
717 if idx:
719 p.text(',')
718 p.text(',')
720 p.breakable()
719 p.breakable()
721 p.pretty(arg)
720 p.pretty(arg)
722 p.end_group(step, ')')
721 p.end_group(step, ')')
723
722
724
723
725 #: the exception base
724 #: the exception base
726 try:
725 try:
727 _exception_base = BaseException
726 _exception_base = BaseException
728 except NameError:
727 except NameError:
729 _exception_base = Exception
728 _exception_base = Exception
730
729
731
730
732 #: printers for builtin types
731 #: printers for builtin types
733 _type_pprinters = {
732 _type_pprinters = {
734 int: _repr_pprint,
733 int: _repr_pprint,
735 float: _repr_pprint,
734 float: _repr_pprint,
736 str: _repr_pprint,
735 str: _repr_pprint,
737 tuple: _seq_pprinter_factory('(', ')', tuple),
736 tuple: _seq_pprinter_factory('(', ')', tuple),
738 list: _seq_pprinter_factory('[', ']', list),
737 list: _seq_pprinter_factory('[', ']', list),
739 dict: _dict_pprinter_factory('{', '}', dict),
738 dict: _dict_pprinter_factory('{', '}', dict),
740
739
741 set: _set_pprinter_factory('{', '}', set),
740 set: _set_pprinter_factory('{', '}', set),
742 frozenset: _set_pprinter_factory('frozenset({', '})', frozenset),
741 frozenset: _set_pprinter_factory('frozenset({', '})', frozenset),
743 super: _super_pprint,
742 super: _super_pprint,
744 _re_pattern_type: _re_pattern_pprint,
743 _re_pattern_type: _re_pattern_pprint,
745 type: _type_pprint,
744 type: _type_pprint,
746 types.FunctionType: _function_pprint,
745 types.FunctionType: _function_pprint,
747 types.BuiltinFunctionType: _function_pprint,
746 types.BuiltinFunctionType: _function_pprint,
748 types.MethodType: _repr_pprint,
747 types.MethodType: _repr_pprint,
749
748
750 datetime.datetime: _repr_pprint,
749 datetime.datetime: _repr_pprint,
751 datetime.timedelta: _repr_pprint,
750 datetime.timedelta: _repr_pprint,
752 _exception_base: _exception_pprint
751 _exception_base: _exception_pprint
753 }
752 }
754
753
755 try:
754 try:
756 # In PyPy, types.DictProxyType is dict, setting the dictproxy printer
755 # In PyPy, types.DictProxyType is dict, setting the dictproxy printer
757 # using dict.setdefault avoids overwritting the dict printer
756 # using dict.setdefault avoids overwritting the dict printer
758 _type_pprinters.setdefault(types.DictProxyType,
757 _type_pprinters.setdefault(types.DictProxyType,
759 _dict_pprinter_factory('dict_proxy({', '})'))
758 _dict_pprinter_factory('dict_proxy({', '})'))
760 _type_pprinters[types.ClassType] = _type_pprint
759 _type_pprinters[types.ClassType] = _type_pprint
761 _type_pprinters[types.SliceType] = _repr_pprint
760 _type_pprinters[types.SliceType] = _repr_pprint
762 except AttributeError: # Python 3
761 except AttributeError: # Python 3
763 _type_pprinters[types.MappingProxyType] = \
762 _type_pprinters[types.MappingProxyType] = \
764 _dict_pprinter_factory('mappingproxy({', '})')
763 _dict_pprinter_factory('mappingproxy({', '})')
765 _type_pprinters[slice] = _repr_pprint
764 _type_pprinters[slice] = _repr_pprint
766
765
767 try:
766 try:
768 _type_pprinters[long] = _repr_pprint
767 _type_pprinters[long] = _repr_pprint
769 _type_pprinters[unicode] = _repr_pprint
768 _type_pprinters[unicode] = _repr_pprint
770 except NameError:
769 except NameError:
771 _type_pprinters[range] = _repr_pprint
770 _type_pprinters[range] = _repr_pprint
772 _type_pprinters[bytes] = _repr_pprint
771 _type_pprinters[bytes] = _repr_pprint
773
772
774 #: printers for types specified by name
773 #: printers for types specified by name
775 _deferred_type_pprinters = {
774 _deferred_type_pprinters = {
776 }
775 }
777
776
778 def for_type(typ, func):
777 def for_type(typ, func):
779 """
778 """
780 Add a pretty printer for a given type.
779 Add a pretty printer for a given type.
781 """
780 """
782 oldfunc = _type_pprinters.get(typ, None)
781 oldfunc = _type_pprinters.get(typ, None)
783 if func is not None:
782 if func is not None:
784 # To support easy restoration of old pprinters, we need to ignore Nones.
783 # To support easy restoration of old pprinters, we need to ignore Nones.
785 _type_pprinters[typ] = func
784 _type_pprinters[typ] = func
786 return oldfunc
785 return oldfunc
787
786
788 def for_type_by_name(type_module, type_name, func):
787 def for_type_by_name(type_module, type_name, func):
789 """
788 """
790 Add a pretty printer for a type specified by the module and name of a type
789 Add a pretty printer for a type specified by the module and name of a type
791 rather than the type object itself.
790 rather than the type object itself.
792 """
791 """
793 key = (type_module, type_name)
792 key = (type_module, type_name)
794 oldfunc = _deferred_type_pprinters.get(key, None)
793 oldfunc = _deferred_type_pprinters.get(key, None)
795 if func is not None:
794 if func is not None:
796 # To support easy restoration of old pprinters, we need to ignore Nones.
795 # To support easy restoration of old pprinters, we need to ignore Nones.
797 _deferred_type_pprinters[key] = func
796 _deferred_type_pprinters[key] = func
798 return oldfunc
797 return oldfunc
799
798
800
799
801 #: printers for the default singletons
800 #: printers for the default singletons
802 _singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis,
801 _singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis,
803 NotImplemented]), _repr_pprint)
802 NotImplemented]), _repr_pprint)
804
803
805
804
806 def _defaultdict_pprint(obj, p, cycle):
805 def _defaultdict_pprint(obj, p, cycle):
807 name = obj.__class__.__name__
806 name = obj.__class__.__name__
808 with p.group(len(name) + 1, name + '(', ')'):
807 with p.group(len(name) + 1, name + '(', ')'):
809 if cycle:
808 if cycle:
810 p.text('...')
809 p.text('...')
811 else:
810 else:
812 p.pretty(obj.default_factory)
811 p.pretty(obj.default_factory)
813 p.text(',')
812 p.text(',')
814 p.breakable()
813 p.breakable()
815 p.pretty(dict(obj))
814 p.pretty(dict(obj))
816
815
817 def _ordereddict_pprint(obj, p, cycle):
816 def _ordereddict_pprint(obj, p, cycle):
818 name = obj.__class__.__name__
817 name = obj.__class__.__name__
819 with p.group(len(name) + 1, name + '(', ')'):
818 with p.group(len(name) + 1, name + '(', ')'):
820 if cycle:
819 if cycle:
821 p.text('...')
820 p.text('...')
822 elif len(obj):
821 elif len(obj):
823 p.pretty(list(obj.items()))
822 p.pretty(list(obj.items()))
824
823
825 def _deque_pprint(obj, p, cycle):
824 def _deque_pprint(obj, p, cycle):
826 name = obj.__class__.__name__
825 name = obj.__class__.__name__
827 with p.group(len(name) + 1, name + '(', ')'):
826 with p.group(len(name) + 1, name + '(', ')'):
828 if cycle:
827 if cycle:
829 p.text('...')
828 p.text('...')
830 else:
829 else:
831 p.pretty(list(obj))
830 p.pretty(list(obj))
832
831
833
832
834 def _counter_pprint(obj, p, cycle):
833 def _counter_pprint(obj, p, cycle):
835 name = obj.__class__.__name__
834 name = obj.__class__.__name__
836 with p.group(len(name) + 1, name + '(', ')'):
835 with p.group(len(name) + 1, name + '(', ')'):
837 if cycle:
836 if cycle:
838 p.text('...')
837 p.text('...')
839 elif len(obj):
838 elif len(obj):
840 p.pretty(dict(obj))
839 p.pretty(dict(obj))
841
840
842 for_type_by_name('collections', 'defaultdict', _defaultdict_pprint)
841 for_type_by_name('collections', 'defaultdict', _defaultdict_pprint)
843 for_type_by_name('collections', 'OrderedDict', _ordereddict_pprint)
842 for_type_by_name('collections', 'OrderedDict', _ordereddict_pprint)
844 for_type_by_name('collections', 'deque', _deque_pprint)
843 for_type_by_name('collections', 'deque', _deque_pprint)
845 for_type_by_name('collections', 'Counter', _counter_pprint)
844 for_type_by_name('collections', 'Counter', _counter_pprint)
846
845
847 if __name__ == '__main__':
846 if __name__ == '__main__':
848 from random import randrange
847 from random import randrange
849 class Foo(object):
848 class Foo(object):
850 def __init__(self):
849 def __init__(self):
851 self.foo = 1
850 self.foo = 1
852 self.bar = re.compile(r'\s+')
851 self.bar = re.compile(r'\s+')
853 self.blub = dict.fromkeys(range(30), randrange(1, 40))
852 self.blub = dict.fromkeys(range(30), randrange(1, 40))
854 self.hehe = 23424.234234
853 self.hehe = 23424.234234
855 self.list = ["blub", "blah", self]
854 self.list = ["blub", "blah", self]
856
855
857 def get_foo(self):
856 def get_foo(self):
858 print("foo")
857 print("foo")
859
858
860 pprint(Foo(), verbose=True)
859 pprint(Foo(), verbose=True)
General Comments 0
You need to be logged in to leave comments. Login now