##// END OF EJS Templates
remove unused imports
Srinivas Reddy Thatiparthy -
Show More
@@ -1,454 +1,453 b''
1 1 # encoding: utf-8
2 2 """
3 3 An application for IPython.
4 4
5 5 All top-level applications should use the classes in this module for
6 6 handling configuration and creating configurables.
7 7
8 8 The job of an :class:`Application` is to create the master configuration
9 9 object and then create the configurable objects, passing the config to them.
10 10 """
11 11
12 12 # Copyright (c) IPython Development Team.
13 13 # Distributed under the terms of the Modified BSD License.
14 14
15 15 import atexit
16 16 from copy import deepcopy
17 17 import glob
18 18 import logging
19 19 import os
20 20 import shutil
21 21 import sys
22 22
23 23 from traitlets.config.application import Application, catch_config_error
24 24 from traitlets.config.loader import ConfigFileNotFound, PyFileConfigLoader
25 25 from IPython.core import release, crashhandler
26 26 from IPython.core.profiledir import ProfileDir, ProfileDirError
27 27 from IPython.paths import get_ipython_dir, get_ipython_package_dir
28 28 from IPython.utils.path import ensure_dir_exists
29 from IPython.utils import py3compat
30 29 from traitlets import (
31 30 List, Unicode, Type, Bool, Dict, Set, Instance, Undefined,
32 31 default, observe,
33 32 )
34 33
35 34 if os.name == 'nt':
36 35 programdata = os.environ.get('PROGRAMDATA', None)
37 36 if programdata:
38 37 SYSTEM_CONFIG_DIRS = [os.path.join(programdata, 'ipython')]
39 38 else: # PROGRAMDATA is not defined by default on XP.
40 39 SYSTEM_CONFIG_DIRS = []
41 40 else:
42 41 SYSTEM_CONFIG_DIRS = [
43 42 "/usr/local/etc/ipython",
44 43 "/etc/ipython",
45 44 ]
46 45
47 46 _envvar = os.environ.get('IPYTHON_SUPPRESS_CONFIG_ERRORS')
48 47 if _envvar in {None, ''}:
49 48 IPYTHON_SUPPRESS_CONFIG_ERRORS = None
50 49 else:
51 50 if _envvar.lower() in {'1','true'}:
52 51 IPYTHON_SUPPRESS_CONFIG_ERRORS = True
53 52 elif _envvar.lower() in {'0','false'} :
54 53 IPYTHON_SUPPRESS_CONFIG_ERRORS = False
55 54 else:
56 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 57 # aliases and flags
59 58
60 59 base_aliases = {
61 60 'profile-dir' : 'ProfileDir.location',
62 61 'profile' : 'BaseIPythonApplication.profile',
63 62 'ipython-dir' : 'BaseIPythonApplication.ipython_dir',
64 63 'log-level' : 'Application.log_level',
65 64 'config' : 'BaseIPythonApplication.extra_config_file',
66 65 }
67 66
68 67 base_flags = dict(
69 68 debug = ({'Application' : {'log_level' : logging.DEBUG}},
70 69 "set log level to logging.DEBUG (maximize logging output)"),
71 70 quiet = ({'Application' : {'log_level' : logging.CRITICAL}},
72 71 "set log level to logging.CRITICAL (minimize logging output)"),
73 72 init = ({'BaseIPythonApplication' : {
74 73 'copy_config_files' : True,
75 74 'auto_create' : True}
76 75 }, """Initialize profile with default config files. This is equivalent
77 76 to running `ipython profile create <profile>` prior to startup.
78 77 """)
79 78 )
80 79
81 80 class ProfileAwareConfigLoader(PyFileConfigLoader):
82 81 """A Python file config loader that is aware of IPython profiles."""
83 82 def load_subconfig(self, fname, path=None, profile=None):
84 83 if profile is not None:
85 84 try:
86 85 profile_dir = ProfileDir.find_profile_dir_by_name(
87 86 get_ipython_dir(),
88 87 profile,
89 88 )
90 89 except ProfileDirError:
91 90 return
92 91 path = profile_dir.location
93 92 return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path)
94 93
95 94 class BaseIPythonApplication(Application):
96 95
97 96 name = Unicode(u'ipython')
98 97 description = Unicode(u'IPython: an enhanced interactive Python shell.')
99 98 version = Unicode(release.version)
100 99
101 100 aliases = Dict(base_aliases)
102 101 flags = Dict(base_flags)
103 102 classes = List([ProfileDir])
104 103
105 104 # enable `load_subconfig('cfg.py', profile='name')`
106 105 python_config_loader_class = ProfileAwareConfigLoader
107 106
108 107 # Track whether the config_file has changed,
109 108 # because some logic happens only if we aren't using the default.
110 109 config_file_specified = Set()
111 110
112 111 config_file_name = Unicode()
113 112 @default('config_file_name')
114 113 def _config_file_name_default(self):
115 114 return self.name.replace('-','_') + u'_config.py'
116 115 @observe('config_file_name')
117 116 def _config_file_name_changed(self, change):
118 117 if change['new'] != change['old']:
119 118 self.config_file_specified.add(change['new'])
120 119
121 120 # The directory that contains IPython's builtin profiles.
122 121 builtin_profile_dir = Unicode(
123 122 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
124 123 )
125 124
126 125 config_file_paths = List(Unicode())
127 126 @default('config_file_paths')
128 127 def _config_file_paths_default(self):
129 128 return [os.getcwd()]
130 129
131 130 extra_config_file = Unicode(
132 131 help="""Path to an extra config file to load.
133 132
134 133 If specified, load this config file in addition to any other IPython config.
135 134 """).tag(config=True)
136 135 @observe('extra_config_file')
137 136 def _extra_config_file_changed(self, change):
138 137 old = change['old']
139 138 new = change['new']
140 139 try:
141 140 self.config_files.remove(old)
142 141 except ValueError:
143 142 pass
144 143 self.config_file_specified.add(new)
145 144 self.config_files.append(new)
146 145
147 146 profile = Unicode(u'default',
148 147 help="""The IPython profile to use."""
149 148 ).tag(config=True)
150 149
151 150 @observe('profile')
152 151 def _profile_changed(self, change):
153 152 self.builtin_profile_dir = os.path.join(
154 153 get_ipython_package_dir(), u'config', u'profile', change['new']
155 154 )
156 155
157 156 ipython_dir = Unicode(
158 157 help="""
159 158 The name of the IPython directory. This directory is used for logging
160 159 configuration (through profiles), history storage, etc. The default
161 160 is usually $HOME/.ipython. This option can also be specified through
162 161 the environment variable IPYTHONDIR.
163 162 """
164 163 ).tag(config=True)
165 164 @default('ipython_dir')
166 165 def _ipython_dir_default(self):
167 166 d = get_ipython_dir()
168 167 self._ipython_dir_changed({
169 168 'name': 'ipython_dir',
170 169 'old': d,
171 170 'new': d,
172 171 })
173 172 return d
174 173
175 174 _in_init_profile_dir = False
176 175 profile_dir = Instance(ProfileDir, allow_none=True)
177 176 @default('profile_dir')
178 177 def _profile_dir_default(self):
179 178 # avoid recursion
180 179 if self._in_init_profile_dir:
181 180 return
182 181 # profile_dir requested early, force initialization
183 182 self.init_profile_dir()
184 183 return self.profile_dir
185 184
186 185 overwrite = Bool(False,
187 186 help="""Whether to overwrite existing config files when copying"""
188 187 ).tag(config=True)
189 188 auto_create = Bool(False,
190 189 help="""Whether to create profile dir if it doesn't exist"""
191 190 ).tag(config=True)
192 191
193 192 config_files = List(Unicode())
194 193 @default('config_files')
195 194 def _config_files_default(self):
196 195 return [self.config_file_name]
197 196
198 197 copy_config_files = Bool(False,
199 198 help="""Whether to install the default config files into the profile dir.
200 199 If a new profile is being created, and IPython contains config files for that
201 200 profile, then they will be staged into the new directory. Otherwise,
202 201 default config files will be automatically generated.
203 202 """).tag(config=True)
204 203
205 204 verbose_crash = Bool(False,
206 205 help="""Create a massive crash report when IPython encounters what may be an
207 206 internal error. The default is to append a short message to the
208 207 usual traceback""").tag(config=True)
209 208
210 209 # The class to use as the crash handler.
211 210 crash_handler_class = Type(crashhandler.CrashHandler)
212 211
213 212 @catch_config_error
214 213 def __init__(self, **kwargs):
215 214 super(BaseIPythonApplication, self).__init__(**kwargs)
216 215 # ensure current working directory exists
217 216 try:
218 217 os.getcwd()
219 218 except:
220 219 # exit if cwd doesn't exist
221 220 self.log.error("Current working directory doesn't exist.")
222 221 self.exit(1)
223 222
224 223 #-------------------------------------------------------------------------
225 224 # Various stages of Application creation
226 225 #-------------------------------------------------------------------------
227 226
228 227 deprecated_subcommands = {}
229 228
230 229 def initialize_subcommand(self, subc, argv=None):
231 230 if subc in self.deprecated_subcommands:
232 231 self.log.warning("Subcommand `ipython {sub}` is deprecated and will be removed "
233 232 "in future versions.".format(sub=subc))
234 233 self.log.warning("You likely want to use `jupyter {sub}` in the "
235 234 "future".format(sub=subc))
236 235 return super(BaseIPythonApplication, self).initialize_subcommand(subc, argv)
237 236
238 237 def init_crash_handler(self):
239 238 """Create a crash handler, typically setting sys.excepthook to it."""
240 239 self.crash_handler = self.crash_handler_class(self)
241 240 sys.excepthook = self.excepthook
242 241 def unset_crashhandler():
243 242 sys.excepthook = sys.__excepthook__
244 243 atexit.register(unset_crashhandler)
245 244
246 245 def excepthook(self, etype, evalue, tb):
247 246 """this is sys.excepthook after init_crashhandler
248 247
249 248 set self.verbose_crash=True to use our full crashhandler, instead of
250 249 a regular traceback with a short message (crash_handler_lite)
251 250 """
252 251
253 252 if self.verbose_crash:
254 253 return self.crash_handler(etype, evalue, tb)
255 254 else:
256 255 return crashhandler.crash_handler_lite(etype, evalue, tb)
257 256
258 257 @observe('ipython_dir')
259 258 def _ipython_dir_changed(self, change):
260 259 old = change['old']
261 260 new = change['new']
262 261 if old is not Undefined:
263 262 str_old = os.path.abspath(old)
264 263 if str_old in sys.path:
265 264 sys.path.remove(str_old)
266 265 str_path = os.path.abspath(new)
267 266 sys.path.append(str_path)
268 267 ensure_dir_exists(new)
269 268 readme = os.path.join(new, 'README')
270 269 readme_src = os.path.join(get_ipython_package_dir(), u'config', u'profile', 'README')
271 270 if not os.path.exists(readme) and os.path.exists(readme_src):
272 271 shutil.copy(readme_src, readme)
273 272 for d in ('extensions', 'nbextensions'):
274 273 path = os.path.join(new, d)
275 274 try:
276 275 ensure_dir_exists(path)
277 276 except OSError as e:
278 277 # this will not be EEXIST
279 278 self.log.error("couldn't create path %s: %s", path, e)
280 279 self.log.debug("IPYTHONDIR set to: %s" % new)
281 280
282 281 def load_config_file(self, suppress_errors=IPYTHON_SUPPRESS_CONFIG_ERRORS):
283 282 """Load the config file.
284 283
285 284 By default, errors in loading config are handled, and a warning
286 285 printed on screen. For testing, the suppress_errors option is set
287 286 to False, so errors will make tests fail.
288 287
289 288 `supress_errors` default value is to be `None` in which case the
290 289 behavior default to the one of `traitlets.Application`.
291 290
292 291 The default value can be set :
293 292 - to `False` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '0', or 'false' (case insensitive).
294 293 - to `True` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '1' or 'true' (case insensitive).
295 294 - to `None` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '' (empty string) or leaving it unset.
296 295
297 296 Any other value are invalid, and will make IPython exit with a non-zero return code.
298 297 """
299 298
300 299
301 300 self.log.debug("Searching path %s for config files", self.config_file_paths)
302 301 base_config = 'ipython_config.py'
303 302 self.log.debug("Attempting to load config file: %s" %
304 303 base_config)
305 304 try:
306 305 if suppress_errors is not None:
307 306 old_value = Application.raise_config_file_errors
308 307 Application.raise_config_file_errors = not suppress_errors;
309 308 Application.load_config_file(
310 309 self,
311 310 base_config,
312 311 path=self.config_file_paths
313 312 )
314 313 except ConfigFileNotFound:
315 314 # ignore errors loading parent
316 315 self.log.debug("Config file %s not found", base_config)
317 316 pass
318 317 if suppress_errors is not None:
319 318 Application.raise_config_file_errors = old_value
320 319
321 320 for config_file_name in self.config_files:
322 321 if not config_file_name or config_file_name == base_config:
323 322 continue
324 323 self.log.debug("Attempting to load config file: %s" %
325 324 self.config_file_name)
326 325 try:
327 326 Application.load_config_file(
328 327 self,
329 328 config_file_name,
330 329 path=self.config_file_paths
331 330 )
332 331 except ConfigFileNotFound:
333 332 # Only warn if the default config file was NOT being used.
334 333 if config_file_name in self.config_file_specified:
335 334 msg = self.log.warning
336 335 else:
337 336 msg = self.log.debug
338 337 msg("Config file not found, skipping: %s", config_file_name)
339 338 except Exception:
340 339 # For testing purposes.
341 340 if not suppress_errors:
342 341 raise
343 342 self.log.warning("Error loading config file: %s" %
344 343 self.config_file_name, exc_info=True)
345 344
346 345 def init_profile_dir(self):
347 346 """initialize the profile dir"""
348 347 self._in_init_profile_dir = True
349 348 if self.profile_dir is not None:
350 349 # already ran
351 350 return
352 351 if 'ProfileDir.location' not in self.config:
353 352 # location not specified, find by profile name
354 353 try:
355 354 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
356 355 except ProfileDirError:
357 356 # not found, maybe create it (always create default profile)
358 357 if self.auto_create or self.profile == 'default':
359 358 try:
360 359 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
361 360 except ProfileDirError:
362 361 self.log.fatal("Could not create profile: %r"%self.profile)
363 362 self.exit(1)
364 363 else:
365 364 self.log.info("Created profile dir: %r"%p.location)
366 365 else:
367 366 self.log.fatal("Profile %r not found."%self.profile)
368 367 self.exit(1)
369 368 else:
370 369 self.log.debug("Using existing profile dir: %r"%p.location)
371 370 else:
372 371 location = self.config.ProfileDir.location
373 372 # location is fully specified
374 373 try:
375 374 p = ProfileDir.find_profile_dir(location, self.config)
376 375 except ProfileDirError:
377 376 # not found, maybe create it
378 377 if self.auto_create:
379 378 try:
380 379 p = ProfileDir.create_profile_dir(location, self.config)
381 380 except ProfileDirError:
382 381 self.log.fatal("Could not create profile directory: %r"%location)
383 382 self.exit(1)
384 383 else:
385 384 self.log.debug("Creating new profile dir: %r"%location)
386 385 else:
387 386 self.log.fatal("Profile directory %r not found."%location)
388 387 self.exit(1)
389 388 else:
390 389 self.log.info("Using existing profile dir: %r"%location)
391 390 # if profile_dir is specified explicitly, set profile name
392 391 dir_name = os.path.basename(p.location)
393 392 if dir_name.startswith('profile_'):
394 393 self.profile = dir_name[8:]
395 394
396 395 self.profile_dir = p
397 396 self.config_file_paths.append(p.location)
398 397 self._in_init_profile_dir = False
399 398
400 399 def init_config_files(self):
401 400 """[optionally] copy default config files into profile dir."""
402 401 self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
403 402 # copy config files
404 403 path = self.builtin_profile_dir
405 404 if self.copy_config_files:
406 405 src = self.profile
407 406
408 407 cfg = self.config_file_name
409 408 if path and os.path.exists(os.path.join(path, cfg)):
410 409 self.log.warning("Staging %r from %s into %r [overwrite=%s]"%(
411 410 cfg, src, self.profile_dir.location, self.overwrite)
412 411 )
413 412 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
414 413 else:
415 414 self.stage_default_config_file()
416 415 else:
417 416 # Still stage *bundled* config files, but not generated ones
418 417 # This is necessary for `ipython profile=sympy` to load the profile
419 418 # on the first go
420 419 files = glob.glob(os.path.join(path, '*.py'))
421 420 for fullpath in files:
422 421 cfg = os.path.basename(fullpath)
423 422 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
424 423 # file was copied
425 424 self.log.warning("Staging bundled %s from %s into %r"%(
426 425 cfg, self.profile, self.profile_dir.location)
427 426 )
428 427
429 428
430 429 def stage_default_config_file(self):
431 430 """auto generate default config file, and stage it into the profile."""
432 431 s = self.generate_config_file()
433 432 fname = os.path.join(self.profile_dir.location, self.config_file_name)
434 433 if self.overwrite or not os.path.exists(fname):
435 434 self.log.warning("Generating default config file: %r"%(fname))
436 435 with open(fname, 'w') as f:
437 436 f.write(s)
438 437
439 438 @catch_config_error
440 439 def initialize(self, argv=None):
441 440 # don't hook up crash handler before parsing command-line
442 441 self.parse_command_line(argv)
443 442 self.init_crash_handler()
444 443 if self.subapp is not None:
445 444 # stop here if subapp is taking over
446 445 return
447 446 # save a copy of CLI config to re-load after config files
448 447 # so that it has highest priority
449 448 cl_config = deepcopy(self.config)
450 449 self.init_profile_dir()
451 450 self.init_config_files()
452 451 self.load_config_file()
453 452 # enforce cl-opts override configfile opts:
454 453 self.update_config(cl_config)
@@ -1,157 +1,155 b''
1 1 # encoding: utf-8
2 2 """A class for managing IPython extensions."""
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 7 import os
8 8 import os.path
9 import warnings
10 from shutil import copyfile
11 9 import sys
12 10 from importlib import import_module
13 11
14 12 from traitlets.config.configurable import Configurable
15 13 from IPython.utils.path import ensure_dir_exists, compress_user
16 14 from IPython.utils.decorators import undoc
17 15 from traitlets import Instance
18 16
19 17 try:
20 18 from importlib import reload
21 19 except ImportError :
22 20 ## deprecated since 3.4
23 21 from imp import reload
24 22
25 23 #-----------------------------------------------------------------------------
26 24 # Main class
27 25 #-----------------------------------------------------------------------------
28 26
29 27 class ExtensionManager(Configurable):
30 28 """A class to manage IPython extensions.
31 29
32 30 An IPython extension is an importable Python module that has
33 31 a function with the signature::
34 32
35 33 def load_ipython_extension(ipython):
36 34 # Do things with ipython
37 35
38 36 This function is called after your extension is imported and the
39 37 currently active :class:`InteractiveShell` instance is passed as
40 38 the only argument. You can do anything you want with IPython at
41 39 that point, including defining new magic and aliases, adding new
42 40 components, etc.
43 41
44 42 You can also optionally define an :func:`unload_ipython_extension(ipython)`
45 43 function, which will be called if the user unloads or reloads the extension.
46 44 The extension manager will only call :func:`load_ipython_extension` again
47 45 if the extension is reloaded.
48 46
49 47 You can put your extension modules anywhere you want, as long as
50 48 they can be imported by Python's standard import mechanism. However,
51 49 to make it easy to write extensions, you can also put your extensions
52 50 in ``os.path.join(self.ipython_dir, 'extensions')``. This directory
53 51 is added to ``sys.path`` automatically.
54 52 """
55 53
56 54 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
57 55
58 56 def __init__(self, shell=None, **kwargs):
59 57 super(ExtensionManager, self).__init__(shell=shell, **kwargs)
60 58 self.shell.observe(
61 59 self._on_ipython_dir_changed, names=('ipython_dir',)
62 60 )
63 61 self.loaded = set()
64 62
65 63 @property
66 64 def ipython_extension_dir(self):
67 65 return os.path.join(self.shell.ipython_dir, u'extensions')
68 66
69 67 def _on_ipython_dir_changed(self, change):
70 68 ensure_dir_exists(self.ipython_extension_dir)
71 69
72 70 def load_extension(self, module_str):
73 71 """Load an IPython extension by its module name.
74 72
75 73 Returns the string "already loaded" if the extension is already loaded,
76 74 "no load function" if the module doesn't have a load_ipython_extension
77 75 function, or None if it succeeded.
78 76 """
79 77 if module_str in self.loaded:
80 78 return "already loaded"
81 79
82 80 from IPython.utils.syspathcontext import prepended_to_syspath
83 81
84 82 with self.shell.builtin_trap:
85 83 if module_str not in sys.modules:
86 84 with prepended_to_syspath(self.ipython_extension_dir):
87 85 mod = import_module(module_str)
88 86 if mod.__file__.startswith(self.ipython_extension_dir):
89 87 print(("Loading extensions from {dir} is deprecated. "
90 88 "We recommend managing extensions like any "
91 89 "other Python packages, in site-packages.").format(
92 90 dir=compress_user(self.ipython_extension_dir)))
93 91 mod = sys.modules[module_str]
94 92 if self._call_load_ipython_extension(mod):
95 93 self.loaded.add(module_str)
96 94 else:
97 95 return "no load function"
98 96
99 97 def unload_extension(self, module_str):
100 98 """Unload an IPython extension by its module name.
101 99
102 100 This function looks up the extension's name in ``sys.modules`` and
103 101 simply calls ``mod.unload_ipython_extension(self)``.
104 102
105 103 Returns the string "no unload function" if the extension doesn't define
106 104 a function to unload itself, "not loaded" if the extension isn't loaded,
107 105 otherwise None.
108 106 """
109 107 if module_str not in self.loaded:
110 108 return "not loaded"
111 109
112 110 if module_str in sys.modules:
113 111 mod = sys.modules[module_str]
114 112 if self._call_unload_ipython_extension(mod):
115 113 self.loaded.discard(module_str)
116 114 else:
117 115 return "no unload function"
118 116
119 117 def reload_extension(self, module_str):
120 118 """Reload an IPython extension by calling reload.
121 119
122 120 If the module has not been loaded before,
123 121 :meth:`InteractiveShell.load_extension` is called. Otherwise
124 122 :func:`reload` is called and then the :func:`load_ipython_extension`
125 123 function of the module, if it exists is called.
126 124 """
127 125 from IPython.utils.syspathcontext import prepended_to_syspath
128 126
129 127 if (module_str in self.loaded) and (module_str in sys.modules):
130 128 self.unload_extension(module_str)
131 129 mod = sys.modules[module_str]
132 130 with prepended_to_syspath(self.ipython_extension_dir):
133 131 reload(mod)
134 132 if self._call_load_ipython_extension(mod):
135 133 self.loaded.add(module_str)
136 134 else:
137 135 self.load_extension(module_str)
138 136
139 137 def _call_load_ipython_extension(self, mod):
140 138 if hasattr(mod, 'load_ipython_extension'):
141 139 mod.load_ipython_extension(self.shell)
142 140 return True
143 141
144 142 def _call_unload_ipython_extension(self, mod):
145 143 if hasattr(mod, 'unload_ipython_extension'):
146 144 mod.unload_ipython_extension(self.shell)
147 145 return True
148 146
149 147 @undoc
150 148 def install_extension(self, url, filename=None):
151 149 """
152 150 Deprecated.
153 151 """
154 152 # Ensure the extension directory exists
155 153 raise DeprecationWarning(
156 154 '`install_extension` and the `install_ext` magic have been deprecated since IPython 4.0'
157 155 'Use pip or other package managers to manage ipython extensions.')
@@ -1,907 +1,906 b''
1 1 """ History related magics and functionality """
2 2
3 3 # Copyright (c) IPython Development Team.
4 4 # Distributed under the terms of the Modified BSD License.
5 5
6 6
7 7 import atexit
8 8 import datetime
9 9 import os
10 10 import re
11 11 try:
12 12 import sqlite3
13 13 except ImportError:
14 14 try:
15 15 from pysqlite2 import dbapi2 as sqlite3
16 16 except ImportError:
17 17 sqlite3 = None
18 18 import threading
19 19
20 20 from traitlets.config.configurable import LoggingConfigurable
21 21 from decorator import decorator
22 22 from IPython.utils.decorators import undoc
23 23 from IPython.utils.path import locate_profile
24 from IPython.utils import py3compat
25 24 from traitlets import (
26 25 Any, Bool, Dict, Instance, Integer, List, Unicode, TraitError,
27 26 default, observe,
28 27 )
29 28 from warnings import warn
30 29
31 30 #-----------------------------------------------------------------------------
32 31 # Classes and functions
33 32 #-----------------------------------------------------------------------------
34 33
35 34 @undoc
36 35 class DummyDB(object):
37 36 """Dummy DB that will act as a black hole for history.
38 37
39 38 Only used in the absence of sqlite"""
40 39 def execute(*args, **kwargs):
41 40 return []
42 41
43 42 def commit(self, *args, **kwargs):
44 43 pass
45 44
46 45 def __enter__(self, *args, **kwargs):
47 46 pass
48 47
49 48 def __exit__(self, *args, **kwargs):
50 49 pass
51 50
52 51
53 52 @decorator
54 53 def needs_sqlite(f, self, *a, **kw):
55 54 """Decorator: return an empty list in the absence of sqlite."""
56 55 if sqlite3 is None or not self.enabled:
57 56 return []
58 57 else:
59 58 return f(self, *a, **kw)
60 59
61 60
62 61 if sqlite3 is not None:
63 62 DatabaseError = sqlite3.DatabaseError
64 63 OperationalError = sqlite3.OperationalError
65 64 else:
66 65 @undoc
67 66 class DatabaseError(Exception):
68 67 "Dummy exception when sqlite could not be imported. Should never occur."
69 68
70 69 @undoc
71 70 class OperationalError(Exception):
72 71 "Dummy exception when sqlite could not be imported. Should never occur."
73 72
74 73 # use 16kB as threshold for whether a corrupt history db should be saved
75 74 # that should be at least 100 entries or so
76 75 _SAVE_DB_SIZE = 16384
77 76
78 77 @decorator
79 78 def catch_corrupt_db(f, self, *a, **kw):
80 79 """A decorator which wraps HistoryAccessor method calls to catch errors from
81 80 a corrupt SQLite database, move the old database out of the way, and create
82 81 a new one.
83 82
84 83 We avoid clobbering larger databases because this may be triggered due to filesystem issues,
85 84 not just a corrupt file.
86 85 """
87 86 try:
88 87 return f(self, *a, **kw)
89 88 except (DatabaseError, OperationalError) as e:
90 89 self._corrupt_db_counter += 1
91 90 self.log.error("Failed to open SQLite history %s (%s).", self.hist_file, e)
92 91 if self.hist_file != ':memory:':
93 92 if self._corrupt_db_counter > self._corrupt_db_limit:
94 93 self.hist_file = ':memory:'
95 94 self.log.error("Failed to load history too many times, history will not be saved.")
96 95 elif os.path.isfile(self.hist_file):
97 96 # move the file out of the way
98 97 base, ext = os.path.splitext(self.hist_file)
99 98 size = os.stat(self.hist_file).st_size
100 99 if size >= _SAVE_DB_SIZE:
101 100 # if there's significant content, avoid clobbering
102 101 now = datetime.datetime.now().isoformat().replace(':', '.')
103 102 newpath = base + '-corrupt-' + now + ext
104 103 # don't clobber previous corrupt backups
105 104 for i in range(100):
106 105 if not os.path.isfile(newpath):
107 106 break
108 107 else:
109 108 newpath = base + '-corrupt-' + now + (u'-%i' % i) + ext
110 109 else:
111 110 # not much content, possibly empty; don't worry about clobbering
112 111 # maybe we should just delete it?
113 112 newpath = base + '-corrupt' + ext
114 113 os.rename(self.hist_file, newpath)
115 114 self.log.error("History file was moved to %s and a new file created.", newpath)
116 115 self.init_db()
117 116 return []
118 117 else:
119 118 # Failed with :memory:, something serious is wrong
120 119 raise
121 120
122 121 class HistoryAccessorBase(LoggingConfigurable):
123 122 """An abstract class for History Accessors """
124 123
125 124 def get_tail(self, n=10, raw=True, output=False, include_latest=False):
126 125 raise NotImplementedError
127 126
128 127 def search(self, pattern="*", raw=True, search_raw=True,
129 128 output=False, n=None, unique=False):
130 129 raise NotImplementedError
131 130
132 131 def get_range(self, session, start=1, stop=None, raw=True,output=False):
133 132 raise NotImplementedError
134 133
135 134 def get_range_by_str(self, rangestr, raw=True, output=False):
136 135 raise NotImplementedError
137 136
138 137
139 138 class HistoryAccessor(HistoryAccessorBase):
140 139 """Access the history database without adding to it.
141 140
142 141 This is intended for use by standalone history tools. IPython shells use
143 142 HistoryManager, below, which is a subclass of this."""
144 143
145 144 # counter for init_db retries, so we don't keep trying over and over
146 145 _corrupt_db_counter = 0
147 146 # after two failures, fallback on :memory:
148 147 _corrupt_db_limit = 2
149 148
150 149 # String holding the path to the history file
151 150 hist_file = Unicode(
152 151 help="""Path to file to use for SQLite history database.
153 152
154 153 By default, IPython will put the history database in the IPython
155 154 profile directory. If you would rather share one history among
156 155 profiles, you can set this value in each, so that they are consistent.
157 156
158 157 Due to an issue with fcntl, SQLite is known to misbehave on some NFS
159 158 mounts. If you see IPython hanging, try setting this to something on a
160 159 local disk, e.g::
161 160
162 161 ipython --HistoryManager.hist_file=/tmp/ipython_hist.sqlite
163 162
164 163 you can also use the specific value `:memory:` (including the colon
165 164 at both end but not the back ticks), to avoid creating an history file.
166 165
167 166 """).tag(config=True)
168 167
169 168 enabled = Bool(True,
170 169 help="""enable the SQLite history
171 170
172 171 set enabled=False to disable the SQLite history,
173 172 in which case there will be no stored history, no SQLite connection,
174 173 and no background saving thread. This may be necessary in some
175 174 threaded environments where IPython is embedded.
176 175 """
177 176 ).tag(config=True)
178 177
179 178 connection_options = Dict(
180 179 help="""Options for configuring the SQLite connection
181 180
182 181 These options are passed as keyword args to sqlite3.connect
183 182 when establishing database conenctions.
184 183 """
185 184 ).tag(config=True)
186 185
187 186 # The SQLite database
188 187 db = Any()
189 188 @observe('db')
190 189 def _db_changed(self, change):
191 190 """validate the db, since it can be an Instance of two different types"""
192 191 new = change['new']
193 192 connection_types = (DummyDB,)
194 193 if sqlite3 is not None:
195 194 connection_types = (DummyDB, sqlite3.Connection)
196 195 if not isinstance(new, connection_types):
197 196 msg = "%s.db must be sqlite3 Connection or DummyDB, not %r" % \
198 197 (self.__class__.__name__, new)
199 198 raise TraitError(msg)
200 199
201 200 def __init__(self, profile='default', hist_file=u'', **traits):
202 201 """Create a new history accessor.
203 202
204 203 Parameters
205 204 ----------
206 205 profile : str
207 206 The name of the profile from which to open history.
208 207 hist_file : str
209 208 Path to an SQLite history database stored by IPython. If specified,
210 209 hist_file overrides profile.
211 210 config : :class:`~traitlets.config.loader.Config`
212 211 Config object. hist_file can also be set through this.
213 212 """
214 213 # We need a pointer back to the shell for various tasks.
215 214 super(HistoryAccessor, self).__init__(**traits)
216 215 # defer setting hist_file from kwarg until after init,
217 216 # otherwise the default kwarg value would clobber any value
218 217 # set by config
219 218 if hist_file:
220 219 self.hist_file = hist_file
221 220
222 221 if self.hist_file == u'':
223 222 # No one has set the hist_file, yet.
224 223 self.hist_file = self._get_hist_file_name(profile)
225 224
226 225 if sqlite3 is None and self.enabled:
227 226 warn("IPython History requires SQLite, your history will not be saved")
228 227 self.enabled = False
229 228
230 229 self.init_db()
231 230
232 231 def _get_hist_file_name(self, profile='default'):
233 232 """Find the history file for the given profile name.
234 233
235 234 This is overridden by the HistoryManager subclass, to use the shell's
236 235 active profile.
237 236
238 237 Parameters
239 238 ----------
240 239 profile : str
241 240 The name of a profile which has a history file.
242 241 """
243 242 return os.path.join(locate_profile(profile), 'history.sqlite')
244 243
245 244 @catch_corrupt_db
246 245 def init_db(self):
247 246 """Connect to the database, and create tables if necessary."""
248 247 if not self.enabled:
249 248 self.db = DummyDB()
250 249 return
251 250
252 251 # use detect_types so that timestamps return datetime objects
253 252 kwargs = dict(detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
254 253 kwargs.update(self.connection_options)
255 254 self.db = sqlite3.connect(self.hist_file, **kwargs)
256 255 self.db.execute("""CREATE TABLE IF NOT EXISTS sessions (session integer
257 256 primary key autoincrement, start timestamp,
258 257 end timestamp, num_cmds integer, remark text)""")
259 258 self.db.execute("""CREATE TABLE IF NOT EXISTS history
260 259 (session integer, line integer, source text, source_raw text,
261 260 PRIMARY KEY (session, line))""")
262 261 # Output history is optional, but ensure the table's there so it can be
263 262 # enabled later.
264 263 self.db.execute("""CREATE TABLE IF NOT EXISTS output_history
265 264 (session integer, line integer, output text,
266 265 PRIMARY KEY (session, line))""")
267 266 self.db.commit()
268 267 # success! reset corrupt db count
269 268 self._corrupt_db_counter = 0
270 269
271 270 def writeout_cache(self):
272 271 """Overridden by HistoryManager to dump the cache before certain
273 272 database lookups."""
274 273 pass
275 274
276 275 ## -------------------------------
277 276 ## Methods for retrieving history:
278 277 ## -------------------------------
279 278 def _run_sql(self, sql, params, raw=True, output=False):
280 279 """Prepares and runs an SQL query for the history database.
281 280
282 281 Parameters
283 282 ----------
284 283 sql : str
285 284 Any filtering expressions to go after SELECT ... FROM ...
286 285 params : tuple
287 286 Parameters passed to the SQL query (to replace "?")
288 287 raw, output : bool
289 288 See :meth:`get_range`
290 289
291 290 Returns
292 291 -------
293 292 Tuples as :meth:`get_range`
294 293 """
295 294 toget = 'source_raw' if raw else 'source'
296 295 sqlfrom = "history"
297 296 if output:
298 297 sqlfrom = "history LEFT JOIN output_history USING (session, line)"
299 298 toget = "history.%s, output_history.output" % toget
300 299 cur = self.db.execute("SELECT session, line, %s FROM %s " %\
301 300 (toget, sqlfrom) + sql, params)
302 301 if output: # Regroup into 3-tuples, and parse JSON
303 302 return ((ses, lin, (inp, out)) for ses, lin, inp, out in cur)
304 303 return cur
305 304
306 305 @needs_sqlite
307 306 @catch_corrupt_db
308 307 def get_session_info(self, session):
309 308 """Get info about a session.
310 309
311 310 Parameters
312 311 ----------
313 312
314 313 session : int
315 314 Session number to retrieve.
316 315
317 316 Returns
318 317 -------
319 318
320 319 session_id : int
321 320 Session ID number
322 321 start : datetime
323 322 Timestamp for the start of the session.
324 323 end : datetime
325 324 Timestamp for the end of the session, or None if IPython crashed.
326 325 num_cmds : int
327 326 Number of commands run, or None if IPython crashed.
328 327 remark : unicode
329 328 A manually set description.
330 329 """
331 330 query = "SELECT * from sessions where session == ?"
332 331 return self.db.execute(query, (session,)).fetchone()
333 332
334 333 @catch_corrupt_db
335 334 def get_last_session_id(self):
336 335 """Get the last session ID currently in the database.
337 336
338 337 Within IPython, this should be the same as the value stored in
339 338 :attr:`HistoryManager.session_number`.
340 339 """
341 340 for record in self.get_tail(n=1, include_latest=True):
342 341 return record[0]
343 342
344 343 @catch_corrupt_db
345 344 def get_tail(self, n=10, raw=True, output=False, include_latest=False):
346 345 """Get the last n lines from the history database.
347 346
348 347 Parameters
349 348 ----------
350 349 n : int
351 350 The number of lines to get
352 351 raw, output : bool
353 352 See :meth:`get_range`
354 353 include_latest : bool
355 354 If False (default), n+1 lines are fetched, and the latest one
356 355 is discarded. This is intended to be used where the function
357 356 is called by a user command, which it should not return.
358 357
359 358 Returns
360 359 -------
361 360 Tuples as :meth:`get_range`
362 361 """
363 362 self.writeout_cache()
364 363 if not include_latest:
365 364 n += 1
366 365 cur = self._run_sql("ORDER BY session DESC, line DESC LIMIT ?",
367 366 (n,), raw=raw, output=output)
368 367 if not include_latest:
369 368 return reversed(list(cur)[1:])
370 369 return reversed(list(cur))
371 370
372 371 @catch_corrupt_db
373 372 def search(self, pattern="*", raw=True, search_raw=True,
374 373 output=False, n=None, unique=False):
375 374 """Search the database using unix glob-style matching (wildcards
376 375 * and ?).
377 376
378 377 Parameters
379 378 ----------
380 379 pattern : str
381 380 The wildcarded pattern to match when searching
382 381 search_raw : bool
383 382 If True, search the raw input, otherwise, the parsed input
384 383 raw, output : bool
385 384 See :meth:`get_range`
386 385 n : None or int
387 386 If an integer is given, it defines the limit of
388 387 returned entries.
389 388 unique : bool
390 389 When it is true, return only unique entries.
391 390
392 391 Returns
393 392 -------
394 393 Tuples as :meth:`get_range`
395 394 """
396 395 tosearch = "source_raw" if search_raw else "source"
397 396 if output:
398 397 tosearch = "history." + tosearch
399 398 self.writeout_cache()
400 399 sqlform = "WHERE %s GLOB ?" % tosearch
401 400 params = (pattern,)
402 401 if unique:
403 402 sqlform += ' GROUP BY {0}'.format(tosearch)
404 403 if n is not None:
405 404 sqlform += " ORDER BY session DESC, line DESC LIMIT ?"
406 405 params += (n,)
407 406 elif unique:
408 407 sqlform += " ORDER BY session, line"
409 408 cur = self._run_sql(sqlform, params, raw=raw, output=output)
410 409 if n is not None:
411 410 return reversed(list(cur))
412 411 return cur
413 412
414 413 @catch_corrupt_db
415 414 def get_range(self, session, start=1, stop=None, raw=True,output=False):
416 415 """Retrieve input by session.
417 416
418 417 Parameters
419 418 ----------
420 419 session : int
421 420 Session number to retrieve.
422 421 start : int
423 422 First line to retrieve.
424 423 stop : int
425 424 End of line range (excluded from output itself). If None, retrieve
426 425 to the end of the session.
427 426 raw : bool
428 427 If True, return untranslated input
429 428 output : bool
430 429 If True, attempt to include output. This will be 'real' Python
431 430 objects for the current session, or text reprs from previous
432 431 sessions if db_log_output was enabled at the time. Where no output
433 432 is found, None is used.
434 433
435 434 Returns
436 435 -------
437 436 entries
438 437 An iterator over the desired lines. Each line is a 3-tuple, either
439 438 (session, line, input) if output is False, or
440 439 (session, line, (input, output)) if output is True.
441 440 """
442 441 if stop:
443 442 lineclause = "line >= ? AND line < ?"
444 443 params = (session, start, stop)
445 444 else:
446 445 lineclause = "line>=?"
447 446 params = (session, start)
448 447
449 448 return self._run_sql("WHERE session==? AND %s" % lineclause,
450 449 params, raw=raw, output=output)
451 450
452 451 def get_range_by_str(self, rangestr, raw=True, output=False):
453 452 """Get lines of history from a string of ranges, as used by magic
454 453 commands %hist, %save, %macro, etc.
455 454
456 455 Parameters
457 456 ----------
458 457 rangestr : str
459 458 A string specifying ranges, e.g. "5 ~2/1-4". See
460 459 :func:`magic_history` for full details.
461 460 raw, output : bool
462 461 As :meth:`get_range`
463 462
464 463 Returns
465 464 -------
466 465 Tuples as :meth:`get_range`
467 466 """
468 467 for sess, s, e in extract_hist_ranges(rangestr):
469 468 for line in self.get_range(sess, s, e, raw=raw, output=output):
470 469 yield line
471 470
472 471
473 472 class HistoryManager(HistoryAccessor):
474 473 """A class to organize all history-related functionality in one place.
475 474 """
476 475 # Public interface
477 476
478 477 # An instance of the IPython shell we are attached to
479 478 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
480 479 allow_none=True)
481 480 # Lists to hold processed and raw history. These start with a blank entry
482 481 # so that we can index them starting from 1
483 482 input_hist_parsed = List([""])
484 483 input_hist_raw = List([""])
485 484 # A list of directories visited during session
486 485 dir_hist = List()
487 486 @default('dir_hist')
488 487 def _dir_hist_default(self):
489 488 try:
490 489 return [os.getcwd()]
491 490 except OSError:
492 491 return []
493 492
494 493 # A dict of output history, keyed with ints from the shell's
495 494 # execution count.
496 495 output_hist = Dict()
497 496 # The text/plain repr of outputs.
498 497 output_hist_reprs = Dict()
499 498
500 499 # The number of the current session in the history database
501 500 session_number = Integer()
502 501
503 502 db_log_output = Bool(False,
504 503 help="Should the history database include output? (default: no)"
505 504 ).tag(config=True)
506 505 db_cache_size = Integer(0,
507 506 help="Write to database every x commands (higher values save disk access & power).\n"
508 507 "Values of 1 or less effectively disable caching."
509 508 ).tag(config=True)
510 509 # The input and output caches
511 510 db_input_cache = List()
512 511 db_output_cache = List()
513 512
514 513 # History saving in separate thread
515 514 save_thread = Instance('IPython.core.history.HistorySavingThread',
516 515 allow_none=True)
517 516 save_flag = Instance(threading.Event, allow_none=True)
518 517
519 518 # Private interface
520 519 # Variables used to store the three last inputs from the user. On each new
521 520 # history update, we populate the user's namespace with these, shifted as
522 521 # necessary.
523 522 _i00 = Unicode(u'')
524 523 _i = Unicode(u'')
525 524 _ii = Unicode(u'')
526 525 _iii = Unicode(u'')
527 526
528 527 # A regex matching all forms of the exit command, so that we don't store
529 528 # them in the history (it's annoying to rewind the first entry and land on
530 529 # an exit call).
531 530 _exit_re = re.compile(r"(exit|quit)(\s*\(.*\))?$")
532 531
533 532 def __init__(self, shell=None, config=None, **traits):
534 533 """Create a new history manager associated with a shell instance.
535 534 """
536 535 # We need a pointer back to the shell for various tasks.
537 536 super(HistoryManager, self).__init__(shell=shell, config=config,
538 537 **traits)
539 538 self.save_flag = threading.Event()
540 539 self.db_input_cache_lock = threading.Lock()
541 540 self.db_output_cache_lock = threading.Lock()
542 541
543 542 try:
544 543 self.new_session()
545 544 except OperationalError:
546 545 self.log.error("Failed to create history session in %s. History will not be saved.",
547 546 self.hist_file, exc_info=True)
548 547 self.hist_file = ':memory:'
549 548
550 549 if self.enabled and self.hist_file != ':memory:':
551 550 self.save_thread = HistorySavingThread(self)
552 551 self.save_thread.start()
553 552
554 553 def _get_hist_file_name(self, profile=None):
555 554 """Get default history file name based on the Shell's profile.
556 555
557 556 The profile parameter is ignored, but must exist for compatibility with
558 557 the parent class."""
559 558 profile_dir = self.shell.profile_dir.location
560 559 return os.path.join(profile_dir, 'history.sqlite')
561 560
562 561 @needs_sqlite
563 562 def new_session(self, conn=None):
564 563 """Get a new session number."""
565 564 if conn is None:
566 565 conn = self.db
567 566
568 567 with conn:
569 568 cur = conn.execute("""INSERT INTO sessions VALUES (NULL, ?, NULL,
570 569 NULL, "") """, (datetime.datetime.now(),))
571 570 self.session_number = cur.lastrowid
572 571
573 572 def end_session(self):
574 573 """Close the database session, filling in the end time and line count."""
575 574 self.writeout_cache()
576 575 with self.db:
577 576 self.db.execute("""UPDATE sessions SET end=?, num_cmds=? WHERE
578 577 session==?""", (datetime.datetime.now(),
579 578 len(self.input_hist_parsed)-1, self.session_number))
580 579 self.session_number = 0
581 580
582 581 def name_session(self, name):
583 582 """Give the current session a name in the history database."""
584 583 with self.db:
585 584 self.db.execute("UPDATE sessions SET remark=? WHERE session==?",
586 585 (name, self.session_number))
587 586
588 587 def reset(self, new_session=True):
589 588 """Clear the session history, releasing all object references, and
590 589 optionally open a new session."""
591 590 self.output_hist.clear()
592 591 # The directory history can't be completely empty
593 592 self.dir_hist[:] = [os.getcwd()]
594 593
595 594 if new_session:
596 595 if self.session_number:
597 596 self.end_session()
598 597 self.input_hist_parsed[:] = [""]
599 598 self.input_hist_raw[:] = [""]
600 599 self.new_session()
601 600
602 601 # ------------------------------
603 602 # Methods for retrieving history
604 603 # ------------------------------
605 604 def get_session_info(self, session=0):
606 605 """Get info about a session.
607 606
608 607 Parameters
609 608 ----------
610 609
611 610 session : int
612 611 Session number to retrieve. The current session is 0, and negative
613 612 numbers count back from current session, so -1 is the previous session.
614 613
615 614 Returns
616 615 -------
617 616
618 617 session_id : int
619 618 Session ID number
620 619 start : datetime
621 620 Timestamp for the start of the session.
622 621 end : datetime
623 622 Timestamp for the end of the session, or None if IPython crashed.
624 623 num_cmds : int
625 624 Number of commands run, or None if IPython crashed.
626 625 remark : unicode
627 626 A manually set description.
628 627 """
629 628 if session <= 0:
630 629 session += self.session_number
631 630
632 631 return super(HistoryManager, self).get_session_info(session=session)
633 632
634 633 def _get_range_session(self, start=1, stop=None, raw=True, output=False):
635 634 """Get input and output history from the current session. Called by
636 635 get_range, and takes similar parameters."""
637 636 input_hist = self.input_hist_raw if raw else self.input_hist_parsed
638 637
639 638 n = len(input_hist)
640 639 if start < 0:
641 640 start += n
642 641 if not stop or (stop > n):
643 642 stop = n
644 643 elif stop < 0:
645 644 stop += n
646 645
647 646 for i in range(start, stop):
648 647 if output:
649 648 line = (input_hist[i], self.output_hist_reprs.get(i))
650 649 else:
651 650 line = input_hist[i]
652 651 yield (0, i, line)
653 652
654 653 def get_range(self, session=0, start=1, stop=None, raw=True,output=False):
655 654 """Retrieve input by session.
656 655
657 656 Parameters
658 657 ----------
659 658 session : int
660 659 Session number to retrieve. The current session is 0, and negative
661 660 numbers count back from current session, so -1 is previous session.
662 661 start : int
663 662 First line to retrieve.
664 663 stop : int
665 664 End of line range (excluded from output itself). If None, retrieve
666 665 to the end of the session.
667 666 raw : bool
668 667 If True, return untranslated input
669 668 output : bool
670 669 If True, attempt to include output. This will be 'real' Python
671 670 objects for the current session, or text reprs from previous
672 671 sessions if db_log_output was enabled at the time. Where no output
673 672 is found, None is used.
674 673
675 674 Returns
676 675 -------
677 676 entries
678 677 An iterator over the desired lines. Each line is a 3-tuple, either
679 678 (session, line, input) if output is False, or
680 679 (session, line, (input, output)) if output is True.
681 680 """
682 681 if session <= 0:
683 682 session += self.session_number
684 683 if session==self.session_number: # Current session
685 684 return self._get_range_session(start, stop, raw, output)
686 685 return super(HistoryManager, self).get_range(session, start, stop, raw,
687 686 output)
688 687
689 688 ## ----------------------------
690 689 ## Methods for storing history:
691 690 ## ----------------------------
692 691 def store_inputs(self, line_num, source, source_raw=None):
693 692 """Store source and raw input in history and create input cache
694 693 variables ``_i*``.
695 694
696 695 Parameters
697 696 ----------
698 697 line_num : int
699 698 The prompt number of this input.
700 699
701 700 source : str
702 701 Python input.
703 702
704 703 source_raw : str, optional
705 704 If given, this is the raw input without any IPython transformations
706 705 applied to it. If not given, ``source`` is used.
707 706 """
708 707 if source_raw is None:
709 708 source_raw = source
710 709 source = source.rstrip('\n')
711 710 source_raw = source_raw.rstrip('\n')
712 711
713 712 # do not store exit/quit commands
714 713 if self._exit_re.match(source_raw.strip()):
715 714 return
716 715
717 716 self.input_hist_parsed.append(source)
718 717 self.input_hist_raw.append(source_raw)
719 718
720 719 with self.db_input_cache_lock:
721 720 self.db_input_cache.append((line_num, source, source_raw))
722 721 # Trigger to flush cache and write to DB.
723 722 if len(self.db_input_cache) >= self.db_cache_size:
724 723 self.save_flag.set()
725 724
726 725 # update the auto _i variables
727 726 self._iii = self._ii
728 727 self._ii = self._i
729 728 self._i = self._i00
730 729 self._i00 = source_raw
731 730
732 731 # hackish access to user namespace to create _i1,_i2... dynamically
733 732 new_i = '_i%s' % line_num
734 733 to_main = {'_i': self._i,
735 734 '_ii': self._ii,
736 735 '_iii': self._iii,
737 736 new_i : self._i00 }
738 737
739 738 if self.shell is not None:
740 739 self.shell.push(to_main, interactive=False)
741 740
742 741 def store_output(self, line_num):
743 742 """If database output logging is enabled, this saves all the
744 743 outputs from the indicated prompt number to the database. It's
745 744 called by run_cell after code has been executed.
746 745
747 746 Parameters
748 747 ----------
749 748 line_num : int
750 749 The line number from which to save outputs
751 750 """
752 751 if (not self.db_log_output) or (line_num not in self.output_hist_reprs):
753 752 return
754 753 output = self.output_hist_reprs[line_num]
755 754
756 755 with self.db_output_cache_lock:
757 756 self.db_output_cache.append((line_num, output))
758 757 if self.db_cache_size <= 1:
759 758 self.save_flag.set()
760 759
761 760 def _writeout_input_cache(self, conn):
762 761 with conn:
763 762 for line in self.db_input_cache:
764 763 conn.execute("INSERT INTO history VALUES (?, ?, ?, ?)",
765 764 (self.session_number,)+line)
766 765
767 766 def _writeout_output_cache(self, conn):
768 767 with conn:
769 768 for line in self.db_output_cache:
770 769 conn.execute("INSERT INTO output_history VALUES (?, ?, ?)",
771 770 (self.session_number,)+line)
772 771
773 772 @needs_sqlite
774 773 def writeout_cache(self, conn=None):
775 774 """Write any entries in the cache to the database."""
776 775 if conn is None:
777 776 conn = self.db
778 777
779 778 with self.db_input_cache_lock:
780 779 try:
781 780 self._writeout_input_cache(conn)
782 781 except sqlite3.IntegrityError:
783 782 self.new_session(conn)
784 783 print("ERROR! Session/line number was not unique in",
785 784 "database. History logging moved to new session",
786 785 self.session_number)
787 786 try:
788 787 # Try writing to the new session. If this fails, don't
789 788 # recurse
790 789 self._writeout_input_cache(conn)
791 790 except sqlite3.IntegrityError:
792 791 pass
793 792 finally:
794 793 self.db_input_cache = []
795 794
796 795 with self.db_output_cache_lock:
797 796 try:
798 797 self._writeout_output_cache(conn)
799 798 except sqlite3.IntegrityError:
800 799 print("!! Session/line number for output was not unique",
801 800 "in database. Output will not be stored.")
802 801 finally:
803 802 self.db_output_cache = []
804 803
805 804
806 805 class HistorySavingThread(threading.Thread):
807 806 """This thread takes care of writing history to the database, so that
808 807 the UI isn't held up while that happens.
809 808
810 809 It waits for the HistoryManager's save_flag to be set, then writes out
811 810 the history cache. The main thread is responsible for setting the flag when
812 811 the cache size reaches a defined threshold."""
813 812 daemon = True
814 813 stop_now = False
815 814 enabled = True
816 815 def __init__(self, history_manager):
817 816 super(HistorySavingThread, self).__init__(name="IPythonHistorySavingThread")
818 817 self.history_manager = history_manager
819 818 self.enabled = history_manager.enabled
820 819 atexit.register(self.stop)
821 820
822 821 @needs_sqlite
823 822 def run(self):
824 823 # We need a separate db connection per thread:
825 824 try:
826 825 self.db = sqlite3.connect(self.history_manager.hist_file,
827 826 **self.history_manager.connection_options
828 827 )
829 828 while True:
830 829 self.history_manager.save_flag.wait()
831 830 if self.stop_now:
832 831 self.db.close()
833 832 return
834 833 self.history_manager.save_flag.clear()
835 834 self.history_manager.writeout_cache(self.db)
836 835 except Exception as e:
837 836 print(("The history saving thread hit an unexpected error (%s)."
838 837 "History will not be written to the database.") % repr(e))
839 838
840 839 def stop(self):
841 840 """This can be called from the main thread to safely stop this thread.
842 841
843 842 Note that it does not attempt to write out remaining history before
844 843 exiting. That should be done by calling the HistoryManager's
845 844 end_session method."""
846 845 self.stop_now = True
847 846 self.history_manager.save_flag.set()
848 847 self.join()
849 848
850 849
851 850 # To match, e.g. ~5/8-~2/3
852 851 range_re = re.compile(r"""
853 852 ((?P<startsess>~?\d+)/)?
854 853 (?P<start>\d+)?
855 854 ((?P<sep>[\-:])
856 855 ((?P<endsess>~?\d+)/)?
857 856 (?P<end>\d+))?
858 857 $""", re.VERBOSE)
859 858
860 859
861 860 def extract_hist_ranges(ranges_str):
862 861 """Turn a string of history ranges into 3-tuples of (session, start, stop).
863 862
864 863 Examples
865 864 --------
866 865 >>> list(extract_hist_ranges("~8/5-~7/4 2"))
867 866 [(-8, 5, None), (-7, 1, 5), (0, 2, 3)]
868 867 """
869 868 for range_str in ranges_str.split():
870 869 rmatch = range_re.match(range_str)
871 870 if not rmatch:
872 871 continue
873 872 start = rmatch.group("start")
874 873 if start:
875 874 start = int(start)
876 875 end = rmatch.group("end")
877 876 # If no end specified, get (a, a + 1)
878 877 end = int(end) if end else start + 1
879 878 else: # start not specified
880 879 if not rmatch.group('startsess'): # no startsess
881 880 continue
882 881 start = 1
883 882 end = None # provide the entire session hist
884 883
885 884 if rmatch.group("sep") == "-": # 1-3 == 1:4 --> [1, 2, 3]
886 885 end += 1
887 886 startsess = rmatch.group("startsess") or "0"
888 887 endsess = rmatch.group("endsess") or startsess
889 888 startsess = int(startsess.replace("~","-"))
890 889 endsess = int(endsess.replace("~","-"))
891 890 assert endsess >= startsess, "start session must be earlier than end session"
892 891
893 892 if endsess == startsess:
894 893 yield (startsess, start, end)
895 894 continue
896 895 # Multiple sessions in one range:
897 896 yield (startsess, start, None)
898 897 for sess in range(startsess+1, endsess):
899 898 yield (sess, 1, None)
900 899 yield (endsess, 1, end)
901 900
902 901
903 902 def _format_lineno(session, line):
904 903 """Helper function to format line numbers properly."""
905 904 if session == 0:
906 905 return str(line)
907 906 return "%s#%s" % (session, line)
@@ -1,54 +1,53 b''
1 1 """Support for interactive macros in IPython"""
2 2
3 3 #*****************************************************************************
4 4 # Copyright (C) 2001-2005 Fernando Perez <fperez@colorado.edu>
5 5 #
6 6 # Distributed under the terms of the BSD License. The full license is in
7 7 # the file COPYING, distributed as part of this software.
8 8 #*****************************************************************************
9 9
10 10 import re
11 11
12 from IPython.utils import py3compat
13 12 from IPython.utils.encoding import DEFAULT_ENCODING
14 13
15 14 coding_declaration = re.compile(r"#\s*coding[:=]\s*([-\w.]+)")
16 15
17 16 class Macro(object):
18 17 """Simple class to store the value of macros as strings.
19 18
20 19 Macro is just a callable that executes a string of IPython
21 20 input when called.
22 21 """
23 22
24 23 def __init__(self,code):
25 24 """store the macro value, as a single string which can be executed"""
26 25 lines = []
27 26 enc = None
28 27 for line in code.splitlines():
29 28 coding_match = coding_declaration.match(line)
30 29 if coding_match:
31 30 enc = coding_match.group(1)
32 31 else:
33 32 lines.append(line)
34 33 code = "\n".join(lines)
35 34 if isinstance(code, bytes):
36 35 code = code.decode(enc or DEFAULT_ENCODING)
37 36 self.value = code + '\n'
38 37
39 38 def __str__(self):
40 39 return self.value
41 40
42 41 def __repr__(self):
43 42 return 'IPython.macro.Macro(%s)' % repr(self.value)
44 43
45 44 def __getstate__(self):
46 45 """ needed for safe pickling via %store """
47 46 return {'value': self.value}
48 47
49 48 def __add__(self, other):
50 49 if isinstance(other, Macro):
51 50 return Macro(self.value + other.value)
52 51 elif isinstance(other, str):
53 52 return Macro(self.value + other)
54 53 raise TypeError
@@ -1,685 +1,684 b''
1 1 # encoding: utf-8
2 2 """Magic functions for InteractiveShell.
3 3 """
4 4
5 5 #-----------------------------------------------------------------------------
6 6 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
7 7 # Copyright (C) 2001 Fernando Perez <fperez@colorado.edu>
8 8 # Copyright (C) 2008 The IPython Development Team
9 9
10 10 # Distributed under the terms of the BSD License. The full license is in
11 11 # the file COPYING, distributed as part of this software.
12 12 #-----------------------------------------------------------------------------
13 13
14 14 import os
15 15 import re
16 16 import sys
17 import types
18 17 from getopt import getopt, GetoptError
19 18
20 19 from traitlets.config.configurable import Configurable
21 20 from IPython.core import oinspect
22 21 from IPython.core.error import UsageError
23 22 from IPython.core.inputsplitter import ESC_MAGIC, ESC_MAGIC2
24 23 from decorator import decorator
25 24 from IPython.utils.ipstruct import Struct
26 25 from IPython.utils.process import arg_split
27 26 from IPython.utils.text import dedent
28 27 from traitlets import Bool, Dict, Instance, observe
29 28 from logging import error
30 29
31 30 #-----------------------------------------------------------------------------
32 31 # Globals
33 32 #-----------------------------------------------------------------------------
34 33
35 34 # A dict we'll use for each class that has magics, used as temporary storage to
36 35 # pass information between the @line/cell_magic method decorators and the
37 36 # @magics_class class decorator, because the method decorators have no
38 37 # access to the class when they run. See for more details:
39 38 # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
40 39
41 40 magics = dict(line={}, cell={})
42 41
43 42 magic_kinds = ('line', 'cell')
44 43 magic_spec = ('line', 'cell', 'line_cell')
45 44 magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
46 45
47 46 #-----------------------------------------------------------------------------
48 47 # Utility classes and functions
49 48 #-----------------------------------------------------------------------------
50 49
51 50 class Bunch: pass
52 51
53 52
54 53 def on_off(tag):
55 54 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
56 55 return ['OFF','ON'][tag]
57 56
58 57
59 58 def compress_dhist(dh):
60 59 """Compress a directory history into a new one with at most 20 entries.
61 60
62 61 Return a new list made from the first and last 10 elements of dhist after
63 62 removal of duplicates.
64 63 """
65 64 head, tail = dh[:-10], dh[-10:]
66 65
67 66 newhead = []
68 67 done = set()
69 68 for h in head:
70 69 if h in done:
71 70 continue
72 71 newhead.append(h)
73 72 done.add(h)
74 73
75 74 return newhead + tail
76 75
77 76
78 77 def needs_local_scope(func):
79 78 """Decorator to mark magic functions which need to local scope to run."""
80 79 func.needs_local_scope = True
81 80 return func
82 81
83 82 #-----------------------------------------------------------------------------
84 83 # Class and method decorators for registering magics
85 84 #-----------------------------------------------------------------------------
86 85
87 86 def magics_class(cls):
88 87 """Class decorator for all subclasses of the main Magics class.
89 88
90 89 Any class that subclasses Magics *must* also apply this decorator, to
91 90 ensure that all the methods that have been decorated as line/cell magics
92 91 get correctly registered in the class instance. This is necessary because
93 92 when method decorators run, the class does not exist yet, so they
94 93 temporarily store their information into a module global. Application of
95 94 this class decorator copies that global data to the class instance and
96 95 clears the global.
97 96
98 97 Obviously, this mechanism is not thread-safe, which means that the
99 98 *creation* of subclasses of Magic should only be done in a single-thread
100 99 context. Instantiation of the classes has no restrictions. Given that
101 100 these classes are typically created at IPython startup time and before user
102 101 application code becomes active, in practice this should not pose any
103 102 problems.
104 103 """
105 104 cls.registered = True
106 105 cls.magics = dict(line = magics['line'],
107 106 cell = magics['cell'])
108 107 magics['line'] = {}
109 108 magics['cell'] = {}
110 109 return cls
111 110
112 111
113 112 def record_magic(dct, magic_kind, magic_name, func):
114 113 """Utility function to store a function as a magic of a specific kind.
115 114
116 115 Parameters
117 116 ----------
118 117 dct : dict
119 118 A dictionary with 'line' and 'cell' subdicts.
120 119
121 120 magic_kind : str
122 121 Kind of magic to be stored.
123 122
124 123 magic_name : str
125 124 Key to store the magic as.
126 125
127 126 func : function
128 127 Callable object to store.
129 128 """
130 129 if magic_kind == 'line_cell':
131 130 dct['line'][magic_name] = dct['cell'][magic_name] = func
132 131 else:
133 132 dct[magic_kind][magic_name] = func
134 133
135 134
136 135 def validate_type(magic_kind):
137 136 """Ensure that the given magic_kind is valid.
138 137
139 138 Check that the given magic_kind is one of the accepted spec types (stored
140 139 in the global `magic_spec`), raise ValueError otherwise.
141 140 """
142 141 if magic_kind not in magic_spec:
143 142 raise ValueError('magic_kind must be one of %s, %s given' %
144 143 magic_kinds, magic_kind)
145 144
146 145
147 146 # The docstrings for the decorator below will be fairly similar for the two
148 147 # types (method and function), so we generate them here once and reuse the
149 148 # templates below.
150 149 _docstring_template = \
151 150 """Decorate the given {0} as {1} magic.
152 151
153 152 The decorator can be used with or without arguments, as follows.
154 153
155 154 i) without arguments: it will create a {1} magic named as the {0} being
156 155 decorated::
157 156
158 157 @deco
159 158 def foo(...)
160 159
161 160 will create a {1} magic named `foo`.
162 161
163 162 ii) with one string argument: which will be used as the actual name of the
164 163 resulting magic::
165 164
166 165 @deco('bar')
167 166 def foo(...)
168 167
169 168 will create a {1} magic named `bar`.
170 169
171 170 To register a class magic use ``Interactiveshell.register_magic(class or instance)``.
172 171 """
173 172
174 173 # These two are decorator factories. While they are conceptually very similar,
175 174 # there are enough differences in the details that it's simpler to have them
176 175 # written as completely standalone functions rather than trying to share code
177 176 # and make a single one with convoluted logic.
178 177
179 178 def _method_magic_marker(magic_kind):
180 179 """Decorator factory for methods in Magics subclasses.
181 180 """
182 181
183 182 validate_type(magic_kind)
184 183
185 184 # This is a closure to capture the magic_kind. We could also use a class,
186 185 # but it's overkill for just that one bit of state.
187 186 def magic_deco(arg):
188 187 call = lambda f, *a, **k: f(*a, **k)
189 188
190 189 if callable(arg):
191 190 # "Naked" decorator call (just @foo, no args)
192 191 func = arg
193 192 name = func.__name__
194 193 retval = decorator(call, func)
195 194 record_magic(magics, magic_kind, name, name)
196 195 elif isinstance(arg, str):
197 196 # Decorator called with arguments (@foo('bar'))
198 197 name = arg
199 198 def mark(func, *a, **kw):
200 199 record_magic(magics, magic_kind, name, func.__name__)
201 200 return decorator(call, func)
202 201 retval = mark
203 202 else:
204 203 raise TypeError("Decorator can only be called with "
205 204 "string or function")
206 205 return retval
207 206
208 207 # Ensure the resulting decorator has a usable docstring
209 208 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
210 209 return magic_deco
211 210
212 211
213 212 def _function_magic_marker(magic_kind):
214 213 """Decorator factory for standalone functions.
215 214 """
216 215 validate_type(magic_kind)
217 216
218 217 # This is a closure to capture the magic_kind. We could also use a class,
219 218 # but it's overkill for just that one bit of state.
220 219 def magic_deco(arg):
221 220 call = lambda f, *a, **k: f(*a, **k)
222 221
223 222 # Find get_ipython() in the caller's namespace
224 223 caller = sys._getframe(1)
225 224 for ns in ['f_locals', 'f_globals', 'f_builtins']:
226 225 get_ipython = getattr(caller, ns).get('get_ipython')
227 226 if get_ipython is not None:
228 227 break
229 228 else:
230 229 raise NameError('Decorator can only run in context where '
231 230 '`get_ipython` exists')
232 231
233 232 ip = get_ipython()
234 233
235 234 if callable(arg):
236 235 # "Naked" decorator call (just @foo, no args)
237 236 func = arg
238 237 name = func.__name__
239 238 ip.register_magic_function(func, magic_kind, name)
240 239 retval = decorator(call, func)
241 240 elif isinstance(arg, str):
242 241 # Decorator called with arguments (@foo('bar'))
243 242 name = arg
244 243 def mark(func, *a, **kw):
245 244 ip.register_magic_function(func, magic_kind, name)
246 245 return decorator(call, func)
247 246 retval = mark
248 247 else:
249 248 raise TypeError("Decorator can only be called with "
250 249 "string or function")
251 250 return retval
252 251
253 252 # Ensure the resulting decorator has a usable docstring
254 253 ds = _docstring_template.format('function', magic_kind)
255 254
256 255 ds += dedent("""
257 256 Note: this decorator can only be used in a context where IPython is already
258 257 active, so that the `get_ipython()` call succeeds. You can therefore use
259 258 it in your startup files loaded after IPython initializes, but *not* in the
260 259 IPython configuration file itself, which is executed before IPython is
261 260 fully up and running. Any file located in the `startup` subdirectory of
262 261 your configuration profile will be OK in this sense.
263 262 """)
264 263
265 264 magic_deco.__doc__ = ds
266 265 return magic_deco
267 266
268 267
269 268 # Create the actual decorators for public use
270 269
271 270 # These three are used to decorate methods in class definitions
272 271 line_magic = _method_magic_marker('line')
273 272 cell_magic = _method_magic_marker('cell')
274 273 line_cell_magic = _method_magic_marker('line_cell')
275 274
276 275 # These three decorate standalone functions and perform the decoration
277 276 # immediately. They can only run where get_ipython() works
278 277 register_line_magic = _function_magic_marker('line')
279 278 register_cell_magic = _function_magic_marker('cell')
280 279 register_line_cell_magic = _function_magic_marker('line_cell')
281 280
282 281 #-----------------------------------------------------------------------------
283 282 # Core Magic classes
284 283 #-----------------------------------------------------------------------------
285 284
286 285 class MagicsManager(Configurable):
287 286 """Object that handles all magic-related functionality for IPython.
288 287 """
289 288 # Non-configurable class attributes
290 289
291 290 # A two-level dict, first keyed by magic type, then by magic function, and
292 291 # holding the actual callable object as value. This is the dict used for
293 292 # magic function dispatch
294 293 magics = Dict()
295 294
296 295 # A registry of the original objects that we've been given holding magics.
297 296 registry = Dict()
298 297
299 298 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
300 299
301 300 auto_magic = Bool(True, help=
302 301 "Automatically call line magics without requiring explicit % prefix"
303 302 ).tag(config=True)
304 303 @observe('auto_magic')
305 304 def _auto_magic_changed(self, change):
306 305 self.shell.automagic = change['new']
307 306
308 307 _auto_status = [
309 308 'Automagic is OFF, % prefix IS needed for line magics.',
310 309 'Automagic is ON, % prefix IS NOT needed for line magics.']
311 310
312 311 user_magics = Instance('IPython.core.magics.UserMagics', allow_none=True)
313 312
314 313 def __init__(self, shell=None, config=None, user_magics=None, **traits):
315 314
316 315 super(MagicsManager, self).__init__(shell=shell, config=config,
317 316 user_magics=user_magics, **traits)
318 317 self.magics = dict(line={}, cell={})
319 318 # Let's add the user_magics to the registry for uniformity, so *all*
320 319 # registered magic containers can be found there.
321 320 self.registry[user_magics.__class__.__name__] = user_magics
322 321
323 322 def auto_status(self):
324 323 """Return descriptive string with automagic status."""
325 324 return self._auto_status[self.auto_magic]
326 325
327 326 def lsmagic(self):
328 327 """Return a dict of currently available magic functions.
329 328
330 329 The return dict has the keys 'line' and 'cell', corresponding to the
331 330 two types of magics we support. Each value is a list of names.
332 331 """
333 332 return self.magics
334 333
335 334 def lsmagic_docs(self, brief=False, missing=''):
336 335 """Return dict of documentation of magic functions.
337 336
338 337 The return dict has the keys 'line' and 'cell', corresponding to the
339 338 two types of magics we support. Each value is a dict keyed by magic
340 339 name whose value is the function docstring. If a docstring is
341 340 unavailable, the value of `missing` is used instead.
342 341
343 342 If brief is True, only the first line of each docstring will be returned.
344 343 """
345 344 docs = {}
346 345 for m_type in self.magics:
347 346 m_docs = {}
348 347 for m_name, m_func in self.magics[m_type].items():
349 348 if m_func.__doc__:
350 349 if brief:
351 350 m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
352 351 else:
353 352 m_docs[m_name] = m_func.__doc__.rstrip()
354 353 else:
355 354 m_docs[m_name] = missing
356 355 docs[m_type] = m_docs
357 356 return docs
358 357
359 358 def register(self, *magic_objects):
360 359 """Register one or more instances of Magics.
361 360
362 361 Take one or more classes or instances of classes that subclass the main
363 362 `core.Magic` class, and register them with IPython to use the magic
364 363 functions they provide. The registration process will then ensure that
365 364 any methods that have decorated to provide line and/or cell magics will
366 365 be recognized with the `%x`/`%%x` syntax as a line/cell magic
367 366 respectively.
368 367
369 368 If classes are given, they will be instantiated with the default
370 369 constructor. If your classes need a custom constructor, you should
371 370 instanitate them first and pass the instance.
372 371
373 372 The provided arguments can be an arbitrary mix of classes and instances.
374 373
375 374 Parameters
376 375 ----------
377 376 magic_objects : one or more classes or instances
378 377 """
379 378 # Start by validating them to ensure they have all had their magic
380 379 # methods registered at the instance level
381 380 for m in magic_objects:
382 381 if not m.registered:
383 382 raise ValueError("Class of magics %r was constructed without "
384 383 "the @register_magics class decorator")
385 384 if isinstance(m, type):
386 385 # If we're given an uninstantiated class
387 386 m = m(shell=self.shell)
388 387
389 388 # Now that we have an instance, we can register it and update the
390 389 # table of callables
391 390 self.registry[m.__class__.__name__] = m
392 391 for mtype in magic_kinds:
393 392 self.magics[mtype].update(m.magics[mtype])
394 393
395 394 def register_function(self, func, magic_kind='line', magic_name=None):
396 395 """Expose a standalone function as magic function for IPython.
397 396
398 397 This will create an IPython magic (line, cell or both) from a
399 398 standalone function. The functions should have the following
400 399 signatures:
401 400
402 401 * For line magics: `def f(line)`
403 402 * For cell magics: `def f(line, cell)`
404 403 * For a function that does both: `def f(line, cell=None)`
405 404
406 405 In the latter case, the function will be called with `cell==None` when
407 406 invoked as `%f`, and with cell as a string when invoked as `%%f`.
408 407
409 408 Parameters
410 409 ----------
411 410 func : callable
412 411 Function to be registered as a magic.
413 412
414 413 magic_kind : str
415 414 Kind of magic, one of 'line', 'cell' or 'line_cell'
416 415
417 416 magic_name : optional str
418 417 If given, the name the magic will have in the IPython namespace. By
419 418 default, the name of the function itself is used.
420 419 """
421 420
422 421 # Create the new method in the user_magics and register it in the
423 422 # global table
424 423 validate_type(magic_kind)
425 424 magic_name = func.__name__ if magic_name is None else magic_name
426 425 setattr(self.user_magics, magic_name, func)
427 426 record_magic(self.magics, magic_kind, magic_name, func)
428 427
429 428 def register_alias(self, alias_name, magic_name, magic_kind='line', magic_params=None):
430 429 """Register an alias to a magic function.
431 430
432 431 The alias is an instance of :class:`MagicAlias`, which holds the
433 432 name and kind of the magic it should call. Binding is done at
434 433 call time, so if the underlying magic function is changed the alias
435 434 will call the new function.
436 435
437 436 Parameters
438 437 ----------
439 438 alias_name : str
440 439 The name of the magic to be registered.
441 440
442 441 magic_name : str
443 442 The name of an existing magic.
444 443
445 444 magic_kind : str
446 445 Kind of magic, one of 'line' or 'cell'
447 446 """
448 447
449 448 # `validate_type` is too permissive, as it allows 'line_cell'
450 449 # which we do not handle.
451 450 if magic_kind not in magic_kinds:
452 451 raise ValueError('magic_kind must be one of %s, %s given' %
453 452 magic_kinds, magic_kind)
454 453
455 454 alias = MagicAlias(self.shell, magic_name, magic_kind, magic_params)
456 455 setattr(self.user_magics, alias_name, alias)
457 456 record_magic(self.magics, magic_kind, alias_name, alias)
458 457
459 458 # Key base class that provides the central functionality for magics.
460 459
461 460
462 461 class Magics(Configurable):
463 462 """Base class for implementing magic functions.
464 463
465 464 Shell functions which can be reached as %function_name. All magic
466 465 functions should accept a string, which they can parse for their own
467 466 needs. This can make some functions easier to type, eg `%cd ../`
468 467 vs. `%cd("../")`
469 468
470 469 Classes providing magic functions need to subclass this class, and they
471 470 MUST:
472 471
473 472 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
474 473 individual methods as magic functions, AND
475 474
476 475 - Use the class decorator `@magics_class` to ensure that the magic
477 476 methods are properly registered at the instance level upon instance
478 477 initialization.
479 478
480 479 See :mod:`magic_functions` for examples of actual implementation classes.
481 480 """
482 481 # Dict holding all command-line options for each magic.
483 482 options_table = None
484 483 # Dict for the mapping of magic names to methods, set by class decorator
485 484 magics = None
486 485 # Flag to check that the class decorator was properly applied
487 486 registered = False
488 487 # Instance of IPython shell
489 488 shell = None
490 489
491 490 def __init__(self, shell=None, **kwargs):
492 491 if not(self.__class__.registered):
493 492 raise ValueError('Magics subclass without registration - '
494 493 'did you forget to apply @magics_class?')
495 494 if shell is not None:
496 495 if hasattr(shell, 'configurables'):
497 496 shell.configurables.append(self)
498 497 if hasattr(shell, 'config'):
499 498 kwargs.setdefault('parent', shell)
500 499
501 500 self.shell = shell
502 501 self.options_table = {}
503 502 # The method decorators are run when the instance doesn't exist yet, so
504 503 # they can only record the names of the methods they are supposed to
505 504 # grab. Only now, that the instance exists, can we create the proper
506 505 # mapping to bound methods. So we read the info off the original names
507 506 # table and replace each method name by the actual bound method.
508 507 # But we mustn't clobber the *class* mapping, in case of multiple instances.
509 508 class_magics = self.magics
510 509 self.magics = {}
511 510 for mtype in magic_kinds:
512 511 tab = self.magics[mtype] = {}
513 512 cls_tab = class_magics[mtype]
514 513 for magic_name, meth_name in cls_tab.items():
515 514 if isinstance(meth_name, str):
516 515 # it's a method name, grab it
517 516 tab[magic_name] = getattr(self, meth_name)
518 517 else:
519 518 # it's the real thing
520 519 tab[magic_name] = meth_name
521 520 # Configurable **needs** to be initiated at the end or the config
522 521 # magics get screwed up.
523 522 super(Magics, self).__init__(**kwargs)
524 523
525 524 def arg_err(self,func):
526 525 """Print docstring if incorrect arguments were passed"""
527 526 print('Error in arguments:')
528 527 print(oinspect.getdoc(func))
529 528
530 529 def format_latex(self, strng):
531 530 """Format a string for latex inclusion."""
532 531
533 532 # Characters that need to be escaped for latex:
534 533 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
535 534 # Magic command names as headers:
536 535 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
537 536 re.MULTILINE)
538 537 # Magic commands
539 538 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
540 539 re.MULTILINE)
541 540 # Paragraph continue
542 541 par_re = re.compile(r'\\$',re.MULTILINE)
543 542
544 543 # The "\n" symbol
545 544 newline_re = re.compile(r'\\n')
546 545
547 546 # Now build the string for output:
548 547 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
549 548 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
550 549 strng)
551 550 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
552 551 strng = par_re.sub(r'\\\\',strng)
553 552 strng = escape_re.sub(r'\\\1',strng)
554 553 strng = newline_re.sub(r'\\textbackslash{}n',strng)
555 554 return strng
556 555
557 556 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
558 557 """Parse options passed to an argument string.
559 558
560 559 The interface is similar to that of :func:`getopt.getopt`, but it
561 560 returns a :class:`~IPython.utils.struct.Struct` with the options as keys
562 561 and the stripped argument string still as a string.
563 562
564 563 arg_str is quoted as a true sys.argv vector by using shlex.split.
565 564 This allows us to easily expand variables, glob files, quote
566 565 arguments, etc.
567 566
568 567 Parameters
569 568 ----------
570 569
571 570 arg_str : str
572 571 The arguments to parse.
573 572
574 573 opt_str : str
575 574 The options specification.
576 575
577 576 mode : str, default 'string'
578 577 If given as 'list', the argument string is returned as a list (split
579 578 on whitespace) instead of a string.
580 579
581 580 list_all : bool, default False
582 581 Put all option values in lists. Normally only options
583 582 appearing more than once are put in a list.
584 583
585 584 posix : bool, default True
586 585 Whether to split the input line in POSIX mode or not, as per the
587 586 conventions outlined in the :mod:`shlex` module from the standard
588 587 library.
589 588 """
590 589
591 590 # inject default options at the beginning of the input line
592 591 caller = sys._getframe(1).f_code.co_name
593 592 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
594 593
595 594 mode = kw.get('mode','string')
596 595 if mode not in ['string','list']:
597 596 raise ValueError('incorrect mode given: %s' % mode)
598 597 # Get options
599 598 list_all = kw.get('list_all',0)
600 599 posix = kw.get('posix', os.name == 'posix')
601 600 strict = kw.get('strict', True)
602 601
603 602 # Check if we have more than one argument to warrant extra processing:
604 603 odict = {} # Dictionary with options
605 604 args = arg_str.split()
606 605 if len(args) >= 1:
607 606 # If the list of inputs only has 0 or 1 thing in it, there's no
608 607 # need to look for options
609 608 argv = arg_split(arg_str, posix, strict)
610 609 # Do regular option processing
611 610 try:
612 611 opts,args = getopt(argv, opt_str, long_opts)
613 612 except GetoptError as e:
614 613 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
615 614 " ".join(long_opts)))
616 615 for o,a in opts:
617 616 if o.startswith('--'):
618 617 o = o[2:]
619 618 else:
620 619 o = o[1:]
621 620 try:
622 621 odict[o].append(a)
623 622 except AttributeError:
624 623 odict[o] = [odict[o],a]
625 624 except KeyError:
626 625 if list_all:
627 626 odict[o] = [a]
628 627 else:
629 628 odict[o] = a
630 629
631 630 # Prepare opts,args for return
632 631 opts = Struct(odict)
633 632 if mode == 'string':
634 633 args = ' '.join(args)
635 634
636 635 return opts,args
637 636
638 637 def default_option(self, fn, optstr):
639 638 """Make an entry in the options_table for fn, with value optstr"""
640 639
641 640 if fn not in self.lsmagic():
642 641 error("%s is not a magic function" % fn)
643 642 self.options_table[fn] = optstr
644 643
645 644
646 645 class MagicAlias(object):
647 646 """An alias to another magic function.
648 647
649 648 An alias is determined by its magic name and magic kind. Lookup
650 649 is done at call time, so if the underlying magic changes the alias
651 650 will call the new function.
652 651
653 652 Use the :meth:`MagicsManager.register_alias` method or the
654 653 `%alias_magic` magic function to create and register a new alias.
655 654 """
656 655 def __init__(self, shell, magic_name, magic_kind, magic_params=None):
657 656 self.shell = shell
658 657 self.magic_name = magic_name
659 658 self.magic_params = magic_params
660 659 self.magic_kind = magic_kind
661 660
662 661 self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name)
663 662 self.__doc__ = "Alias for `%s`." % self.pretty_target
664 663
665 664 self._in_call = False
666 665
667 666 def __call__(self, *args, **kwargs):
668 667 """Call the magic alias."""
669 668 fn = self.shell.find_magic(self.magic_name, self.magic_kind)
670 669 if fn is None:
671 670 raise UsageError("Magic `%s` not found." % self.pretty_target)
672 671
673 672 # Protect against infinite recursion.
674 673 if self._in_call:
675 674 raise UsageError("Infinite recursion detected; "
676 675 "magic aliases cannot call themselves.")
677 676 self._in_call = True
678 677 try:
679 678 if self.magic_params:
680 679 args_list = list(args)
681 680 args_list[0] = self.magic_params + " " + args[0]
682 681 args = tuple(args_list)
683 682 return fn(*args, **kwargs)
684 683 finally:
685 684 self._in_call = False
@@ -1,66 +1,63 b''
1 1 """Implementation of magic functions for the extension machinery.
2 2 """
3 3 #-----------------------------------------------------------------------------
4 4 # Copyright (c) 2012 The IPython Development Team.
5 5 #
6 6 # Distributed under the terms of the Modified BSD License.
7 7 #
8 8 # The full license is in the file COPYING.txt, distributed with this software.
9 9 #-----------------------------------------------------------------------------
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Imports
13 13 #-----------------------------------------------------------------------------
14 14
15 # Stdlib
16 import os
17 15
18 16 # Our own packages
19 17 from IPython.core.error import UsageError
20 18 from IPython.core.magic import Magics, magics_class, line_magic
21 from warnings import warn
22 19
23 20 #-----------------------------------------------------------------------------
24 21 # Magic implementation classes
25 22 #-----------------------------------------------------------------------------
26 23
27 24 @magics_class
28 25 class ExtensionMagics(Magics):
29 26 """Magics to manage the IPython extensions system."""
30 27
31 28 @line_magic
32 29 def load_ext(self, module_str):
33 30 """Load an IPython extension by its module name."""
34 31 if not module_str:
35 32 raise UsageError('Missing module name.')
36 33 res = self.shell.extension_manager.load_extension(module_str)
37 34
38 35 if res == 'already loaded':
39 36 print("The %s extension is already loaded. To reload it, use:" % module_str)
40 37 print(" %reload_ext", module_str)
41 38 elif res == 'no load function':
42 39 print("The %s module is not an IPython extension." % module_str)
43 40
44 41 @line_magic
45 42 def unload_ext(self, module_str):
46 43 """Unload an IPython extension by its module name.
47 44
48 45 Not all extensions can be unloaded, only those which define an
49 46 ``unload_ipython_extension`` function.
50 47 """
51 48 if not module_str:
52 49 raise UsageError('Missing module name.')
53 50
54 51 res = self.shell.extension_manager.unload_extension(module_str)
55 52
56 53 if res == 'no unload function':
57 54 print("The %s extension doesn't define how to unload it." % module_str)
58 55 elif res == "not loaded":
59 56 print("The %s extension is not loaded." % module_str)
60 57
61 58 @line_magic
62 59 def reload_ext(self, module_str):
63 60 """Reload an IPython extension by its module name."""
64 61 if not module_str:
65 62 raise UsageError('Missing module name.')
66 63 self.shell.extension_manager.reload_extension(module_str)
@@ -1,793 +1,792 b''
1 1 """Implementation of magic functions for interaction with the OS.
2 2
3 3 Note: this module is named 'osm' instead of 'os' to avoid a collision with the
4 4 builtin.
5 5 """
6 6 # Copyright (c) IPython Development Team.
7 7 # Distributed under the terms of the Modified BSD License.
8 8
9 9 import io
10 10 import os
11 11 import re
12 12 import sys
13 13 from pprint import pformat
14 14
15 15 from IPython.core import magic_arguments
16 16 from IPython.core import oinspect
17 17 from IPython.core import page
18 18 from IPython.core.alias import AliasError, Alias
19 19 from IPython.core.error import UsageError
20 20 from IPython.core.magic import (
21 21 Magics, compress_dhist, magics_class, line_magic, cell_magic, line_cell_magic
22 22 )
23 23 from IPython.testing.skipdoctest import skip_doctest
24 24 from IPython.utils.openpy import source_to_unicode
25 25 from IPython.utils.process import abbrev_cwd
26 from IPython.utils import py3compat
27 26 from IPython.utils.terminal import set_term_title
28 27
29 28
30 29 @magics_class
31 30 class OSMagics(Magics):
32 31 """Magics to interact with the underlying OS (shell-type functionality).
33 32 """
34 33
35 34 @skip_doctest
36 35 @line_magic
37 36 def alias(self, parameter_s=''):
38 37 """Define an alias for a system command.
39 38
40 39 '%alias alias_name cmd' defines 'alias_name' as an alias for 'cmd'
41 40
42 41 Then, typing 'alias_name params' will execute the system command 'cmd
43 42 params' (from your underlying operating system).
44 43
45 44 Aliases have lower precedence than magic functions and Python normal
46 45 variables, so if 'foo' is both a Python variable and an alias, the
47 46 alias can not be executed until 'del foo' removes the Python variable.
48 47
49 48 You can use the %l specifier in an alias definition to represent the
50 49 whole line when the alias is called. For example::
51 50
52 51 In [2]: alias bracket echo "Input in brackets: <%l>"
53 52 In [3]: bracket hello world
54 53 Input in brackets: <hello world>
55 54
56 55 You can also define aliases with parameters using %s specifiers (one
57 56 per parameter)::
58 57
59 58 In [1]: alias parts echo first %s second %s
60 59 In [2]: %parts A B
61 60 first A second B
62 61 In [3]: %parts A
63 62 Incorrect number of arguments: 2 expected.
64 63 parts is an alias to: 'echo first %s second %s'
65 64
66 65 Note that %l and %s are mutually exclusive. You can only use one or
67 66 the other in your aliases.
68 67
69 68 Aliases expand Python variables just like system calls using ! or !!
70 69 do: all expressions prefixed with '$' get expanded. For details of
71 70 the semantic rules, see PEP-215:
72 71 http://www.python.org/peps/pep-0215.html. This is the library used by
73 72 IPython for variable expansion. If you want to access a true shell
74 73 variable, an extra $ is necessary to prevent its expansion by
75 74 IPython::
76 75
77 76 In [6]: alias show echo
78 77 In [7]: PATH='A Python string'
79 78 In [8]: show $PATH
80 79 A Python string
81 80 In [9]: show $$PATH
82 81 /usr/local/lf9560/bin:/usr/local/intel/compiler70/ia32/bin:...
83 82
84 83 You can use the alias facility to access all of $PATH. See the %rehashx
85 84 function, which automatically creates aliases for the contents of your
86 85 $PATH.
87 86
88 87 If called with no parameters, %alias prints the current alias table
89 88 for your system. For posix systems, the default aliases are 'cat',
90 89 'cp', 'mv', 'rm', 'rmdir', and 'mkdir', and other platform-specific
91 90 aliases are added. For windows-based systems, the default aliases are
92 91 'copy', 'ddir', 'echo', 'ls', 'ldir', 'mkdir', 'ren', and 'rmdir'.
93 92
94 93 You can see the definition of alias by adding a question mark in the
95 94 end::
96 95
97 96 In [1]: cat?
98 97 Repr: <alias cat for 'cat'>"""
99 98
100 99 par = parameter_s.strip()
101 100 if not par:
102 101 aliases = sorted(self.shell.alias_manager.aliases)
103 102 # stored = self.shell.db.get('stored_aliases', {} )
104 103 # for k, v in stored:
105 104 # atab.append(k, v[0])
106 105
107 106 print("Total number of aliases:", len(aliases))
108 107 sys.stdout.flush()
109 108 return aliases
110 109
111 110 # Now try to define a new one
112 111 try:
113 112 alias,cmd = par.split(None, 1)
114 113 except TypeError:
115 114 print(oinspect.getdoc(self.alias))
116 115 return
117 116
118 117 try:
119 118 self.shell.alias_manager.define_alias(alias, cmd)
120 119 except AliasError as e:
121 120 print(e)
122 121 # end magic_alias
123 122
124 123 @line_magic
125 124 def unalias(self, parameter_s=''):
126 125 """Remove an alias"""
127 126
128 127 aname = parameter_s.strip()
129 128 try:
130 129 self.shell.alias_manager.undefine_alias(aname)
131 130 except ValueError as e:
132 131 print(e)
133 132 return
134 133
135 134 stored = self.shell.db.get('stored_aliases', {} )
136 135 if aname in stored:
137 136 print("Removing %stored alias",aname)
138 137 del stored[aname]
139 138 self.shell.db['stored_aliases'] = stored
140 139
141 140 @line_magic
142 141 def rehashx(self, parameter_s=''):
143 142 """Update the alias table with all executable files in $PATH.
144 143
145 144 rehashx explicitly checks that every entry in $PATH is a file
146 145 with execute access (os.X_OK).
147 146
148 147 Under Windows, it checks executability as a match against a
149 148 '|'-separated string of extensions, stored in the IPython config
150 149 variable win_exec_ext. This defaults to 'exe|com|bat'.
151 150
152 151 This function also resets the root module cache of module completer,
153 152 used on slow filesystems.
154 153 """
155 154 from IPython.core.alias import InvalidAliasError
156 155
157 156 # for the benefit of module completer in ipy_completers.py
158 157 del self.shell.db['rootmodules_cache']
159 158
160 159 path = [os.path.abspath(os.path.expanduser(p)) for p in
161 160 os.environ.get('PATH','').split(os.pathsep)]
162 161
163 162 syscmdlist = []
164 163 # Now define isexec in a cross platform manner.
165 164 if os.name == 'posix':
166 165 isexec = lambda fname:os.path.isfile(fname) and \
167 166 os.access(fname,os.X_OK)
168 167 else:
169 168 try:
170 169 winext = os.environ['pathext'].replace(';','|').replace('.','')
171 170 except KeyError:
172 171 winext = 'exe|com|bat|py'
173 172 if 'py' not in winext:
174 173 winext += '|py'
175 174 execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE)
176 175 isexec = lambda fname:os.path.isfile(fname) and execre.match(fname)
177 176 savedir = os.getcwd()
178 177
179 178 # Now walk the paths looking for executables to alias.
180 179 try:
181 180 # write the whole loop for posix/Windows so we don't have an if in
182 181 # the innermost part
183 182 if os.name == 'posix':
184 183 for pdir in path:
185 184 try:
186 185 os.chdir(pdir)
187 186 dirlist = os.listdir(pdir)
188 187 except OSError:
189 188 continue
190 189 for ff in dirlist:
191 190 if isexec(ff):
192 191 try:
193 192 # Removes dots from the name since ipython
194 193 # will assume names with dots to be python.
195 194 if not self.shell.alias_manager.is_alias(ff):
196 195 self.shell.alias_manager.define_alias(
197 196 ff.replace('.',''), ff)
198 197 except InvalidAliasError:
199 198 pass
200 199 else:
201 200 syscmdlist.append(ff)
202 201 else:
203 202 no_alias = Alias.blacklist
204 203 for pdir in path:
205 204 try:
206 205 os.chdir(pdir)
207 206 dirlist = os.listdir(pdir)
208 207 except OSError:
209 208 continue
210 209 for ff in dirlist:
211 210 base, ext = os.path.splitext(ff)
212 211 if isexec(ff) and base.lower() not in no_alias:
213 212 if ext.lower() == '.exe':
214 213 ff = base
215 214 try:
216 215 # Removes dots from the name since ipython
217 216 # will assume names with dots to be python.
218 217 self.shell.alias_manager.define_alias(
219 218 base.lower().replace('.',''), ff)
220 219 except InvalidAliasError:
221 220 pass
222 221 syscmdlist.append(ff)
223 222 self.shell.db['syscmdlist'] = syscmdlist
224 223 finally:
225 224 os.chdir(savedir)
226 225
227 226 @skip_doctest
228 227 @line_magic
229 228 def pwd(self, parameter_s=''):
230 229 """Return the current working directory path.
231 230
232 231 Examples
233 232 --------
234 233 ::
235 234
236 235 In [9]: pwd
237 236 Out[9]: '/home/tsuser/sprint/ipython'
238 237 """
239 238 try:
240 239 return os.getcwd()
241 240 except FileNotFoundError:
242 241 raise UsageError("CWD no longer exists - please use %cd to change directory.")
243 242
244 243 @skip_doctest
245 244 @line_magic
246 245 def cd(self, parameter_s=''):
247 246 """Change the current working directory.
248 247
249 248 This command automatically maintains an internal list of directories
250 249 you visit during your IPython session, in the variable _dh. The
251 250 command %dhist shows this history nicely formatted. You can also
252 251 do 'cd -<tab>' to see directory history conveniently.
253 252
254 253 Usage:
255 254
256 255 cd 'dir': changes to directory 'dir'.
257 256
258 257 cd -: changes to the last visited directory.
259 258
260 259 cd -<n>: changes to the n-th directory in the directory history.
261 260
262 261 cd --foo: change to directory that matches 'foo' in history
263 262
264 263 cd -b <bookmark_name>: jump to a bookmark set by %bookmark
265 264 (note: cd <bookmark_name> is enough if there is no
266 265 directory <bookmark_name>, but a bookmark with the name exists.)
267 266 'cd -b <tab>' allows you to tab-complete bookmark names.
268 267
269 268 Options:
270 269
271 270 -q: quiet. Do not print the working directory after the cd command is
272 271 executed. By default IPython's cd command does print this directory,
273 272 since the default prompts do not display path information.
274 273
275 274 Note that !cd doesn't work for this purpose because the shell where
276 275 !command runs is immediately discarded after executing 'command'.
277 276
278 277 Examples
279 278 --------
280 279 ::
281 280
282 281 In [10]: cd parent/child
283 282 /home/tsuser/parent/child
284 283 """
285 284
286 285 try:
287 286 oldcwd = os.getcwd()
288 287 except FileNotFoundError:
289 288 # Happens if the CWD has been deleted.
290 289 oldcwd = None
291 290
292 291 numcd = re.match(r'(-)(\d+)$',parameter_s)
293 292 # jump in directory history by number
294 293 if numcd:
295 294 nn = int(numcd.group(2))
296 295 try:
297 296 ps = self.shell.user_ns['_dh'][nn]
298 297 except IndexError:
299 298 print('The requested directory does not exist in history.')
300 299 return
301 300 else:
302 301 opts = {}
303 302 elif parameter_s.startswith('--'):
304 303 ps = None
305 304 fallback = None
306 305 pat = parameter_s[2:]
307 306 dh = self.shell.user_ns['_dh']
308 307 # first search only by basename (last component)
309 308 for ent in reversed(dh):
310 309 if pat in os.path.basename(ent) and os.path.isdir(ent):
311 310 ps = ent
312 311 break
313 312
314 313 if fallback is None and pat in ent and os.path.isdir(ent):
315 314 fallback = ent
316 315
317 316 # if we have no last part match, pick the first full path match
318 317 if ps is None:
319 318 ps = fallback
320 319
321 320 if ps is None:
322 321 print("No matching entry in directory history")
323 322 return
324 323 else:
325 324 opts = {}
326 325
327 326
328 327 else:
329 328 opts, ps = self.parse_options(parameter_s, 'qb', mode='string')
330 329 # jump to previous
331 330 if ps == '-':
332 331 try:
333 332 ps = self.shell.user_ns['_dh'][-2]
334 333 except IndexError:
335 334 raise UsageError('%cd -: No previous directory to change to.')
336 335 # jump to bookmark if needed
337 336 else:
338 337 if not os.path.isdir(ps) or 'b' in opts:
339 338 bkms = self.shell.db.get('bookmarks', {})
340 339
341 340 if ps in bkms:
342 341 target = bkms[ps]
343 342 print('(bookmark:%s) -> %s' % (ps, target))
344 343 ps = target
345 344 else:
346 345 if 'b' in opts:
347 346 raise UsageError("Bookmark '%s' not found. "
348 347 "Use '%%bookmark -l' to see your bookmarks." % ps)
349 348
350 349 # at this point ps should point to the target dir
351 350 if ps:
352 351 try:
353 352 os.chdir(os.path.expanduser(ps))
354 353 if hasattr(self.shell, 'term_title') and self.shell.term_title:
355 354 set_term_title(self.shell.term_title_format.format(cwd=abbrev_cwd()))
356 355 except OSError:
357 356 print(sys.exc_info()[1])
358 357 else:
359 358 cwd = os.getcwd()
360 359 dhist = self.shell.user_ns['_dh']
361 360 if oldcwd != cwd:
362 361 dhist.append(cwd)
363 362 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
364 363
365 364 else:
366 365 os.chdir(self.shell.home_dir)
367 366 if hasattr(self.shell, 'term_title') and self.shell.term_title:
368 367 set_term_title(self.shell.term_title_format.format(cwd="~"))
369 368 cwd = os.getcwd()
370 369 dhist = self.shell.user_ns['_dh']
371 370
372 371 if oldcwd != cwd:
373 372 dhist.append(cwd)
374 373 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
375 374 if not 'q' in opts and self.shell.user_ns['_dh']:
376 375 print(self.shell.user_ns['_dh'][-1])
377 376
378 377 @line_magic
379 378 def env(self, parameter_s=''):
380 379 """Get, set, or list environment variables.
381 380
382 381 Usage:\\
383 382
384 383 %env: lists all environment variables/values
385 384 %env var: get value for var
386 385 %env var val: set value for var
387 386 %env var=val: set value for var
388 387 %env var=$val: set value for var, using python expansion if possible
389 388 """
390 389 if parameter_s.strip():
391 390 split = '=' if '=' in parameter_s else ' '
392 391 bits = parameter_s.split(split)
393 392 if len(bits) == 1:
394 393 key = parameter_s.strip()
395 394 if key in os.environ:
396 395 return os.environ[key]
397 396 else:
398 397 err = "Environment does not have key: {0}".format(key)
399 398 raise UsageError(err)
400 399 if len(bits) > 1:
401 400 return self.set_env(parameter_s)
402 401 return dict(os.environ)
403 402
404 403 @line_magic
405 404 def set_env(self, parameter_s):
406 405 """Set environment variables. Assumptions are that either "val" is a
407 406 name in the user namespace, or val is something that evaluates to a
408 407 string.
409 408
410 409 Usage:\\
411 410 %set_env var val: set value for var
412 411 %set_env var=val: set value for var
413 412 %set_env var=$val: set value for var, using python expansion if possible
414 413 """
415 414 split = '=' if '=' in parameter_s else ' '
416 415 bits = parameter_s.split(split, 1)
417 416 if not parameter_s.strip() or len(bits)<2:
418 417 raise UsageError("usage is 'set_env var=val'")
419 418 var = bits[0].strip()
420 419 val = bits[1].strip()
421 420 if re.match(r'.*\s.*', var):
422 421 # an environment variable with whitespace is almost certainly
423 422 # not what the user intended. what's more likely is the wrong
424 423 # split was chosen, ie for "set_env cmd_args A=B", we chose
425 424 # '=' for the split and should have chosen ' '. to get around
426 425 # this, users should just assign directly to os.environ or use
427 426 # standard magic {var} expansion.
428 427 err = "refusing to set env var with whitespace: '{0}'"
429 428 err = err.format(val)
430 429 raise UsageError(err)
431 430 os.environ[var] = val
432 431 print('env: {0}={1}'.format(var,val))
433 432
434 433 @line_magic
435 434 def pushd(self, parameter_s=''):
436 435 """Place the current dir on stack and change directory.
437 436
438 437 Usage:\\
439 438 %pushd ['dirname']
440 439 """
441 440
442 441 dir_s = self.shell.dir_stack
443 442 tgt = os.path.expanduser(parameter_s)
444 443 cwd = os.getcwd().replace(self.shell.home_dir,'~')
445 444 if tgt:
446 445 self.cd(parameter_s)
447 446 dir_s.insert(0,cwd)
448 447 return self.shell.magic('dirs')
449 448
450 449 @line_magic
451 450 def popd(self, parameter_s=''):
452 451 """Change to directory popped off the top of the stack.
453 452 """
454 453 if not self.shell.dir_stack:
455 454 raise UsageError("%popd on empty stack")
456 455 top = self.shell.dir_stack.pop(0)
457 456 self.cd(top)
458 457 print("popd ->",top)
459 458
460 459 @line_magic
461 460 def dirs(self, parameter_s=''):
462 461 """Return the current directory stack."""
463 462
464 463 return self.shell.dir_stack
465 464
466 465 @line_magic
467 466 def dhist(self, parameter_s=''):
468 467 """Print your history of visited directories.
469 468
470 469 %dhist -> print full history\\
471 470 %dhist n -> print last n entries only\\
472 471 %dhist n1 n2 -> print entries between n1 and n2 (n2 not included)\\
473 472
474 473 This history is automatically maintained by the %cd command, and
475 474 always available as the global list variable _dh. You can use %cd -<n>
476 475 to go to directory number <n>.
477 476
478 477 Note that most of time, you should view directory history by entering
479 478 cd -<TAB>.
480 479
481 480 """
482 481
483 482 dh = self.shell.user_ns['_dh']
484 483 if parameter_s:
485 484 try:
486 485 args = map(int,parameter_s.split())
487 486 except:
488 487 self.arg_err(self.dhist)
489 488 return
490 489 if len(args) == 1:
491 490 ini,fin = max(len(dh)-(args[0]),0),len(dh)
492 491 elif len(args) == 2:
493 492 ini,fin = args
494 493 fin = min(fin, len(dh))
495 494 else:
496 495 self.arg_err(self.dhist)
497 496 return
498 497 else:
499 498 ini,fin = 0,len(dh)
500 499 print('Directory history (kept in _dh)')
501 500 for i in range(ini, fin):
502 501 print("%d: %s" % (i, dh[i]))
503 502
504 503 @skip_doctest
505 504 @line_magic
506 505 def sc(self, parameter_s=''):
507 506 """Shell capture - run shell command and capture output (DEPRECATED use !).
508 507
509 508 DEPRECATED. Suboptimal, retained for backwards compatibility.
510 509
511 510 You should use the form 'var = !command' instead. Example:
512 511
513 512 "%sc -l myfiles = ls ~" should now be written as
514 513
515 514 "myfiles = !ls ~"
516 515
517 516 myfiles.s, myfiles.l and myfiles.n still apply as documented
518 517 below.
519 518
520 519 --
521 520 %sc [options] varname=command
522 521
523 522 IPython will run the given command using commands.getoutput(), and
524 523 will then update the user's interactive namespace with a variable
525 524 called varname, containing the value of the call. Your command can
526 525 contain shell wildcards, pipes, etc.
527 526
528 527 The '=' sign in the syntax is mandatory, and the variable name you
529 528 supply must follow Python's standard conventions for valid names.
530 529
531 530 (A special format without variable name exists for internal use)
532 531
533 532 Options:
534 533
535 534 -l: list output. Split the output on newlines into a list before
536 535 assigning it to the given variable. By default the output is stored
537 536 as a single string.
538 537
539 538 -v: verbose. Print the contents of the variable.
540 539
541 540 In most cases you should not need to split as a list, because the
542 541 returned value is a special type of string which can automatically
543 542 provide its contents either as a list (split on newlines) or as a
544 543 space-separated string. These are convenient, respectively, either
545 544 for sequential processing or to be passed to a shell command.
546 545
547 546 For example::
548 547
549 548 # Capture into variable a
550 549 In [1]: sc a=ls *py
551 550
552 551 # a is a string with embedded newlines
553 552 In [2]: a
554 553 Out[2]: 'setup.py\\nwin32_manual_post_install.py'
555 554
556 555 # which can be seen as a list:
557 556 In [3]: a.l
558 557 Out[3]: ['setup.py', 'win32_manual_post_install.py']
559 558
560 559 # or as a whitespace-separated string:
561 560 In [4]: a.s
562 561 Out[4]: 'setup.py win32_manual_post_install.py'
563 562
564 563 # a.s is useful to pass as a single command line:
565 564 In [5]: !wc -l $a.s
566 565 146 setup.py
567 566 130 win32_manual_post_install.py
568 567 276 total
569 568
570 569 # while the list form is useful to loop over:
571 570 In [6]: for f in a.l:
572 571 ...: !wc -l $f
573 572 ...:
574 573 146 setup.py
575 574 130 win32_manual_post_install.py
576 575
577 576 Similarly, the lists returned by the -l option are also special, in
578 577 the sense that you can equally invoke the .s attribute on them to
579 578 automatically get a whitespace-separated string from their contents::
580 579
581 580 In [7]: sc -l b=ls *py
582 581
583 582 In [8]: b
584 583 Out[8]: ['setup.py', 'win32_manual_post_install.py']
585 584
586 585 In [9]: b.s
587 586 Out[9]: 'setup.py win32_manual_post_install.py'
588 587
589 588 In summary, both the lists and strings used for output capture have
590 589 the following special attributes::
591 590
592 591 .l (or .list) : value as list.
593 592 .n (or .nlstr): value as newline-separated string.
594 593 .s (or .spstr): value as space-separated string.
595 594 """
596 595
597 596 opts,args = self.parse_options(parameter_s, 'lv')
598 597 # Try to get a variable name and command to run
599 598 try:
600 599 # the variable name must be obtained from the parse_options
601 600 # output, which uses shlex.split to strip options out.
602 601 var,_ = args.split('=', 1)
603 602 var = var.strip()
604 603 # But the command has to be extracted from the original input
605 604 # parameter_s, not on what parse_options returns, to avoid the
606 605 # quote stripping which shlex.split performs on it.
607 606 _,cmd = parameter_s.split('=', 1)
608 607 except ValueError:
609 608 var,cmd = '',''
610 609 # If all looks ok, proceed
611 610 split = 'l' in opts
612 611 out = self.shell.getoutput(cmd, split=split)
613 612 if 'v' in opts:
614 613 print('%s ==\n%s' % (var, pformat(out)))
615 614 if var:
616 615 self.shell.user_ns.update({var:out})
617 616 else:
618 617 return out
619 618
620 619 @line_cell_magic
621 620 def sx(self, line='', cell=None):
622 621 """Shell execute - run shell command and capture output (!! is short-hand).
623 622
624 623 %sx command
625 624
626 625 IPython will run the given command using commands.getoutput(), and
627 626 return the result formatted as a list (split on '\\n'). Since the
628 627 output is _returned_, it will be stored in ipython's regular output
629 628 cache Out[N] and in the '_N' automatic variables.
630 629
631 630 Notes:
632 631
633 632 1) If an input line begins with '!!', then %sx is automatically
634 633 invoked. That is, while::
635 634
636 635 !ls
637 636
638 637 causes ipython to simply issue system('ls'), typing::
639 638
640 639 !!ls
641 640
642 641 is a shorthand equivalent to::
643 642
644 643 %sx ls
645 644
646 645 2) %sx differs from %sc in that %sx automatically splits into a list,
647 646 like '%sc -l'. The reason for this is to make it as easy as possible
648 647 to process line-oriented shell output via further python commands.
649 648 %sc is meant to provide much finer control, but requires more
650 649 typing.
651 650
652 651 3) Just like %sc -l, this is a list with special attributes:
653 652 ::
654 653
655 654 .l (or .list) : value as list.
656 655 .n (or .nlstr): value as newline-separated string.
657 656 .s (or .spstr): value as whitespace-separated string.
658 657
659 658 This is very useful when trying to use such lists as arguments to
660 659 system commands."""
661 660
662 661 if cell is None:
663 662 # line magic
664 663 return self.shell.getoutput(line)
665 664 else:
666 665 opts,args = self.parse_options(line, '', 'out=')
667 666 output = self.shell.getoutput(cell)
668 667 out_name = opts.get('out', opts.get('o'))
669 668 if out_name:
670 669 self.shell.user_ns[out_name] = output
671 670 else:
672 671 return output
673 672
674 673 system = line_cell_magic('system')(sx)
675 674 bang = cell_magic('!')(sx)
676 675
677 676 @line_magic
678 677 def bookmark(self, parameter_s=''):
679 678 """Manage IPython's bookmark system.
680 679
681 680 %bookmark <name> - set bookmark to current dir
682 681 %bookmark <name> <dir> - set bookmark to <dir>
683 682 %bookmark -l - list all bookmarks
684 683 %bookmark -d <name> - remove bookmark
685 684 %bookmark -r - remove all bookmarks
686 685
687 686 You can later on access a bookmarked folder with::
688 687
689 688 %cd -b <name>
690 689
691 690 or simply '%cd <name>' if there is no directory called <name> AND
692 691 there is such a bookmark defined.
693 692
694 693 Your bookmarks persist through IPython sessions, but they are
695 694 associated with each profile."""
696 695
697 696 opts,args = self.parse_options(parameter_s,'drl',mode='list')
698 697 if len(args) > 2:
699 698 raise UsageError("%bookmark: too many arguments")
700 699
701 700 bkms = self.shell.db.get('bookmarks',{})
702 701
703 702 if 'd' in opts:
704 703 try:
705 704 todel = args[0]
706 705 except IndexError:
707 706 raise UsageError(
708 707 "%bookmark -d: must provide a bookmark to delete")
709 708 else:
710 709 try:
711 710 del bkms[todel]
712 711 except KeyError:
713 712 raise UsageError(
714 713 "%%bookmark -d: Can't delete bookmark '%s'" % todel)
715 714
716 715 elif 'r' in opts:
717 716 bkms = {}
718 717 elif 'l' in opts:
719 718 bks = sorted(bkms)
720 719 if bks:
721 720 size = max(map(len, bks))
722 721 else:
723 722 size = 0
724 723 fmt = '%-'+str(size)+'s -> %s'
725 724 print('Current bookmarks:')
726 725 for bk in bks:
727 726 print(fmt % (bk, bkms[bk]))
728 727 else:
729 728 if not args:
730 729 raise UsageError("%bookmark: You must specify the bookmark name")
731 730 elif len(args)==1:
732 731 bkms[args[0]] = os.getcwd()
733 732 elif len(args)==2:
734 733 bkms[args[0]] = args[1]
735 734 self.shell.db['bookmarks'] = bkms
736 735
737 736 @line_magic
738 737 def pycat(self, parameter_s=''):
739 738 """Show a syntax-highlighted file through a pager.
740 739
741 740 This magic is similar to the cat utility, but it will assume the file
742 741 to be Python source and will show it with syntax highlighting.
743 742
744 743 This magic command can either take a local filename, an url,
745 744 an history range (see %history) or a macro as argument ::
746 745
747 746 %pycat myscript.py
748 747 %pycat 7-27
749 748 %pycat myMacro
750 749 %pycat http://www.example.com/myscript.py
751 750 """
752 751 if not parameter_s:
753 752 raise UsageError('Missing filename, URL, input history range, '
754 753 'or macro.')
755 754
756 755 try :
757 756 cont = self.shell.find_user_code(parameter_s, skip_encoding_cookie=False)
758 757 except (ValueError, IOError):
759 758 print("Error: no such file, variable, URL, history range or macro")
760 759 return
761 760
762 761 page.page(self.shell.pycolorize(source_to_unicode(cont)))
763 762
764 763 @magic_arguments.magic_arguments()
765 764 @magic_arguments.argument(
766 765 '-a', '--append', action='store_true', default=False,
767 766 help='Append contents of the cell to an existing file. '
768 767 'The file will be created if it does not exist.'
769 768 )
770 769 @magic_arguments.argument(
771 770 'filename', type=str,
772 771 help='file to write'
773 772 )
774 773 @cell_magic
775 774 def writefile(self, line, cell):
776 775 """Write the contents of the cell to a file.
777 776
778 777 The file will be overwritten unless the -a (--append) flag is specified.
779 778 """
780 779 args = magic_arguments.parse_argstring(self.writefile, line)
781 780 filename = os.path.expanduser(args.filename)
782 781
783 782 if os.path.exists(filename):
784 783 if args.append:
785 784 print("Appending to %s" % filename)
786 785 else:
787 786 print("Overwriting %s" % filename)
788 787 else:
789 788 print("Writing %s" % filename)
790 789
791 790 mode = 'a' if args.append else 'w'
792 791 with io.open(filename, mode, encoding='utf-8') as f:
793 792 f.write(cell)
@@ -1,313 +1,312 b''
1 1 # encoding: utf-8
2 2 """
3 3 An application for managing IPython profiles.
4 4
5 5 To be invoked as the `ipython profile` subcommand.
6 6
7 7 Authors:
8 8
9 9 * Min RK
10 10
11 11 """
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Copyright (C) 2008 The IPython Development Team
15 15 #
16 16 # Distributed under the terms of the BSD License. The full license is in
17 17 # the file COPYING, distributed as part of this software.
18 18 #-----------------------------------------------------------------------------
19 19
20 20 #-----------------------------------------------------------------------------
21 21 # Imports
22 22 #-----------------------------------------------------------------------------
23 23
24 24 import os
25 25
26 26 from traitlets.config.application import Application
27 27 from IPython.core.application import (
28 28 BaseIPythonApplication, base_flags
29 29 )
30 30 from IPython.core.profiledir import ProfileDir
31 31 from IPython.utils.importstring import import_item
32 32 from IPython.paths import get_ipython_dir, get_ipython_package_dir
33 from IPython.utils import py3compat
34 33 from traitlets import Unicode, Bool, Dict, observe
35 34
36 35 #-----------------------------------------------------------------------------
37 36 # Constants
38 37 #-----------------------------------------------------------------------------
39 38
40 39 create_help = """Create an IPython profile by name
41 40
42 41 Create an ipython profile directory by its name or
43 42 profile directory path. Profile directories contain
44 43 configuration, log and security related files and are named
45 44 using the convention 'profile_<name>'. By default they are
46 45 located in your ipython directory. Once created, you will
47 46 can edit the configuration files in the profile
48 47 directory to configure IPython. Most users will create a
49 48 profile directory by name,
50 49 `ipython profile create myprofile`, which will put the directory
51 50 in `<ipython_dir>/profile_myprofile`.
52 51 """
53 52 list_help = """List available IPython profiles
54 53
55 54 List all available profiles, by profile location, that can
56 55 be found in the current working directly or in the ipython
57 56 directory. Profile directories are named using the convention
58 57 'profile_<profile>'.
59 58 """
60 59 profile_help = """Manage IPython profiles
61 60
62 61 Profile directories contain
63 62 configuration, log and security related files and are named
64 63 using the convention 'profile_<name>'. By default they are
65 64 located in your ipython directory. You can create profiles
66 65 with `ipython profile create <name>`, or see the profiles you
67 66 already have with `ipython profile list`
68 67
69 68 To get started configuring IPython, simply do:
70 69
71 70 $> ipython profile create
72 71
73 72 and IPython will create the default profile in <ipython_dir>/profile_default,
74 73 where you can edit ipython_config.py to start configuring IPython.
75 74
76 75 """
77 76
78 77 _list_examples = "ipython profile list # list all profiles"
79 78
80 79 _create_examples = """
81 80 ipython profile create foo # create profile foo w/ default config files
82 81 ipython profile create foo --reset # restage default config files over current
83 82 ipython profile create foo --parallel # also stage parallel config files
84 83 """
85 84
86 85 _main_examples = """
87 86 ipython profile create -h # show the help string for the create subcommand
88 87 ipython profile list -h # show the help string for the list subcommand
89 88
90 89 ipython locate profile foo # print the path to the directory for profile 'foo'
91 90 """
92 91
93 92 #-----------------------------------------------------------------------------
94 93 # Profile Application Class (for `ipython profile` subcommand)
95 94 #-----------------------------------------------------------------------------
96 95
97 96
98 97 def list_profiles_in(path):
99 98 """list profiles in a given root directory"""
100 99 files = os.listdir(path)
101 100 profiles = []
102 101 for f in files:
103 102 try:
104 103 full_path = os.path.join(path, f)
105 104 except UnicodeError:
106 105 continue
107 106 if os.path.isdir(full_path) and f.startswith('profile_'):
108 107 profiles.append(f.split('_',1)[-1])
109 108 return profiles
110 109
111 110
112 111 def list_bundled_profiles():
113 112 """list profiles that are bundled with IPython."""
114 113 path = os.path.join(get_ipython_package_dir(), u'core', u'profile')
115 114 files = os.listdir(path)
116 115 profiles = []
117 116 for profile in files:
118 117 full_path = os.path.join(path, profile)
119 118 if os.path.isdir(full_path) and profile != "__pycache__":
120 119 profiles.append(profile)
121 120 return profiles
122 121
123 122
124 123 class ProfileLocate(BaseIPythonApplication):
125 124 description = """print the path to an IPython profile dir"""
126 125
127 126 def parse_command_line(self, argv=None):
128 127 super(ProfileLocate, self).parse_command_line(argv)
129 128 if self.extra_args:
130 129 self.profile = self.extra_args[0]
131 130
132 131 def start(self):
133 132 print(self.profile_dir.location)
134 133
135 134
136 135 class ProfileList(Application):
137 136 name = u'ipython-profile'
138 137 description = list_help
139 138 examples = _list_examples
140 139
141 140 aliases = Dict({
142 141 'ipython-dir' : 'ProfileList.ipython_dir',
143 142 'log-level' : 'Application.log_level',
144 143 })
145 144 flags = Dict(dict(
146 145 debug = ({'Application' : {'log_level' : 0}},
147 146 "Set Application.log_level to 0, maximizing log output."
148 147 )
149 148 ))
150 149
151 150 ipython_dir = Unicode(get_ipython_dir(),
152 151 help="""
153 152 The name of the IPython directory. This directory is used for logging
154 153 configuration (through profiles), history storage, etc. The default
155 154 is usually $HOME/.ipython. This options can also be specified through
156 155 the environment variable IPYTHONDIR.
157 156 """
158 157 ).tag(config=True)
159 158
160 159
161 160 def _print_profiles(self, profiles):
162 161 """print list of profiles, indented."""
163 162 for profile in profiles:
164 163 print(' %s' % profile)
165 164
166 165 def list_profile_dirs(self):
167 166 profiles = list_bundled_profiles()
168 167 if profiles:
169 168 print()
170 169 print("Available profiles in IPython:")
171 170 self._print_profiles(profiles)
172 171 print()
173 172 print(" The first request for a bundled profile will copy it")
174 173 print(" into your IPython directory (%s)," % self.ipython_dir)
175 174 print(" where you can customize it.")
176 175
177 176 profiles = list_profiles_in(self.ipython_dir)
178 177 if profiles:
179 178 print()
180 179 print("Available profiles in %s:" % self.ipython_dir)
181 180 self._print_profiles(profiles)
182 181
183 182 profiles = list_profiles_in(os.getcwd())
184 183 if profiles:
185 184 print()
186 185 print("Available profiles in current directory (%s):" % os.getcwd())
187 186 self._print_profiles(profiles)
188 187
189 188 print()
190 189 print("To use any of the above profiles, start IPython with:")
191 190 print(" ipython --profile=<name>")
192 191 print()
193 192
194 193 def start(self):
195 194 self.list_profile_dirs()
196 195
197 196
198 197 create_flags = {}
199 198 create_flags.update(base_flags)
200 199 # don't include '--init' flag, which implies running profile create in other apps
201 200 create_flags.pop('init')
202 201 create_flags['reset'] = ({'ProfileCreate': {'overwrite' : True}},
203 202 "reset config files in this profile to the defaults.")
204 203 create_flags['parallel'] = ({'ProfileCreate': {'parallel' : True}},
205 204 "Include the config files for parallel "
206 205 "computing apps (ipengine, ipcontroller, etc.)")
207 206
208 207
209 208 class ProfileCreate(BaseIPythonApplication):
210 209 name = u'ipython-profile'
211 210 description = create_help
212 211 examples = _create_examples
213 212 auto_create = Bool(True)
214 213 def _log_format_default(self):
215 214 return "[%(name)s] %(message)s"
216 215
217 216 def _copy_config_files_default(self):
218 217 return True
219 218
220 219 parallel = Bool(False,
221 220 help="whether to include parallel computing config files"
222 221 ).tag(config=True)
223 222
224 223 @observe('parallel')
225 224 def _parallel_changed(self, change):
226 225 parallel_files = [ 'ipcontroller_config.py',
227 226 'ipengine_config.py',
228 227 'ipcluster_config.py'
229 228 ]
230 229 if change['new']:
231 230 for cf in parallel_files:
232 231 self.config_files.append(cf)
233 232 else:
234 233 for cf in parallel_files:
235 234 if cf in self.config_files:
236 235 self.config_files.remove(cf)
237 236
238 237 def parse_command_line(self, argv):
239 238 super(ProfileCreate, self).parse_command_line(argv)
240 239 # accept positional arg as profile name
241 240 if self.extra_args:
242 241 self.profile = self.extra_args[0]
243 242
244 243 flags = Dict(create_flags)
245 244
246 245 classes = [ProfileDir]
247 246
248 247 def _import_app(self, app_path):
249 248 """import an app class"""
250 249 app = None
251 250 name = app_path.rsplit('.', 1)[-1]
252 251 try:
253 252 app = import_item(app_path)
254 253 except ImportError:
255 254 self.log.info("Couldn't import %s, config file will be excluded", name)
256 255 except Exception:
257 256 self.log.warning('Unexpected error importing %s', name, exc_info=True)
258 257 return app
259 258
260 259 def init_config_files(self):
261 260 super(ProfileCreate, self).init_config_files()
262 261 # use local imports, since these classes may import from here
263 262 from IPython.terminal.ipapp import TerminalIPythonApp
264 263 apps = [TerminalIPythonApp]
265 264 for app_path in (
266 265 'ipykernel.kernelapp.IPKernelApp',
267 266 ):
268 267 app = self._import_app(app_path)
269 268 if app is not None:
270 269 apps.append(app)
271 270 if self.parallel:
272 271 from ipyparallel.apps.ipcontrollerapp import IPControllerApp
273 272 from ipyparallel.apps.ipengineapp import IPEngineApp
274 273 from ipyparallel.apps.ipclusterapp import IPClusterStart
275 274 apps.extend([
276 275 IPControllerApp,
277 276 IPEngineApp,
278 277 IPClusterStart,
279 278 ])
280 279 for App in apps:
281 280 app = App()
282 281 app.config.update(self.config)
283 282 app.log = self.log
284 283 app.overwrite = self.overwrite
285 284 app.copy_config_files=True
286 285 app.ipython_dir=self.ipython_dir
287 286 app.profile_dir=self.profile_dir
288 287 app.init_config_files()
289 288
290 289 def stage_default_config_file(self):
291 290 pass
292 291
293 292
294 293 class ProfileApp(Application):
295 294 name = u'ipython profile'
296 295 description = profile_help
297 296 examples = _main_examples
298 297
299 298 subcommands = Dict(dict(
300 299 create = (ProfileCreate, ProfileCreate.description.splitlines()[0]),
301 300 list = (ProfileList, ProfileList.description.splitlines()[0]),
302 301 locate = (ProfileLocate, ProfileLocate.description.splitlines()[0]),
303 302 ))
304 303
305 304 def start(self):
306 305 if self.subapp is None:
307 306 print("No subcommand specified. Must specify one of: %s"%(self.subcommands.keys()))
308 307 print()
309 308 self.print_description()
310 309 self.print_subcommands()
311 310 self.exit(1)
312 311 else:
313 312 return self.subapp.start()
@@ -1,224 +1,223 b''
1 1 # encoding: utf-8
2 2 """An object for managing IPython profile directories."""
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 7 import os
8 8 import shutil
9 9 import errno
10 10
11 11 from traitlets.config.configurable import LoggingConfigurable
12 12 from IPython.paths import get_ipython_package_dir
13 13 from IPython.utils.path import expand_path, ensure_dir_exists
14 from IPython.utils import py3compat
15 14 from traitlets import Unicode, Bool, observe
16 15
17 16 #-----------------------------------------------------------------------------
18 17 # Module errors
19 18 #-----------------------------------------------------------------------------
20 19
21 20 class ProfileDirError(Exception):
22 21 pass
23 22
24 23
25 24 #-----------------------------------------------------------------------------
26 25 # Class for managing profile directories
27 26 #-----------------------------------------------------------------------------
28 27
29 28 class ProfileDir(LoggingConfigurable):
30 29 """An object to manage the profile directory and its resources.
31 30
32 31 The profile directory is used by all IPython applications, to manage
33 32 configuration, logging and security.
34 33
35 34 This object knows how to find, create and manage these directories. This
36 35 should be used by any code that wants to handle profiles.
37 36 """
38 37
39 38 security_dir_name = Unicode('security')
40 39 log_dir_name = Unicode('log')
41 40 startup_dir_name = Unicode('startup')
42 41 pid_dir_name = Unicode('pid')
43 42 static_dir_name = Unicode('static')
44 43 security_dir = Unicode(u'')
45 44 log_dir = Unicode(u'')
46 45 startup_dir = Unicode(u'')
47 46 pid_dir = Unicode(u'')
48 47 static_dir = Unicode(u'')
49 48
50 49 location = Unicode(u'',
51 50 help="""Set the profile location directly. This overrides the logic used by the
52 51 `profile` option.""",
53 52 ).tag(config=True)
54 53
55 54 _location_isset = Bool(False) # flag for detecting multiply set location
56 55 @observe('location')
57 56 def _location_changed(self, change):
58 57 if self._location_isset:
59 58 raise RuntimeError("Cannot set profile location more than once.")
60 59 self._location_isset = True
61 60 new = change['new']
62 61 ensure_dir_exists(new)
63 62
64 63 # ensure config files exist:
65 64 self.security_dir = os.path.join(new, self.security_dir_name)
66 65 self.log_dir = os.path.join(new, self.log_dir_name)
67 66 self.startup_dir = os.path.join(new, self.startup_dir_name)
68 67 self.pid_dir = os.path.join(new, self.pid_dir_name)
69 68 self.static_dir = os.path.join(new, self.static_dir_name)
70 69 self.check_dirs()
71 70
72 71 def _mkdir(self, path, mode=None):
73 72 """ensure a directory exists at a given path
74 73
75 74 This is a version of os.mkdir, with the following differences:
76 75
77 76 - returns True if it created the directory, False otherwise
78 77 - ignores EEXIST, protecting against race conditions where
79 78 the dir may have been created in between the check and
80 79 the creation
81 80 - sets permissions if requested and the dir already exists
82 81 """
83 82 if os.path.exists(path):
84 83 if mode and os.stat(path).st_mode != mode:
85 84 try:
86 85 os.chmod(path, mode)
87 86 except OSError:
88 87 self.log.warning(
89 88 "Could not set permissions on %s",
90 89 path
91 90 )
92 91 return False
93 92 try:
94 93 if mode:
95 94 os.mkdir(path, mode)
96 95 else:
97 96 os.mkdir(path)
98 97 except OSError as e:
99 98 if e.errno == errno.EEXIST:
100 99 return False
101 100 else:
102 101 raise
103 102
104 103 return True
105 104
106 105 @observe('log_dir')
107 106 def check_log_dir(self, change=None):
108 107 self._mkdir(self.log_dir)
109 108
110 109 @observe('startup_dir')
111 110 def check_startup_dir(self, change=None):
112 111 self._mkdir(self.startup_dir)
113 112
114 113 readme = os.path.join(self.startup_dir, 'README')
115 114 src = os.path.join(get_ipython_package_dir(), u'core', u'profile', u'README_STARTUP')
116 115
117 116 if not os.path.exists(src):
118 117 self.log.warning("Could not copy README_STARTUP to startup dir. Source file %s does not exist.", src)
119 118
120 119 if os.path.exists(src) and not os.path.exists(readme):
121 120 shutil.copy(src, readme)
122 121
123 122 @observe('security_dir')
124 123 def check_security_dir(self, change=None):
125 124 self._mkdir(self.security_dir, 0o40700)
126 125
127 126 @observe('pid_dir')
128 127 def check_pid_dir(self, change=None):
129 128 self._mkdir(self.pid_dir, 0o40700)
130 129
131 130 def check_dirs(self):
132 131 self.check_security_dir()
133 132 self.check_log_dir()
134 133 self.check_pid_dir()
135 134 self.check_startup_dir()
136 135
137 136 def copy_config_file(self, config_file, path=None, overwrite=False):
138 137 """Copy a default config file into the active profile directory.
139 138
140 139 Default configuration files are kept in :mod:`IPython.core.profile`.
141 140 This function moves these from that location to the working profile
142 141 directory.
143 142 """
144 143 dst = os.path.join(self.location, config_file)
145 144 if os.path.isfile(dst) and not overwrite:
146 145 return False
147 146 if path is None:
148 147 path = os.path.join(get_ipython_package_dir(), u'core', u'profile', u'default')
149 148 src = os.path.join(path, config_file)
150 149 shutil.copy(src, dst)
151 150 return True
152 151
153 152 @classmethod
154 153 def create_profile_dir(cls, profile_dir, config=None):
155 154 """Create a new profile directory given a full path.
156 155
157 156 Parameters
158 157 ----------
159 158 profile_dir : str
160 159 The full path to the profile directory. If it does exist, it will
161 160 be used. If not, it will be created.
162 161 """
163 162 return cls(location=profile_dir, config=config)
164 163
165 164 @classmethod
166 165 def create_profile_dir_by_name(cls, path, name=u'default', config=None):
167 166 """Create a profile dir by profile name and path.
168 167
169 168 Parameters
170 169 ----------
171 170 path : unicode
172 171 The path (directory) to put the profile directory in.
173 172 name : unicode
174 173 The name of the profile. The name of the profile directory will
175 174 be "profile_<profile>".
176 175 """
177 176 if not os.path.isdir(path):
178 177 raise ProfileDirError('Directory not found: %s' % path)
179 178 profile_dir = os.path.join(path, u'profile_' + name)
180 179 return cls(location=profile_dir, config=config)
181 180
182 181 @classmethod
183 182 def find_profile_dir_by_name(cls, ipython_dir, name=u'default', config=None):
184 183 """Find an existing profile dir by profile name, return its ProfileDir.
185 184
186 185 This searches through a sequence of paths for a profile dir. If it
187 186 is not found, a :class:`ProfileDirError` exception will be raised.
188 187
189 188 The search path algorithm is:
190 189 1. ``os.getcwd()``
191 190 2. ``ipython_dir``
192 191
193 192 Parameters
194 193 ----------
195 194 ipython_dir : unicode or str
196 195 The IPython directory to use.
197 196 name : unicode or str
198 197 The name of the profile. The name of the profile directory
199 198 will be "profile_<profile>".
200 199 """
201 200 dirname = u'profile_' + name
202 201 paths = [os.getcwd(), ipython_dir]
203 202 for p in paths:
204 203 profile_dir = os.path.join(p, dirname)
205 204 if os.path.isdir(profile_dir):
206 205 return cls(location=profile_dir, config=config)
207 206 else:
208 207 raise ProfileDirError('Profile directory not found in paths: %s' % dirname)
209 208
210 209 @classmethod
211 210 def find_profile_dir(cls, profile_dir, config=None):
212 211 """Find/create a profile dir and return its ProfileDir.
213 212
214 213 This will create the profile directory if it doesn't exist.
215 214
216 215 Parameters
217 216 ----------
218 217 profile_dir : unicode or str
219 218 The path of the profile directory.
220 219 """
221 220 profile_dir = expand_path(profile_dir)
222 221 if not os.path.isdir(profile_dir):
223 222 raise ProfileDirError('Profile directory not found: %s' % profile_dir)
224 223 return cls(location=profile_dir, config=config)
@@ -1,23 +1,21 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Being removed
3 3 """
4 4
5 from IPython.utils import py3compat
6
7 5 class LazyEvaluate(object):
8 6 """This is used for formatting strings with values that need to be updated
9 7 at that time, such as the current time or working directory."""
10 8 def __init__(self, func, *args, **kwargs):
11 9 self.func = func
12 10 self.args = args
13 11 self.kwargs = kwargs
14 12
15 13 def __call__(self, **kwargs):
16 14 self.kwargs.update(kwargs)
17 15 return self.func(*self.args, **self.kwargs)
18 16
19 17 def __str__(self):
20 18 return str(self())
21 19
22 20 def __format__(self, format_spec):
23 21 return format(self(), format_spec)
@@ -1,410 +1,408 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Pylab (matplotlib) support utilities."""
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 7 from io import BytesIO
8 8
9 9 from IPython.core.display import _pngxy
10 10 from IPython.utils.decorators import flag_calls
11 from IPython.utils import py3compat
12 11
13 12 # If user specifies a GUI, that dictates the backend, otherwise we read the
14 13 # user's mpl default from the mpl rc structure
15 14 backends = {'tk': 'TkAgg',
16 15 'gtk': 'GTKAgg',
17 16 'gtk3': 'GTK3Agg',
18 17 'wx': 'WXAgg',
19 18 'qt': 'Qt4Agg', # qt3 not supported
20 19 'qt4': 'Qt4Agg',
21 20 'qt5': 'Qt5Agg',
22 21 'osx': 'MacOSX',
23 22 'nbagg': 'nbAgg',
24 23 'notebook': 'nbAgg',
25 24 'agg': 'agg',
26 25 'inline': 'module://ipykernel.pylab.backend_inline',
27 26 'ipympl': 'module://ipympl.backend_nbagg',
28 27 }
29 28
30 29 # We also need a reverse backends2guis mapping that will properly choose which
31 30 # GUI support to activate based on the desired matplotlib backend. For the
32 31 # most part it's just a reverse of the above dict, but we also need to add a
33 32 # few others that map to the same GUI manually:
34 33 backend2gui = dict(zip(backends.values(), backends.keys()))
35 34 # Our tests expect backend2gui to just return 'qt'
36 35 backend2gui['Qt4Agg'] = 'qt'
37 36 # In the reverse mapping, there are a few extra valid matplotlib backends that
38 37 # map to the same GUI support
39 38 backend2gui['GTK'] = backend2gui['GTKCairo'] = 'gtk'
40 39 backend2gui['GTK3Cairo'] = 'gtk3'
41 40 backend2gui['WX'] = 'wx'
42 41 backend2gui['CocoaAgg'] = 'osx'
43 42 # And some backends that don't need GUI integration
44 43 del backend2gui['nbAgg']
45 44 del backend2gui['agg']
46 45 del backend2gui['module://ipykernel.pylab.backend_inline']
47 46
48 47 #-----------------------------------------------------------------------------
49 48 # Matplotlib utilities
50 49 #-----------------------------------------------------------------------------
51 50
52 51
53 52 def getfigs(*fig_nums):
54 53 """Get a list of matplotlib figures by figure numbers.
55 54
56 55 If no arguments are given, all available figures are returned. If the
57 56 argument list contains references to invalid figures, a warning is printed
58 57 but the function continues pasting further figures.
59 58
60 59 Parameters
61 60 ----------
62 61 figs : tuple
63 62 A tuple of ints giving the figure numbers of the figures to return.
64 63 """
65 64 from matplotlib._pylab_helpers import Gcf
66 65 if not fig_nums:
67 66 fig_managers = Gcf.get_all_fig_managers()
68 67 return [fm.canvas.figure for fm in fig_managers]
69 68 else:
70 69 figs = []
71 70 for num in fig_nums:
72 71 f = Gcf.figs.get(num)
73 72 if f is None:
74 73 print('Warning: figure %s not available.' % num)
75 74 else:
76 75 figs.append(f.canvas.figure)
77 76 return figs
78 77
79 78
80 79 def figsize(sizex, sizey):
81 80 """Set the default figure size to be [sizex, sizey].
82 81
83 82 This is just an easy to remember, convenience wrapper that sets::
84 83
85 84 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
86 85 """
87 86 import matplotlib
88 87 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
89 88
90 89
91 90 def print_figure(fig, fmt='png', bbox_inches='tight', **kwargs):
92 91 """Print a figure to an image, and return the resulting file data
93 92
94 93 Returned data will be bytes unless ``fmt='svg'``,
95 94 in which case it will be unicode.
96 95
97 96 Any keyword args are passed to fig.canvas.print_figure,
98 97 such as ``quality`` or ``bbox_inches``.
99 98 """
100 from matplotlib import rcParams
101 99 # When there's an empty figure, we shouldn't return anything, otherwise we
102 100 # get big blank areas in the qt console.
103 101 if not fig.axes and not fig.lines:
104 102 return
105 103
106 104 dpi = fig.dpi
107 105 if fmt == 'retina':
108 106 dpi = dpi * 2
109 107 fmt = 'png'
110 108
111 109 # build keyword args
112 110 kw = {
113 111 "format":fmt,
114 112 "facecolor":fig.get_facecolor(),
115 113 "edgecolor":fig.get_edgecolor(),
116 114 "dpi":dpi,
117 115 "bbox_inches":bbox_inches,
118 116 }
119 117 # **kwargs get higher priority
120 118 kw.update(kwargs)
121 119
122 120 bytes_io = BytesIO()
123 121 fig.canvas.print_figure(bytes_io, **kw)
124 122 data = bytes_io.getvalue()
125 123 if fmt == 'svg':
126 124 data = data.decode('utf-8')
127 125 return data
128 126
129 127 def retina_figure(fig, **kwargs):
130 128 """format a figure as a pixel-doubled (retina) PNG"""
131 129 pngdata = print_figure(fig, fmt='retina', **kwargs)
132 130 # Make sure that retina_figure acts just like print_figure and returns
133 131 # None when the figure is empty.
134 132 if pngdata is None:
135 133 return
136 134 w, h = _pngxy(pngdata)
137 135 metadata = {"width": w//2, "height":h//2}
138 136 return pngdata, metadata
139 137
140 138 # We need a little factory function here to create the closure where
141 139 # safe_execfile can live.
142 140 def mpl_runner(safe_execfile):
143 141 """Factory to return a matplotlib-enabled runner for %run.
144 142
145 143 Parameters
146 144 ----------
147 145 safe_execfile : function
148 146 This must be a function with the same interface as the
149 147 :meth:`safe_execfile` method of IPython.
150 148
151 149 Returns
152 150 -------
153 151 A function suitable for use as the ``runner`` argument of the %run magic
154 152 function.
155 153 """
156 154
157 155 def mpl_execfile(fname,*where,**kw):
158 156 """matplotlib-aware wrapper around safe_execfile.
159 157
160 158 Its interface is identical to that of the :func:`execfile` builtin.
161 159
162 160 This is ultimately a call to execfile(), but wrapped in safeties to
163 161 properly handle interactive rendering."""
164 162
165 163 import matplotlib
166 164 import matplotlib.pyplot as plt
167 165
168 166 #print '*** Matplotlib runner ***' # dbg
169 167 # turn off rendering until end of script
170 168 is_interactive = matplotlib.rcParams['interactive']
171 169 matplotlib.interactive(False)
172 170 safe_execfile(fname,*where,**kw)
173 171 matplotlib.interactive(is_interactive)
174 172 # make rendering call now, if the user tried to do it
175 173 if plt.draw_if_interactive.called:
176 174 plt.draw()
177 175 plt.draw_if_interactive.called = False
178 176
179 177 # re-draw everything that is stale
180 178 try:
181 179 da = plt.draw_all
182 180 except AttributeError:
183 181 pass
184 182 else:
185 183 da()
186 184
187 185 return mpl_execfile
188 186
189 187
190 188 def _reshow_nbagg_figure(fig):
191 189 """reshow an nbagg figure"""
192 190 try:
193 191 reshow = fig.canvas.manager.reshow
194 192 except AttributeError:
195 193 raise NotImplementedError()
196 194 else:
197 195 reshow()
198 196
199 197
200 198 def select_figure_formats(shell, formats, **kwargs):
201 199 """Select figure formats for the inline backend.
202 200
203 201 Parameters
204 202 ==========
205 203 shell : InteractiveShell
206 204 The main IPython instance.
207 205 formats : str or set
208 206 One or a set of figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
209 207 **kwargs : any
210 208 Extra keyword arguments to be passed to fig.canvas.print_figure.
211 209 """
212 210 import matplotlib
213 211 from matplotlib.figure import Figure
214 212
215 213 svg_formatter = shell.display_formatter.formatters['image/svg+xml']
216 214 png_formatter = shell.display_formatter.formatters['image/png']
217 215 jpg_formatter = shell.display_formatter.formatters['image/jpeg']
218 216 pdf_formatter = shell.display_formatter.formatters['application/pdf']
219 217
220 218 if isinstance(formats, str):
221 219 formats = {formats}
222 220 # cast in case of list / tuple
223 221 formats = set(formats)
224 222
225 223 [ f.pop(Figure, None) for f in shell.display_formatter.formatters.values() ]
226 224 mplbackend = matplotlib.get_backend().lower()
227 225 if mplbackend == 'nbagg' or mplbackend == 'module://ipympl.backend_nbagg':
228 226 formatter = shell.display_formatter.ipython_display_formatter
229 227 formatter.for_type(Figure, _reshow_nbagg_figure)
230 228
231 229 supported = {'png', 'png2x', 'retina', 'jpg', 'jpeg', 'svg', 'pdf'}
232 230 bad = formats.difference(supported)
233 231 if bad:
234 232 bs = "%s" % ','.join([repr(f) for f in bad])
235 233 gs = "%s" % ','.join([repr(f) for f in supported])
236 234 raise ValueError("supported formats are: %s not %s" % (gs, bs))
237 235
238 236 if 'png' in formats:
239 237 png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png', **kwargs))
240 238 if 'retina' in formats or 'png2x' in formats:
241 239 png_formatter.for_type(Figure, lambda fig: retina_figure(fig, **kwargs))
242 240 if 'jpg' in formats or 'jpeg' in formats:
243 241 jpg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'jpg', **kwargs))
244 242 if 'svg' in formats:
245 243 svg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'svg', **kwargs))
246 244 if 'pdf' in formats:
247 245 pdf_formatter.for_type(Figure, lambda fig: print_figure(fig, 'pdf', **kwargs))
248 246
249 247 #-----------------------------------------------------------------------------
250 248 # Code for initializing matplotlib and importing pylab
251 249 #-----------------------------------------------------------------------------
252 250
253 251
254 252 def find_gui_and_backend(gui=None, gui_select=None):
255 253 """Given a gui string return the gui and mpl backend.
256 254
257 255 Parameters
258 256 ----------
259 257 gui : str
260 258 Can be one of ('tk','gtk','wx','qt','qt4','inline','agg').
261 259 gui_select : str
262 260 Can be one of ('tk','gtk','wx','qt','qt4','inline').
263 261 This is any gui already selected by the shell.
264 262
265 263 Returns
266 264 -------
267 265 A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg',
268 266 'WXAgg','Qt4Agg','module://ipykernel.pylab.backend_inline','agg').
269 267 """
270 268
271 269 import matplotlib
272 270
273 271 if gui and gui != 'auto':
274 272 # select backend based on requested gui
275 273 backend = backends[gui]
276 274 if gui == 'agg':
277 275 gui = None
278 276 else:
279 277 # We need to read the backend from the original data structure, *not*
280 278 # from mpl.rcParams, since a prior invocation of %matplotlib may have
281 279 # overwritten that.
282 280 # WARNING: this assumes matplotlib 1.1 or newer!!
283 281 backend = matplotlib.rcParamsOrig['backend']
284 282 # In this case, we need to find what the appropriate gui selection call
285 283 # should be for IPython, so we can activate inputhook accordingly
286 284 gui = backend2gui.get(backend, None)
287 285
288 286 # If we have already had a gui active, we need it and inline are the
289 287 # ones allowed.
290 288 if gui_select and gui != gui_select:
291 289 gui = gui_select
292 290 backend = backends[gui]
293 291
294 292 return gui, backend
295 293
296 294
297 295 def activate_matplotlib(backend):
298 296 """Activate the given backend and set interactive to True."""
299 297
300 298 import matplotlib
301 299 matplotlib.interactive(True)
302 300
303 301 # Matplotlib had a bug where even switch_backend could not force
304 302 # the rcParam to update. This needs to be set *before* the module
305 303 # magic of switch_backend().
306 304 matplotlib.rcParams['backend'] = backend
307 305
308 306 import matplotlib.pyplot
309 307 matplotlib.pyplot.switch_backend(backend)
310 308
311 309 # This must be imported last in the matplotlib series, after
312 310 # backend/interactivity choices have been made
313 311 import matplotlib.pyplot as plt
314 312
315 313 plt.show._needmain = False
316 314 # We need to detect at runtime whether show() is called by the user.
317 315 # For this, we wrap it into a decorator which adds a 'called' flag.
318 316 plt.draw_if_interactive = flag_calls(plt.draw_if_interactive)
319 317
320 318
321 319 def import_pylab(user_ns, import_all=True):
322 320 """Populate the namespace with pylab-related values.
323 321
324 322 Imports matplotlib, pylab, numpy, and everything from pylab and numpy.
325 323
326 324 Also imports a few names from IPython (figsize, display, getfigs)
327 325
328 326 """
329 327
330 328 # Import numpy as np/pyplot as plt are conventions we're trying to
331 329 # somewhat standardize on. Making them available to users by default
332 330 # will greatly help this.
333 331 s = ("import numpy\n"
334 332 "import matplotlib\n"
335 333 "from matplotlib import pylab, mlab, pyplot\n"
336 334 "np = numpy\n"
337 335 "plt = pyplot\n"
338 336 )
339 337 exec(s, user_ns)
340 338
341 339 if import_all:
342 340 s = ("from matplotlib.pylab import *\n"
343 341 "from numpy import *\n")
344 342 exec(s, user_ns)
345 343
346 344 # IPython symbols to add
347 345 user_ns['figsize'] = figsize
348 346 from IPython.core.display import display
349 347 # Add display and getfigs to the user's namespace
350 348 user_ns['display'] = display
351 349 user_ns['getfigs'] = getfigs
352 350
353 351
354 352 def configure_inline_support(shell, backend):
355 353 """Configure an IPython shell object for matplotlib use.
356 354
357 355 Parameters
358 356 ----------
359 357 shell : InteractiveShell instance
360 358
361 359 backend : matplotlib backend
362 360 """
363 361 # If using our svg payload backend, register the post-execution
364 362 # function that will pick up the results for display. This can only be
365 363 # done with access to the real shell object.
366 364
367 365 # Note: if we can't load the inline backend, then there's no point
368 366 # continuing (such as in terminal-only shells in environments without
369 367 # zeromq available).
370 368 try:
371 369 from ipykernel.pylab.backend_inline import InlineBackend
372 370 except ImportError:
373 371 return
374 372 import matplotlib
375 373
376 374 cfg = InlineBackend.instance(parent=shell)
377 375 cfg.shell = shell
378 376 if cfg not in shell.configurables:
379 377 shell.configurables.append(cfg)
380 378
381 379 if backend == backends['inline']:
382 380 from ipykernel.pylab.backend_inline import flush_figures
383 381 shell.events.register('post_execute', flush_figures)
384 382
385 383 # Save rcParams that will be overwrittern
386 384 shell._saved_rcParams = {}
387 385 for k in cfg.rc:
388 386 shell._saved_rcParams[k] = matplotlib.rcParams[k]
389 387 # load inline_rc
390 388 matplotlib.rcParams.update(cfg.rc)
391 389 new_backend_name = "inline"
392 390 else:
393 391 from ipykernel.pylab.backend_inline import flush_figures
394 392 try:
395 393 shell.events.unregister('post_execute', flush_figures)
396 394 except ValueError:
397 395 pass
398 396 if hasattr(shell, '_saved_rcParams'):
399 397 matplotlib.rcParams.update(shell._saved_rcParams)
400 398 del shell._saved_rcParams
401 399 new_backend_name = "other"
402 400
403 401 # only enable the formats once -> don't change the enabled formats (which the user may
404 402 # has changed) when getting another "%matplotlib inline" call.
405 403 # See https://github.com/ipython/ipykernel/issues/29
406 404 cur_backend = getattr(configure_inline_support, "current_backend", "unset")
407 405 if new_backend_name != cur_backend:
408 406 # Setup the default figure format
409 407 select_figure_formats(shell, cfg.figure_formats, **cfg.print_figure_kwargs)
410 408 configure_inline_support.current_backend = new_backend_name
@@ -1,405 +1,404 b''
1 1 # encoding: utf-8
2 2 """
3 3 A mixin for :class:`~IPython.core.application.Application` classes that
4 4 launch InteractiveShell instances, load extensions, etc.
5 5 """
6 6
7 7 # Copyright (c) IPython Development Team.
8 8 # Distributed under the terms of the Modified BSD License.
9 9
10 10 import glob
11 11 import os
12 12 import sys
13 13
14 14 from traitlets.config.application import boolean_flag
15 15 from traitlets.config.configurable import Configurable
16 16 from traitlets.config.loader import Config
17 17 from IPython.core import pylabtools
18 from IPython.utils import py3compat
19 18 from IPython.utils.contexts import preserve_keys
20 19 from IPython.utils.path import filefind
21 20 from traitlets import (
22 21 Unicode, Instance, List, Bool, CaselessStrEnum, observe,
23 22 )
24 23 from IPython.terminal import pt_inputhooks
25 24
26 25 #-----------------------------------------------------------------------------
27 26 # Aliases and Flags
28 27 #-----------------------------------------------------------------------------
29 28
30 29 gui_keys = tuple(sorted(pt_inputhooks.backends) + sorted(pt_inputhooks.aliases))
31 30
32 31 backend_keys = sorted(pylabtools.backends.keys())
33 32 backend_keys.insert(0, 'auto')
34 33
35 34 shell_flags = {}
36 35
37 36 addflag = lambda *args: shell_flags.update(boolean_flag(*args))
38 37 addflag('autoindent', 'InteractiveShell.autoindent',
39 38 'Turn on autoindenting.', 'Turn off autoindenting.'
40 39 )
41 40 addflag('automagic', 'InteractiveShell.automagic',
42 41 """Turn on the auto calling of magic commands. Type %%magic at the
43 42 IPython prompt for more information.""",
44 43 'Turn off the auto calling of magic commands.'
45 44 )
46 45 addflag('pdb', 'InteractiveShell.pdb',
47 46 "Enable auto calling the pdb debugger after every exception.",
48 47 "Disable auto calling the pdb debugger after every exception."
49 48 )
50 49 addflag('pprint', 'PlainTextFormatter.pprint',
51 50 "Enable auto pretty printing of results.",
52 51 "Disable auto pretty printing of results."
53 52 )
54 53 addflag('color-info', 'InteractiveShell.color_info',
55 54 """IPython can display information about objects via a set of functions,
56 55 and optionally can use colors for this, syntax highlighting
57 56 source code and various other elements. This is on by default, but can cause
58 57 problems with some pagers. If you see such problems, you can disable the
59 58 colours.""",
60 59 "Disable using colors for info related things."
61 60 )
62 61 nosep_config = Config()
63 62 nosep_config.InteractiveShell.separate_in = ''
64 63 nosep_config.InteractiveShell.separate_out = ''
65 64 nosep_config.InteractiveShell.separate_out2 = ''
66 65
67 66 shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
68 67 shell_flags['pylab'] = (
69 68 {'InteractiveShellApp' : {'pylab' : 'auto'}},
70 69 """Pre-load matplotlib and numpy for interactive use with
71 70 the default matplotlib backend."""
72 71 )
73 72 shell_flags['matplotlib'] = (
74 73 {'InteractiveShellApp' : {'matplotlib' : 'auto'}},
75 74 """Configure matplotlib for interactive use with
76 75 the default matplotlib backend."""
77 76 )
78 77
79 78 # it's possible we don't want short aliases for *all* of these:
80 79 shell_aliases = dict(
81 80 autocall='InteractiveShell.autocall',
82 81 colors='InteractiveShell.colors',
83 82 logfile='InteractiveShell.logfile',
84 83 logappend='InteractiveShell.logappend',
85 84 c='InteractiveShellApp.code_to_run',
86 85 m='InteractiveShellApp.module_to_run',
87 86 ext='InteractiveShellApp.extra_extension',
88 87 gui='InteractiveShellApp.gui',
89 88 pylab='InteractiveShellApp.pylab',
90 89 matplotlib='InteractiveShellApp.matplotlib',
91 90 )
92 91 shell_aliases['cache-size'] = 'InteractiveShell.cache_size'
93 92
94 93 #-----------------------------------------------------------------------------
95 94 # Main classes and functions
96 95 #-----------------------------------------------------------------------------
97 96
98 97 class InteractiveShellApp(Configurable):
99 98 """A Mixin for applications that start InteractiveShell instances.
100 99
101 100 Provides configurables for loading extensions and executing files
102 101 as part of configuring a Shell environment.
103 102
104 103 The following methods should be called by the :meth:`initialize` method
105 104 of the subclass:
106 105
107 106 - :meth:`init_path`
108 107 - :meth:`init_shell` (to be implemented by the subclass)
109 108 - :meth:`init_gui_pylab`
110 109 - :meth:`init_extensions`
111 110 - :meth:`init_code`
112 111 """
113 112 extensions = List(Unicode(),
114 113 help="A list of dotted module names of IPython extensions to load."
115 114 ).tag(config=True)
116 115 extra_extension = Unicode('',
117 116 help="dotted module name of an IPython extension to load."
118 117 ).tag(config=True)
119 118
120 119 reraise_ipython_extension_failures = Bool(False,
121 120 help="Reraise exceptions encountered loading IPython extensions?",
122 121 ).tag(config=True)
123 122
124 123 # Extensions that are always loaded (not configurable)
125 124 default_extensions = List(Unicode(), [u'storemagic']).tag(config=False)
126 125
127 126 hide_initial_ns = Bool(True,
128 127 help="""Should variables loaded at startup (by startup files, exec_lines, etc.)
129 128 be hidden from tools like %who?"""
130 129 ).tag(config=True)
131 130
132 131 exec_files = List(Unicode(),
133 132 help="""List of files to run at IPython startup."""
134 133 ).tag(config=True)
135 134 exec_PYTHONSTARTUP = Bool(True,
136 135 help="""Run the file referenced by the PYTHONSTARTUP environment
137 136 variable at IPython startup."""
138 137 ).tag(config=True)
139 138 file_to_run = Unicode('',
140 139 help="""A file to be run""").tag(config=True)
141 140
142 141 exec_lines = List(Unicode(),
143 142 help="""lines of code to run at IPython startup."""
144 143 ).tag(config=True)
145 144 code_to_run = Unicode('',
146 145 help="Execute the given command string."
147 146 ).tag(config=True)
148 147 module_to_run = Unicode('',
149 148 help="Run the module as a script."
150 149 ).tag(config=True)
151 150 gui = CaselessStrEnum(gui_keys, allow_none=True,
152 151 help="Enable GUI event loop integration with any of {0}.".format(gui_keys)
153 152 ).tag(config=True)
154 153 matplotlib = CaselessStrEnum(backend_keys, allow_none=True,
155 154 help="""Configure matplotlib for interactive use with
156 155 the default matplotlib backend."""
157 156 ).tag(config=True)
158 157 pylab = CaselessStrEnum(backend_keys, allow_none=True,
159 158 help="""Pre-load matplotlib and numpy for interactive use,
160 159 selecting a particular matplotlib backend and loop integration.
161 160 """
162 161 ).tag(config=True)
163 162 pylab_import_all = Bool(True,
164 163 help="""If true, IPython will populate the user namespace with numpy, pylab, etc.
165 164 and an ``import *`` is done from numpy and pylab, when using pylab mode.
166 165
167 166 When False, pylab mode should not import any names into the user namespace.
168 167 """
169 168 ).tag(config=True)
170 169 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
171 170 allow_none=True)
172 171 # whether interact-loop should start
173 172 interact = Bool(True)
174 173
175 174 user_ns = Instance(dict, args=None, allow_none=True)
176 175 @observe('user_ns')
177 176 def _user_ns_changed(self, change):
178 177 if self.shell is not None:
179 178 self.shell.user_ns = change['new']
180 179 self.shell.init_user_ns()
181 180
182 181 def init_path(self):
183 182 """Add current working directory, '', to sys.path"""
184 183 if sys.path[0] != '':
185 184 sys.path.insert(0, '')
186 185
187 186 def init_shell(self):
188 187 raise NotImplementedError("Override in subclasses")
189 188
190 189 def init_gui_pylab(self):
191 190 """Enable GUI event loop integration, taking pylab into account."""
192 191 enable = False
193 192 shell = self.shell
194 193 if self.pylab:
195 194 enable = lambda key: shell.enable_pylab(key, import_all=self.pylab_import_all)
196 195 key = self.pylab
197 196 elif self.matplotlib:
198 197 enable = shell.enable_matplotlib
199 198 key = self.matplotlib
200 199 elif self.gui:
201 200 enable = shell.enable_gui
202 201 key = self.gui
203 202
204 203 if not enable:
205 204 return
206 205
207 206 try:
208 207 r = enable(key)
209 208 except ImportError:
210 209 self.log.warning("Eventloop or matplotlib integration failed. Is matplotlib installed?")
211 210 self.shell.showtraceback()
212 211 return
213 212 except Exception:
214 213 self.log.warning("GUI event loop or pylab initialization failed")
215 214 self.shell.showtraceback()
216 215 return
217 216
218 217 if isinstance(r, tuple):
219 218 gui, backend = r[:2]
220 219 self.log.info("Enabling GUI event loop integration, "
221 220 "eventloop=%s, matplotlib=%s", gui, backend)
222 221 if key == "auto":
223 222 print("Using matplotlib backend: %s" % backend)
224 223 else:
225 224 gui = r
226 225 self.log.info("Enabling GUI event loop integration, "
227 226 "eventloop=%s", gui)
228 227
229 228 def init_extensions(self):
230 229 """Load all IPython extensions in IPythonApp.extensions.
231 230
232 231 This uses the :meth:`ExtensionManager.load_extensions` to load all
233 232 the extensions listed in ``self.extensions``.
234 233 """
235 234 try:
236 235 self.log.debug("Loading IPython extensions...")
237 236 extensions = self.default_extensions + self.extensions
238 237 if self.extra_extension:
239 238 extensions.append(self.extra_extension)
240 239 for ext in extensions:
241 240 try:
242 241 self.log.info("Loading IPython extension: %s" % ext)
243 242 self.shell.extension_manager.load_extension(ext)
244 243 except:
245 244 if self.reraise_ipython_extension_failures:
246 245 raise
247 246 msg = ("Error in loading extension: {ext}\n"
248 247 "Check your config files in {location}".format(
249 248 ext=ext,
250 249 location=self.profile_dir.location
251 250 ))
252 251 self.log.warning(msg, exc_info=True)
253 252 except:
254 253 if self.reraise_ipython_extension_failures:
255 254 raise
256 255 self.log.warning("Unknown error in loading extensions:", exc_info=True)
257 256
258 257 def init_code(self):
259 258 """run the pre-flight code, specified via exec_lines"""
260 259 self._run_startup_files()
261 260 self._run_exec_lines()
262 261 self._run_exec_files()
263 262
264 263 # Hide variables defined here from %who etc.
265 264 if self.hide_initial_ns:
266 265 self.shell.user_ns_hidden.update(self.shell.user_ns)
267 266
268 267 # command-line execution (ipython -i script.py, ipython -m module)
269 268 # should *not* be excluded from %whos
270 269 self._run_cmd_line_code()
271 270 self._run_module()
272 271
273 272 # flush output, so itwon't be attached to the first cell
274 273 sys.stdout.flush()
275 274 sys.stderr.flush()
276 275
277 276 def _run_exec_lines(self):
278 277 """Run lines of code in IPythonApp.exec_lines in the user's namespace."""
279 278 if not self.exec_lines:
280 279 return
281 280 try:
282 281 self.log.debug("Running code from IPythonApp.exec_lines...")
283 282 for line in self.exec_lines:
284 283 try:
285 284 self.log.info("Running code in user namespace: %s" %
286 285 line)
287 286 self.shell.run_cell(line, store_history=False)
288 287 except:
289 288 self.log.warning("Error in executing line in user "
290 289 "namespace: %s" % line)
291 290 self.shell.showtraceback()
292 291 except:
293 292 self.log.warning("Unknown error in handling IPythonApp.exec_lines:")
294 293 self.shell.showtraceback()
295 294
296 295 def _exec_file(self, fname, shell_futures=False):
297 296 try:
298 297 full_filename = filefind(fname, [u'.', self.ipython_dir])
299 298 except IOError:
300 299 self.log.warning("File not found: %r"%fname)
301 300 return
302 301 # Make sure that the running script gets a proper sys.argv as if it
303 302 # were run from a system shell.
304 303 save_argv = sys.argv
305 304 sys.argv = [full_filename] + self.extra_args[1:]
306 305 try:
307 306 if os.path.isfile(full_filename):
308 307 self.log.info("Running file in user namespace: %s" %
309 308 full_filename)
310 309 # Ensure that __file__ is always defined to match Python
311 310 # behavior.
312 311 with preserve_keys(self.shell.user_ns, '__file__'):
313 312 self.shell.user_ns['__file__'] = fname
314 313 if full_filename.endswith('.ipy'):
315 314 self.shell.safe_execfile_ipy(full_filename,
316 315 shell_futures=shell_futures)
317 316 else:
318 317 # default to python, even without extension
319 318 self.shell.safe_execfile(full_filename,
320 319 self.shell.user_ns,
321 320 shell_futures=shell_futures,
322 321 raise_exceptions=True)
323 322 finally:
324 323 sys.argv = save_argv
325 324
326 325 def _run_startup_files(self):
327 326 """Run files from profile startup directory"""
328 327 startup_dir = self.profile_dir.startup_dir
329 328 startup_files = []
330 329
331 330 if self.exec_PYTHONSTARTUP and os.environ.get('PYTHONSTARTUP', False) and \
332 331 not (self.file_to_run or self.code_to_run or self.module_to_run):
333 332 python_startup = os.environ['PYTHONSTARTUP']
334 333 self.log.debug("Running PYTHONSTARTUP file %s...", python_startup)
335 334 try:
336 335 self._exec_file(python_startup)
337 336 except:
338 337 self.log.warning("Unknown error in handling PYTHONSTARTUP file %s:", python_startup)
339 338 self.shell.showtraceback()
340 339
341 340 startup_files += glob.glob(os.path.join(startup_dir, '*.py'))
342 341 startup_files += glob.glob(os.path.join(startup_dir, '*.ipy'))
343 342 if not startup_files:
344 343 return
345 344
346 345 self.log.debug("Running startup files from %s...", startup_dir)
347 346 try:
348 347 for fname in sorted(startup_files):
349 348 self._exec_file(fname)
350 349 except:
351 350 self.log.warning("Unknown error in handling startup files:")
352 351 self.shell.showtraceback()
353 352
354 353 def _run_exec_files(self):
355 354 """Run files from IPythonApp.exec_files"""
356 355 if not self.exec_files:
357 356 return
358 357
359 358 self.log.debug("Running files in IPythonApp.exec_files...")
360 359 try:
361 360 for fname in self.exec_files:
362 361 self._exec_file(fname)
363 362 except:
364 363 self.log.warning("Unknown error in handling IPythonApp.exec_files:")
365 364 self.shell.showtraceback()
366 365
367 366 def _run_cmd_line_code(self):
368 367 """Run code or file specified at the command-line"""
369 368 if self.code_to_run:
370 369 line = self.code_to_run
371 370 try:
372 371 self.log.info("Running code given at command line (c=): %s" %
373 372 line)
374 373 self.shell.run_cell(line, store_history=False)
375 374 except:
376 375 self.log.warning("Error in executing line in user namespace: %s" %
377 376 line)
378 377 self.shell.showtraceback()
379 378 if not self.interact:
380 379 self.exit(1)
381 380
382 381 # Like Python itself, ignore the second if the first of these is present
383 382 elif self.file_to_run:
384 383 fname = self.file_to_run
385 384 if os.path.isdir(fname):
386 385 fname = os.path.join(fname, "__main__.py")
387 386 try:
388 387 self._exec_file(fname, shell_futures=True)
389 388 except:
390 389 self.shell.showtraceback(tb_offset=4)
391 390 if not self.interact:
392 391 self.exit(1)
393 392
394 393 def _run_module(self):
395 394 """Run module specified at the command-line."""
396 395 if self.module_to_run:
397 396 # Make sure that the module gets a proper sys.argv as if it were
398 397 # run using `python -m`.
399 398 save_argv = sys.argv
400 399 sys.argv = [sys.executable] + self.extra_args
401 400 try:
402 401 self.shell.safe_run_module(self.module_to_run,
403 402 self.shell.user_ns)
404 403 finally:
405 404 sys.argv = save_argv
@@ -1,1460 +1,1459 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 Verbose and colourful traceback formatting.
4 4
5 5 **ColorTB**
6 6
7 7 I've always found it a bit hard to visually parse tracebacks in Python. The
8 8 ColorTB class is a solution to that problem. It colors the different parts of a
9 9 traceback in a manner similar to what you would expect from a syntax-highlighting
10 10 text editor.
11 11
12 12 Installation instructions for ColorTB::
13 13
14 14 import sys,ultratb
15 15 sys.excepthook = ultratb.ColorTB()
16 16
17 17 **VerboseTB**
18 18
19 19 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
20 20 of useful info when a traceback occurs. Ping originally had it spit out HTML
21 21 and intended it for CGI programmers, but why should they have all the fun? I
22 22 altered it to spit out colored text to the terminal. It's a bit overwhelming,
23 23 but kind of neat, and maybe useful for long-running programs that you believe
24 24 are bug-free. If a crash *does* occur in that type of program you want details.
25 25 Give it a shot--you'll love it or you'll hate it.
26 26
27 27 .. note::
28 28
29 29 The Verbose mode prints the variables currently visible where the exception
30 30 happened (shortening their strings if too long). This can potentially be
31 31 very slow, if you happen to have a huge data structure whose string
32 32 representation is complex to compute. Your computer may appear to freeze for
33 33 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
34 34 with Ctrl-C (maybe hitting it more than once).
35 35
36 36 If you encounter this kind of situation often, you may want to use the
37 37 Verbose_novars mode instead of the regular Verbose, which avoids formatting
38 38 variables (but otherwise includes the information and context given by
39 39 Verbose).
40 40
41 41 .. note::
42 42
43 43 The verbose mode print all variables in the stack, which means it can
44 44 potentially leak sensitive information like access keys, or unencryted
45 45 password.
46 46
47 47 Installation instructions for VerboseTB::
48 48
49 49 import sys,ultratb
50 50 sys.excepthook = ultratb.VerboseTB()
51 51
52 52 Note: Much of the code in this module was lifted verbatim from the standard
53 53 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
54 54
55 55 Color schemes
56 56 -------------
57 57
58 58 The colors are defined in the class TBTools through the use of the
59 59 ColorSchemeTable class. Currently the following exist:
60 60
61 61 - NoColor: allows all of this module to be used in any terminal (the color
62 62 escapes are just dummy blank strings).
63 63
64 64 - Linux: is meant to look good in a terminal like the Linux console (black
65 65 or very dark background).
66 66
67 67 - LightBG: similar to Linux but swaps dark/light colors to be more readable
68 68 in light background terminals.
69 69
70 70 - Neutral: a neutral color scheme that should be readable on both light and
71 71 dark background
72 72
73 73 You can implement other color schemes easily, the syntax is fairly
74 74 self-explanatory. Please send back new schemes you develop to the author for
75 75 possible inclusion in future releases.
76 76
77 77 Inheritance diagram:
78 78
79 79 .. inheritance-diagram:: IPython.core.ultratb
80 80 :parts: 3
81 81 """
82 82
83 83 #*****************************************************************************
84 84 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
85 85 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
86 86 #
87 87 # Distributed under the terms of the BSD License. The full license is in
88 88 # the file COPYING, distributed as part of this software.
89 89 #*****************************************************************************
90 90
91 91
92 92 import dis
93 93 import inspect
94 94 import keyword
95 95 import linecache
96 96 import os
97 97 import pydoc
98 98 import re
99 99 import sys
100 100 import time
101 101 import tokenize
102 102 import traceback
103 import types
104 103
105 104 try: # Python 2
106 105 generate_tokens = tokenize.generate_tokens
107 106 except AttributeError: # Python 3
108 107 generate_tokens = tokenize.tokenize
109 108
110 109 # For purposes of monkeypatching inspect to fix a bug in it.
111 110 from inspect import getsourcefile, getfile, getmodule, \
112 111 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
113 112
114 113 # IPython's own modules
115 114 from IPython import get_ipython
116 115 from IPython.core import debugger
117 116 from IPython.core.display_trap import DisplayTrap
118 117 from IPython.core.excolors import exception_colors
119 118 from IPython.utils import PyColorize
120 119 from IPython.utils import openpy
121 120 from IPython.utils import path as util_path
122 121 from IPython.utils import py3compat
123 122 from IPython.utils.data import uniq_stable
124 123 from IPython.utils.terminal import get_terminal_size
125 124 from logging import info, error
126 125
127 126 import IPython.utils.colorable as colorable
128 127
129 128 # Globals
130 129 # amount of space to put line numbers before verbose tracebacks
131 130 INDENT_SIZE = 8
132 131
133 132 # Default color scheme. This is used, for example, by the traceback
134 133 # formatter. When running in an actual IPython instance, the user's rc.colors
135 134 # value is used, but having a module global makes this functionality available
136 135 # to users of ultratb who are NOT running inside ipython.
137 136 DEFAULT_SCHEME = 'NoColor'
138 137
139 138 # ---------------------------------------------------------------------------
140 139 # Code begins
141 140
142 141 # Utility functions
143 142 def inspect_error():
144 143 """Print a message about internal inspect errors.
145 144
146 145 These are unfortunately quite common."""
147 146
148 147 error('Internal Python error in the inspect module.\n'
149 148 'Below is the traceback from this internal error.\n')
150 149
151 150
152 151 # This function is a monkeypatch we apply to the Python inspect module. We have
153 152 # now found when it's needed (see discussion on issue gh-1456), and we have a
154 153 # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
155 154 # the monkeypatch is not applied. TK, Aug 2012.
156 155 def findsource(object):
157 156 """Return the entire source file and starting line number for an object.
158 157
159 158 The argument may be a module, class, method, function, traceback, frame,
160 159 or code object. The source code is returned as a list of all the lines
161 160 in the file and the line number indexes a line in that list. An IOError
162 161 is raised if the source code cannot be retrieved.
163 162
164 163 FIXED version with which we monkeypatch the stdlib to work around a bug."""
165 164
166 165 file = getsourcefile(object) or getfile(object)
167 166 # If the object is a frame, then trying to get the globals dict from its
168 167 # module won't work. Instead, the frame object itself has the globals
169 168 # dictionary.
170 169 globals_dict = None
171 170 if inspect.isframe(object):
172 171 # XXX: can this ever be false?
173 172 globals_dict = object.f_globals
174 173 else:
175 174 module = getmodule(object, file)
176 175 if module:
177 176 globals_dict = module.__dict__
178 177 lines = linecache.getlines(file, globals_dict)
179 178 if not lines:
180 179 raise IOError('could not get source code')
181 180
182 181 if ismodule(object):
183 182 return lines, 0
184 183
185 184 if isclass(object):
186 185 name = object.__name__
187 186 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
188 187 # make some effort to find the best matching class definition:
189 188 # use the one with the least indentation, which is the one
190 189 # that's most probably not inside a function definition.
191 190 candidates = []
192 191 for i, line in enumerate(lines):
193 192 match = pat.match(line)
194 193 if match:
195 194 # if it's at toplevel, it's already the best one
196 195 if line[0] == 'c':
197 196 return lines, i
198 197 # else add whitespace to candidate list
199 198 candidates.append((match.group(1), i))
200 199 if candidates:
201 200 # this will sort by whitespace, and by line number,
202 201 # less whitespace first
203 202 candidates.sort()
204 203 return lines, candidates[0][1]
205 204 else:
206 205 raise IOError('could not find class definition')
207 206
208 207 if ismethod(object):
209 208 object = object.__func__
210 209 if isfunction(object):
211 210 object = object.__code__
212 211 if istraceback(object):
213 212 object = object.tb_frame
214 213 if isframe(object):
215 214 object = object.f_code
216 215 if iscode(object):
217 216 if not hasattr(object, 'co_firstlineno'):
218 217 raise IOError('could not find function definition')
219 218 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
220 219 pmatch = pat.match
221 220 # fperez - fix: sometimes, co_firstlineno can give a number larger than
222 221 # the length of lines, which causes an error. Safeguard against that.
223 222 lnum = min(object.co_firstlineno, len(lines)) - 1
224 223 while lnum > 0:
225 224 if pmatch(lines[lnum]):
226 225 break
227 226 lnum -= 1
228 227
229 228 return lines, lnum
230 229 raise IOError('could not find code object')
231 230
232 231
233 232 # This is a patched version of inspect.getargs that applies the (unmerged)
234 233 # patch for http://bugs.python.org/issue14611 by Stefano Taschini. This fixes
235 234 # https://github.com/ipython/ipython/issues/8205 and
236 235 # https://github.com/ipython/ipython/issues/8293
237 236 def getargs(co):
238 237 """Get information about the arguments accepted by a code object.
239 238
240 239 Three things are returned: (args, varargs, varkw), where 'args' is
241 240 a list of argument names (possibly containing nested lists), and
242 241 'varargs' and 'varkw' are the names of the * and ** arguments or None."""
243 242 if not iscode(co):
244 243 raise TypeError('{!r} is not a code object'.format(co))
245 244
246 245 nargs = co.co_argcount
247 246 names = co.co_varnames
248 247 args = list(names[:nargs])
249 248 step = 0
250 249
251 250 # The following acrobatics are for anonymous (tuple) arguments.
252 251 for i in range(nargs):
253 252 if args[i][:1] in ('', '.'):
254 253 stack, remain, count = [], [], []
255 254 while step < len(co.co_code):
256 255 op = ord(co.co_code[step])
257 256 step = step + 1
258 257 if op >= dis.HAVE_ARGUMENT:
259 258 opname = dis.opname[op]
260 259 value = ord(co.co_code[step]) + ord(co.co_code[step+1])*256
261 260 step = step + 2
262 261 if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'):
263 262 remain.append(value)
264 263 count.append(value)
265 264 elif opname in ('STORE_FAST', 'STORE_DEREF'):
266 265 if op in dis.haslocal:
267 266 stack.append(co.co_varnames[value])
268 267 elif op in dis.hasfree:
269 268 stack.append((co.co_cellvars + co.co_freevars)[value])
270 269 # Special case for sublists of length 1: def foo((bar))
271 270 # doesn't generate the UNPACK_TUPLE bytecode, so if
272 271 # `remain` is empty here, we have such a sublist.
273 272 if not remain:
274 273 stack[0] = [stack[0]]
275 274 break
276 275 else:
277 276 remain[-1] = remain[-1] - 1
278 277 while remain[-1] == 0:
279 278 remain.pop()
280 279 size = count.pop()
281 280 stack[-size:] = [stack[-size:]]
282 281 if not remain:
283 282 break
284 283 remain[-1] = remain[-1] - 1
285 284 if not remain:
286 285 break
287 286 args[i] = stack[0]
288 287
289 288 varargs = None
290 289 if co.co_flags & inspect.CO_VARARGS:
291 290 varargs = co.co_varnames[nargs]
292 291 nargs = nargs + 1
293 292 varkw = None
294 293 if co.co_flags & inspect.CO_VARKEYWORDS:
295 294 varkw = co.co_varnames[nargs]
296 295 return inspect.Arguments(args, varargs, varkw)
297 296
298 297
299 298 # Monkeypatch inspect to apply our bugfix.
300 299 def with_patch_inspect(f):
301 300 """
302 301 Deprecated since IPython 6.0
303 302 decorator for monkeypatching inspect.findsource
304 303 """
305 304
306 305 def wrapped(*args, **kwargs):
307 306 save_findsource = inspect.findsource
308 307 save_getargs = inspect.getargs
309 308 inspect.findsource = findsource
310 309 inspect.getargs = getargs
311 310 try:
312 311 return f(*args, **kwargs)
313 312 finally:
314 313 inspect.findsource = save_findsource
315 314 inspect.getargs = save_getargs
316 315
317 316 return wrapped
318 317
319 318
320 319 def fix_frame_records_filenames(records):
321 320 """Try to fix the filenames in each record from inspect.getinnerframes().
322 321
323 322 Particularly, modules loaded from within zip files have useless filenames
324 323 attached to their code object, and inspect.getinnerframes() just uses it.
325 324 """
326 325 fixed_records = []
327 326 for frame, filename, line_no, func_name, lines, index in records:
328 327 # Look inside the frame's globals dictionary for __file__,
329 328 # which should be better. However, keep Cython filenames since
330 329 # we prefer the source filenames over the compiled .so file.
331 330 if not filename.endswith(('.pyx', '.pxd', '.pxi')):
332 331 better_fn = frame.f_globals.get('__file__', None)
333 332 if isinstance(better_fn, str):
334 333 # Check the type just in case someone did something weird with
335 334 # __file__. It might also be None if the error occurred during
336 335 # import.
337 336 filename = better_fn
338 337 fixed_records.append((frame, filename, line_no, func_name, lines, index))
339 338 return fixed_records
340 339
341 340
342 341 @with_patch_inspect
343 342 def _fixed_getinnerframes(etb, context=1, tb_offset=0):
344 343 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
345 344
346 345 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
347 346 # If the error is at the console, don't build any context, since it would
348 347 # otherwise produce 5 blank lines printed out (there is no file at the
349 348 # console)
350 349 rec_check = records[tb_offset:]
351 350 try:
352 351 rname = rec_check[0][1]
353 352 if rname == '<ipython console>' or rname.endswith('<string>'):
354 353 return rec_check
355 354 except IndexError:
356 355 pass
357 356
358 357 aux = traceback.extract_tb(etb)
359 358 assert len(records) == len(aux)
360 359 for i, (file, lnum, _, _) in enumerate(aux):
361 360 maybeStart = lnum - 1 - context // 2
362 361 start = max(maybeStart, 0)
363 362 end = start + context
364 363 lines = linecache.getlines(file)[start:end]
365 364 buf = list(records[i])
366 365 buf[LNUM_POS] = lnum
367 366 buf[INDEX_POS] = lnum - 1 - start
368 367 buf[LINES_POS] = lines
369 368 records[i] = tuple(buf)
370 369 return records[tb_offset:]
371 370
372 371 # Helper function -- largely belongs to VerboseTB, but we need the same
373 372 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
374 373 # can be recognized properly by ipython.el's py-traceback-line-re
375 374 # (SyntaxErrors have to be treated specially because they have no traceback)
376 375
377 376
378 377 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None, _line_format=(lambda x,_:x,None)):
379 378 numbers_width = INDENT_SIZE - 1
380 379 res = []
381 380 i = lnum - index
382 381
383 382 for line in lines:
384 383 line = py3compat.cast_unicode(line)
385 384
386 385 new_line, err = _line_format(line, 'str')
387 386 if not err: line = new_line
388 387
389 388 if i == lnum:
390 389 # This is the line with the error
391 390 pad = numbers_width - len(str(i))
392 391 num = '%s%s' % (debugger.make_arrow(pad), str(lnum))
393 392 line = '%s%s%s %s%s' % (Colors.linenoEm, num,
394 393 Colors.line, line, Colors.Normal)
395 394 else:
396 395 num = '%*s' % (numbers_width, i)
397 396 line = '%s%s%s %s' % (Colors.lineno, num,
398 397 Colors.Normal, line)
399 398
400 399 res.append(line)
401 400 if lvals and i == lnum:
402 401 res.append(lvals + '\n')
403 402 i = i + 1
404 403 return res
405 404
406 405 def is_recursion_error(etype, value, records):
407 406 try:
408 407 # RecursionError is new in Python 3.5
409 408 recursion_error_type = RecursionError
410 409 except NameError:
411 410 recursion_error_type = RuntimeError
412 411
413 412 # The default recursion limit is 1000, but some of that will be taken up
414 413 # by stack frames in IPython itself. >500 frames probably indicates
415 414 # a recursion error.
416 415 return (etype is recursion_error_type) \
417 416 and "recursion" in str(value).lower() \
418 417 and len(records) > 500
419 418
420 419 def find_recursion(etype, value, records):
421 420 """Identify the repeating stack frames from a RecursionError traceback
422 421
423 422 'records' is a list as returned by VerboseTB.get_records()
424 423
425 424 Returns (last_unique, repeat_length)
426 425 """
427 426 # This involves a bit of guesswork - we want to show enough of the traceback
428 427 # to indicate where the recursion is occurring. We guess that the innermost
429 428 # quarter of the traceback (250 frames by default) is repeats, and find the
430 429 # first frame (from in to out) that looks different.
431 430 if not is_recursion_error(etype, value, records):
432 431 return len(records), 0
433 432
434 433 # Select filename, lineno, func_name to track frames with
435 434 records = [r[1:4] for r in records]
436 435 inner_frames = records[-(len(records)//4):]
437 436 frames_repeated = set(inner_frames)
438 437
439 438 last_seen_at = {}
440 439 longest_repeat = 0
441 440 i = len(records)
442 441 for frame in reversed(records):
443 442 i -= 1
444 443 if frame not in frames_repeated:
445 444 last_unique = i
446 445 break
447 446
448 447 if frame in last_seen_at:
449 448 distance = last_seen_at[frame] - i
450 449 longest_repeat = max(longest_repeat, distance)
451 450
452 451 last_seen_at[frame] = i
453 452 else:
454 453 last_unique = 0 # The whole traceback was recursion
455 454
456 455 return last_unique, longest_repeat
457 456
458 457 #---------------------------------------------------------------------------
459 458 # Module classes
460 459 class TBTools(colorable.Colorable):
461 460 """Basic tools used by all traceback printer classes."""
462 461
463 462 # Number of frames to skip when reporting tracebacks
464 463 tb_offset = 0
465 464
466 465 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
467 466 # Whether to call the interactive pdb debugger after printing
468 467 # tracebacks or not
469 468 super(TBTools, self).__init__(parent=parent, config=config)
470 469 self.call_pdb = call_pdb
471 470
472 471 # Output stream to write to. Note that we store the original value in
473 472 # a private attribute and then make the public ostream a property, so
474 473 # that we can delay accessing sys.stdout until runtime. The way
475 474 # things are written now, the sys.stdout object is dynamically managed
476 475 # so a reference to it should NEVER be stored statically. This
477 476 # property approach confines this detail to a single location, and all
478 477 # subclasses can simply access self.ostream for writing.
479 478 self._ostream = ostream
480 479
481 480 # Create color table
482 481 self.color_scheme_table = exception_colors()
483 482
484 483 self.set_colors(color_scheme)
485 484 self.old_scheme = color_scheme # save initial value for toggles
486 485
487 486 if call_pdb:
488 487 self.pdb = debugger.Pdb()
489 488 else:
490 489 self.pdb = None
491 490
492 491 def _get_ostream(self):
493 492 """Output stream that exceptions are written to.
494 493
495 494 Valid values are:
496 495
497 496 - None: the default, which means that IPython will dynamically resolve
498 497 to sys.stdout. This ensures compatibility with most tools, including
499 498 Windows (where plain stdout doesn't recognize ANSI escapes).
500 499
501 500 - Any object with 'write' and 'flush' attributes.
502 501 """
503 502 return sys.stdout if self._ostream is None else self._ostream
504 503
505 504 def _set_ostream(self, val):
506 505 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
507 506 self._ostream = val
508 507
509 508 ostream = property(_get_ostream, _set_ostream)
510 509
511 510 def set_colors(self, *args, **kw):
512 511 """Shorthand access to the color table scheme selector method."""
513 512
514 513 # Set own color table
515 514 self.color_scheme_table.set_active_scheme(*args, **kw)
516 515 # for convenience, set Colors to the active scheme
517 516 self.Colors = self.color_scheme_table.active_colors
518 517 # Also set colors of debugger
519 518 if hasattr(self, 'pdb') and self.pdb is not None:
520 519 self.pdb.set_colors(*args, **kw)
521 520
522 521 def color_toggle(self):
523 522 """Toggle between the currently active color scheme and NoColor."""
524 523
525 524 if self.color_scheme_table.active_scheme_name == 'NoColor':
526 525 self.color_scheme_table.set_active_scheme(self.old_scheme)
527 526 self.Colors = self.color_scheme_table.active_colors
528 527 else:
529 528 self.old_scheme = self.color_scheme_table.active_scheme_name
530 529 self.color_scheme_table.set_active_scheme('NoColor')
531 530 self.Colors = self.color_scheme_table.active_colors
532 531
533 532 def stb2text(self, stb):
534 533 """Convert a structured traceback (a list) to a string."""
535 534 return '\n'.join(stb)
536 535
537 536 def text(self, etype, value, tb, tb_offset=None, context=5):
538 537 """Return formatted traceback.
539 538
540 539 Subclasses may override this if they add extra arguments.
541 540 """
542 541 tb_list = self.structured_traceback(etype, value, tb,
543 542 tb_offset, context)
544 543 return self.stb2text(tb_list)
545 544
546 545 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
547 546 context=5, mode=None):
548 547 """Return a list of traceback frames.
549 548
550 549 Must be implemented by each class.
551 550 """
552 551 raise NotImplementedError()
553 552
554 553
555 554 #---------------------------------------------------------------------------
556 555 class ListTB(TBTools):
557 556 """Print traceback information from a traceback list, with optional color.
558 557
559 558 Calling requires 3 arguments: (etype, evalue, elist)
560 559 as would be obtained by::
561 560
562 561 etype, evalue, tb = sys.exc_info()
563 562 if tb:
564 563 elist = traceback.extract_tb(tb)
565 564 else:
566 565 elist = None
567 566
568 567 It can thus be used by programs which need to process the traceback before
569 568 printing (such as console replacements based on the code module from the
570 569 standard library).
571 570
572 571 Because they are meant to be called without a full traceback (only a
573 572 list), instances of this class can't call the interactive pdb debugger."""
574 573
575 574 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
576 575 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
577 576 ostream=ostream, parent=parent,config=config)
578 577
579 578 def __call__(self, etype, value, elist):
580 579 self.ostream.flush()
581 580 self.ostream.write(self.text(etype, value, elist))
582 581 self.ostream.write('\n')
583 582
584 583 def structured_traceback(self, etype, value, elist, tb_offset=None,
585 584 context=5):
586 585 """Return a color formatted string with the traceback info.
587 586
588 587 Parameters
589 588 ----------
590 589 etype : exception type
591 590 Type of the exception raised.
592 591
593 592 value : object
594 593 Data stored in the exception
595 594
596 595 elist : list
597 596 List of frames, see class docstring for details.
598 597
599 598 tb_offset : int, optional
600 599 Number of frames in the traceback to skip. If not given, the
601 600 instance value is used (set in constructor).
602 601
603 602 context : int, optional
604 603 Number of lines of context information to print.
605 604
606 605 Returns
607 606 -------
608 607 String with formatted exception.
609 608 """
610 609 tb_offset = self.tb_offset if tb_offset is None else tb_offset
611 610 Colors = self.Colors
612 611 out_list = []
613 612 if elist:
614 613
615 614 if tb_offset and len(elist) > tb_offset:
616 615 elist = elist[tb_offset:]
617 616
618 617 out_list.append('Traceback %s(most recent call last)%s:' %
619 618 (Colors.normalEm, Colors.Normal) + '\n')
620 619 out_list.extend(self._format_list(elist))
621 620 # The exception info should be a single entry in the list.
622 621 lines = ''.join(self._format_exception_only(etype, value))
623 622 out_list.append(lines)
624 623
625 624 # Note: this code originally read:
626 625
627 626 ## for line in lines[:-1]:
628 627 ## out_list.append(" "+line)
629 628 ## out_list.append(lines[-1])
630 629
631 630 # This means it was indenting everything but the last line by a little
632 631 # bit. I've disabled this for now, but if we see ugliness somewhere we
633 632 # can restore it.
634 633
635 634 return out_list
636 635
637 636 def _format_list(self, extracted_list):
638 637 """Format a list of traceback entry tuples for printing.
639 638
640 639 Given a list of tuples as returned by extract_tb() or
641 640 extract_stack(), return a list of strings ready for printing.
642 641 Each string in the resulting list corresponds to the item with the
643 642 same index in the argument list. Each string ends in a newline;
644 643 the strings may contain internal newlines as well, for those items
645 644 whose source text line is not None.
646 645
647 646 Lifted almost verbatim from traceback.py
648 647 """
649 648
650 649 Colors = self.Colors
651 650 list = []
652 651 for filename, lineno, name, line in extracted_list[:-1]:
653 652 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
654 653 (Colors.filename, filename, Colors.Normal,
655 654 Colors.lineno, lineno, Colors.Normal,
656 655 Colors.name, name, Colors.Normal)
657 656 if line:
658 657 item += ' %s\n' % line.strip()
659 658 list.append(item)
660 659 # Emphasize the last entry
661 660 filename, lineno, name, line = extracted_list[-1]
662 661 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
663 662 (Colors.normalEm,
664 663 Colors.filenameEm, filename, Colors.normalEm,
665 664 Colors.linenoEm, lineno, Colors.normalEm,
666 665 Colors.nameEm, name, Colors.normalEm,
667 666 Colors.Normal)
668 667 if line:
669 668 item += '%s %s%s\n' % (Colors.line, line.strip(),
670 669 Colors.Normal)
671 670 list.append(item)
672 671 return list
673 672
674 673 def _format_exception_only(self, etype, value):
675 674 """Format the exception part of a traceback.
676 675
677 676 The arguments are the exception type and value such as given by
678 677 sys.exc_info()[:2]. The return value is a list of strings, each ending
679 678 in a newline. Normally, the list contains a single string; however,
680 679 for SyntaxError exceptions, it contains several lines that (when
681 680 printed) display detailed information about where the syntax error
682 681 occurred. The message indicating which exception occurred is the
683 682 always last string in the list.
684 683
685 684 Also lifted nearly verbatim from traceback.py
686 685 """
687 686 have_filedata = False
688 687 Colors = self.Colors
689 688 list = []
690 689 stype = py3compat.cast_unicode(Colors.excName + etype.__name__ + Colors.Normal)
691 690 if value is None:
692 691 # Not sure if this can still happen in Python 2.6 and above
693 692 list.append(stype + '\n')
694 693 else:
695 694 if issubclass(etype, SyntaxError):
696 695 have_filedata = True
697 696 if not value.filename: value.filename = "<string>"
698 697 if value.lineno:
699 698 lineno = value.lineno
700 699 textline = linecache.getline(value.filename, value.lineno)
701 700 else:
702 701 lineno = 'unknown'
703 702 textline = ''
704 703 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
705 704 (Colors.normalEm,
706 705 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
707 706 Colors.linenoEm, lineno, Colors.Normal ))
708 707 if textline == '':
709 708 textline = py3compat.cast_unicode(value.text, "utf-8")
710 709
711 710 if textline is not None:
712 711 i = 0
713 712 while i < len(textline) and textline[i].isspace():
714 713 i += 1
715 714 list.append('%s %s%s\n' % (Colors.line,
716 715 textline.strip(),
717 716 Colors.Normal))
718 717 if value.offset is not None:
719 718 s = ' '
720 719 for c in textline[i:value.offset - 1]:
721 720 if c.isspace():
722 721 s += c
723 722 else:
724 723 s += ' '
725 724 list.append('%s%s^%s\n' % (Colors.caret, s,
726 725 Colors.Normal))
727 726
728 727 try:
729 728 s = value.msg
730 729 except Exception:
731 730 s = self._some_str(value)
732 731 if s:
733 732 list.append('%s%s:%s %s\n' % (stype, Colors.excName,
734 733 Colors.Normal, s))
735 734 else:
736 735 list.append('%s\n' % stype)
737 736
738 737 # sync with user hooks
739 738 if have_filedata:
740 739 ipinst = get_ipython()
741 740 if ipinst is not None:
742 741 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
743 742
744 743 return list
745 744
746 745 def get_exception_only(self, etype, value):
747 746 """Only print the exception type and message, without a traceback.
748 747
749 748 Parameters
750 749 ----------
751 750 etype : exception type
752 751 value : exception value
753 752 """
754 753 return ListTB.structured_traceback(self, etype, value, [])
755 754
756 755 def show_exception_only(self, etype, evalue):
757 756 """Only print the exception type and message, without a traceback.
758 757
759 758 Parameters
760 759 ----------
761 760 etype : exception type
762 761 value : exception value
763 762 """
764 763 # This method needs to use __call__ from *this* class, not the one from
765 764 # a subclass whose signature or behavior may be different
766 765 ostream = self.ostream
767 766 ostream.flush()
768 767 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
769 768 ostream.flush()
770 769
771 770 def _some_str(self, value):
772 771 # Lifted from traceback.py
773 772 try:
774 773 return py3compat.cast_unicode(str(value))
775 774 except:
776 775 return u'<unprintable %s object>' % type(value).__name__
777 776
778 777
779 778 #----------------------------------------------------------------------------
780 779 class VerboseTB(TBTools):
781 780 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
782 781 of HTML. Requires inspect and pydoc. Crazy, man.
783 782
784 783 Modified version which optionally strips the topmost entries from the
785 784 traceback, to be used with alternate interpreters (because their own code
786 785 would appear in the traceback)."""
787 786
788 787 def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None,
789 788 tb_offset=0, long_header=False, include_vars=True,
790 789 check_cache=None, debugger_cls = None,
791 790 parent=None, config=None):
792 791 """Specify traceback offset, headers and color scheme.
793 792
794 793 Define how many frames to drop from the tracebacks. Calling it with
795 794 tb_offset=1 allows use of this handler in interpreters which will have
796 795 their own code at the top of the traceback (VerboseTB will first
797 796 remove that frame before printing the traceback info)."""
798 797 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
799 798 ostream=ostream, parent=parent, config=config)
800 799 self.tb_offset = tb_offset
801 800 self.long_header = long_header
802 801 self.include_vars = include_vars
803 802 # By default we use linecache.checkcache, but the user can provide a
804 803 # different check_cache implementation. This is used by the IPython
805 804 # kernel to provide tracebacks for interactive code that is cached,
806 805 # by a compiler instance that flushes the linecache but preserves its
807 806 # own code cache.
808 807 if check_cache is None:
809 808 check_cache = linecache.checkcache
810 809 self.check_cache = check_cache
811 810
812 811 self.debugger_cls = debugger_cls or debugger.Pdb
813 812
814 813 def format_records(self, records, last_unique, recursion_repeat):
815 814 """Format the stack frames of the traceback"""
816 815 frames = []
817 816 for r in records[:last_unique+recursion_repeat+1]:
818 817 #print '*** record:',file,lnum,func,lines,index # dbg
819 818 frames.append(self.format_record(*r))
820 819
821 820 if recursion_repeat:
822 821 frames.append('... last %d frames repeated, from the frame below ...\n' % recursion_repeat)
823 822 frames.append(self.format_record(*records[last_unique+recursion_repeat+1]))
824 823
825 824 return frames
826 825
827 826 def format_record(self, frame, file, lnum, func, lines, index):
828 827 """Format a single stack frame"""
829 828 Colors = self.Colors # just a shorthand + quicker name lookup
830 829 ColorsNormal = Colors.Normal # used a lot
831 830 col_scheme = self.color_scheme_table.active_scheme_name
832 831 indent = ' ' * INDENT_SIZE
833 832 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
834 833 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
835 834 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
836 835 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
837 836 ColorsNormal)
838 837 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
839 838 (Colors.vName, Colors.valEm, ColorsNormal)
840 839 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
841 840 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
842 841 Colors.vName, ColorsNormal)
843 842 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
844 843
845 844 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
846 845 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm, Colors.line,
847 846 ColorsNormal)
848 847
849 848 abspath = os.path.abspath
850 849
851 850
852 851 if not file:
853 852 file = '?'
854 853 elif file.startswith(str("<")) and file.endswith(str(">")):
855 854 # Not a real filename, no problem...
856 855 pass
857 856 elif not os.path.isabs(file):
858 857 # Try to make the filename absolute by trying all
859 858 # sys.path entries (which is also what linecache does)
860 859 for dirname in sys.path:
861 860 try:
862 861 fullname = os.path.join(dirname, file)
863 862 if os.path.isfile(fullname):
864 863 file = os.path.abspath(fullname)
865 864 break
866 865 except Exception:
867 866 # Just in case that sys.path contains very
868 867 # strange entries...
869 868 pass
870 869
871 870 file = py3compat.cast_unicode(file, util_path.fs_encoding)
872 871 link = tpl_link % util_path.compress_user(file)
873 872 args, varargs, varkw, locals = inspect.getargvalues(frame)
874 873
875 874 if func == '?':
876 875 call = ''
877 876 else:
878 877 # Decide whether to include variable details or not
879 878 var_repr = self.include_vars and eqrepr or nullrepr
880 879 try:
881 880 call = tpl_call % (func, inspect.formatargvalues(args,
882 881 varargs, varkw,
883 882 locals, formatvalue=var_repr))
884 883 except KeyError:
885 884 # This happens in situations like errors inside generator
886 885 # expressions, where local variables are listed in the
887 886 # line, but can't be extracted from the frame. I'm not
888 887 # 100% sure this isn't actually a bug in inspect itself,
889 888 # but since there's no info for us to compute with, the
890 889 # best we can do is report the failure and move on. Here
891 890 # we must *not* call any traceback construction again,
892 891 # because that would mess up use of %debug later on. So we
893 892 # simply report the failure and move on. The only
894 893 # limitation will be that this frame won't have locals
895 894 # listed in the call signature. Quite subtle problem...
896 895 # I can't think of a good way to validate this in a unit
897 896 # test, but running a script consisting of:
898 897 # dict( (k,v.strip()) for (k,v) in range(10) )
899 898 # will illustrate the error, if this exception catch is
900 899 # disabled.
901 900 call = tpl_call_fail % func
902 901
903 902 # Don't attempt to tokenize binary files.
904 903 if file.endswith(('.so', '.pyd', '.dll')):
905 904 return '%s %s\n' % (link, call)
906 905
907 906 elif file.endswith(('.pyc', '.pyo')):
908 907 # Look up the corresponding source file.
909 908 try:
910 909 file = openpy.source_from_cache(file)
911 910 except ValueError:
912 911 # Failed to get the source file for some reason
913 912 # E.g. https://github.com/ipython/ipython/issues/9486
914 913 return '%s %s\n' % (link, call)
915 914
916 915 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
917 916 line = getline(file, lnum[0])
918 917 lnum[0] += 1
919 918 return line
920 919
921 920 # Build the list of names on this line of code where the exception
922 921 # occurred.
923 922 try:
924 923 names = []
925 924 name_cont = False
926 925
927 926 for token_type, token, start, end, line in generate_tokens(linereader):
928 927 # build composite names
929 928 if token_type == tokenize.NAME and token not in keyword.kwlist:
930 929 if name_cont:
931 930 # Continuation of a dotted name
932 931 try:
933 932 names[-1].append(token)
934 933 except IndexError:
935 934 names.append([token])
936 935 name_cont = False
937 936 else:
938 937 # Regular new names. We append everything, the caller
939 938 # will be responsible for pruning the list later. It's
940 939 # very tricky to try to prune as we go, b/c composite
941 940 # names can fool us. The pruning at the end is easy
942 941 # to do (or the caller can print a list with repeated
943 942 # names if so desired.
944 943 names.append([token])
945 944 elif token == '.':
946 945 name_cont = True
947 946 elif token_type == tokenize.NEWLINE:
948 947 break
949 948
950 949 except (IndexError, UnicodeDecodeError, SyntaxError):
951 950 # signals exit of tokenizer
952 951 # SyntaxError can occur if the file is not actually Python
953 952 # - see gh-6300
954 953 pass
955 954 except tokenize.TokenError as msg:
956 955 _m = ("An unexpected error occurred while tokenizing input\n"
957 956 "The following traceback may be corrupted or invalid\n"
958 957 "The error message is: %s\n" % msg)
959 958 error(_m)
960 959
961 960 # Join composite names (e.g. "dict.fromkeys")
962 961 names = ['.'.join(n) for n in names]
963 962 # prune names list of duplicates, but keep the right order
964 963 unique_names = uniq_stable(names)
965 964
966 965 # Start loop over vars
967 966 lvals = []
968 967 if self.include_vars:
969 968 for name_full in unique_names:
970 969 name_base = name_full.split('.', 1)[0]
971 970 if name_base in frame.f_code.co_varnames:
972 971 if name_base in locals:
973 972 try:
974 973 value = repr(eval(name_full, locals))
975 974 except:
976 975 value = undefined
977 976 else:
978 977 value = undefined
979 978 name = tpl_local_var % name_full
980 979 else:
981 980 if name_base in frame.f_globals:
982 981 try:
983 982 value = repr(eval(name_full, frame.f_globals))
984 983 except:
985 984 value = undefined
986 985 else:
987 986 value = undefined
988 987 name = tpl_global_var % name_full
989 988 lvals.append(tpl_name_val % (name, value))
990 989 if lvals:
991 990 lvals = '%s%s' % (indent, em_normal.join(lvals))
992 991 else:
993 992 lvals = ''
994 993
995 994 level = '%s %s\n' % (link, call)
996 995
997 996 if index is None:
998 997 return level
999 998 else:
1000 999 _line_format = PyColorize.Parser(style=col_scheme, parent=self).format2
1001 1000 return '%s%s' % (level, ''.join(
1002 1001 _format_traceback_lines(lnum, index, lines, Colors, lvals,
1003 1002 _line_format)))
1004 1003
1005 1004 def prepare_chained_exception_message(self, cause):
1006 1005 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
1007 1006 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
1008 1007
1009 1008 if cause:
1010 1009 message = [[direct_cause]]
1011 1010 else:
1012 1011 message = [[exception_during_handling]]
1013 1012 return message
1014 1013
1015 1014 def prepare_header(self, etype, long_version=False):
1016 1015 colors = self.Colors # just a shorthand + quicker name lookup
1017 1016 colorsnormal = colors.Normal # used a lot
1018 1017 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
1019 1018 width = min(75, get_terminal_size()[0])
1020 1019 if long_version:
1021 1020 # Header with the exception type, python version, and date
1022 1021 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
1023 1022 date = time.ctime(time.time())
1024 1023
1025 1024 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * width, colorsnormal,
1026 1025 exc, ' ' * (width - len(str(etype)) - len(pyver)),
1027 1026 pyver, date.rjust(width) )
1028 1027 head += "\nA problem occurred executing Python code. Here is the sequence of function" \
1029 1028 "\ncalls leading up to the error, with the most recent (innermost) call last."
1030 1029 else:
1031 1030 # Simplified header
1032 1031 head = '%s%s' % (exc, 'Traceback (most recent call last)'. \
1033 1032 rjust(width - len(str(etype))) )
1034 1033
1035 1034 return head
1036 1035
1037 1036 def format_exception(self, etype, evalue):
1038 1037 colors = self.Colors # just a shorthand + quicker name lookup
1039 1038 colorsnormal = colors.Normal # used a lot
1040 1039 indent = ' ' * INDENT_SIZE
1041 1040 # Get (safely) a string form of the exception info
1042 1041 try:
1043 1042 etype_str, evalue_str = map(str, (etype, evalue))
1044 1043 except:
1045 1044 # User exception is improperly defined.
1046 1045 etype, evalue = str, sys.exc_info()[:2]
1047 1046 etype_str, evalue_str = map(str, (etype, evalue))
1048 1047 # ... and format it
1049 1048 return ['%s%s%s: %s' % (colors.excName, etype_str,
1050 1049 colorsnormal, py3compat.cast_unicode(evalue_str))]
1051 1050
1052 1051 def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset):
1053 1052 """Formats the header, traceback and exception message for a single exception.
1054 1053
1055 1054 This may be called multiple times by Python 3 exception chaining
1056 1055 (PEP 3134).
1057 1056 """
1058 1057 # some locals
1059 1058 orig_etype = etype
1060 1059 try:
1061 1060 etype = etype.__name__
1062 1061 except AttributeError:
1063 1062 pass
1064 1063
1065 1064 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1066 1065 head = self.prepare_header(etype, self.long_header)
1067 1066 records = self.get_records(etb, number_of_lines_of_context, tb_offset)
1068 1067
1069 1068 if records is None:
1070 1069 return ""
1071 1070
1072 1071 last_unique, recursion_repeat = find_recursion(orig_etype, evalue, records)
1073 1072
1074 1073 frames = self.format_records(records, last_unique, recursion_repeat)
1075 1074
1076 1075 formatted_exception = self.format_exception(etype, evalue)
1077 1076 if records:
1078 1077 filepath, lnum = records[-1][1:3]
1079 1078 filepath = os.path.abspath(filepath)
1080 1079 ipinst = get_ipython()
1081 1080 if ipinst is not None:
1082 1081 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
1083 1082
1084 1083 return [[head] + frames + [''.join(formatted_exception[0])]]
1085 1084
1086 1085 def get_records(self, etb, number_of_lines_of_context, tb_offset):
1087 1086 try:
1088 1087 # Try the default getinnerframes and Alex's: Alex's fixes some
1089 1088 # problems, but it generates empty tracebacks for console errors
1090 1089 # (5 blanks lines) where none should be returned.
1091 1090 return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset)
1092 1091 except UnicodeDecodeError:
1093 1092 # This can occur if a file's encoding magic comment is wrong.
1094 1093 # I can't see a way to recover without duplicating a bunch of code
1095 1094 # from the stdlib traceback module. --TK
1096 1095 error('\nUnicodeDecodeError while processing traceback.\n')
1097 1096 return None
1098 1097 except:
1099 1098 # FIXME: I've been getting many crash reports from python 2.3
1100 1099 # users, traceable to inspect.py. If I can find a small test-case
1101 1100 # to reproduce this, I should either write a better workaround or
1102 1101 # file a bug report against inspect (if that's the real problem).
1103 1102 # So far, I haven't been able to find an isolated example to
1104 1103 # reproduce the problem.
1105 1104 inspect_error()
1106 1105 traceback.print_exc(file=self.ostream)
1107 1106 info('\nUnfortunately, your original traceback can not be constructed.\n')
1108 1107 return None
1109 1108
1110 1109 def get_parts_of_chained_exception(self, evalue):
1111 1110 def get_chained_exception(exception_value):
1112 1111 cause = getattr(exception_value, '__cause__', None)
1113 1112 if cause:
1114 1113 return cause
1115 1114 if getattr(exception_value, '__suppress_context__', False):
1116 1115 return None
1117 1116 return getattr(exception_value, '__context__', None)
1118 1117
1119 1118 chained_evalue = get_chained_exception(evalue)
1120 1119
1121 1120 if chained_evalue:
1122 1121 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
1123 1122
1124 1123 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
1125 1124 number_of_lines_of_context=5):
1126 1125 """Return a nice text document describing the traceback."""
1127 1126
1128 1127 formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
1129 1128 tb_offset)
1130 1129
1131 1130 colors = self.Colors # just a shorthand + quicker name lookup
1132 1131 colorsnormal = colors.Normal # used a lot
1133 1132 head = '%s%s%s' % (colors.topline, '-' * min(75, get_terminal_size()[0]), colorsnormal)
1134 1133 structured_traceback_parts = [head]
1135 1134 if py3compat.PY3:
1136 1135 chained_exceptions_tb_offset = 0
1137 1136 lines_of_context = 3
1138 1137 formatted_exceptions = formatted_exception
1139 1138 exception = self.get_parts_of_chained_exception(evalue)
1140 1139 if exception:
1141 1140 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1142 1141 etype, evalue, etb = exception
1143 1142 else:
1144 1143 evalue = None
1145 1144 chained_exc_ids = set()
1146 1145 while evalue:
1147 1146 formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context,
1148 1147 chained_exceptions_tb_offset)
1149 1148 exception = self.get_parts_of_chained_exception(evalue)
1150 1149
1151 1150 if exception and not id(exception[1]) in chained_exc_ids:
1152 1151 chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop
1153 1152 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1154 1153 etype, evalue, etb = exception
1155 1154 else:
1156 1155 evalue = None
1157 1156
1158 1157 # we want to see exceptions in a reversed order:
1159 1158 # the first exception should be on top
1160 1159 for formatted_exception in reversed(formatted_exceptions):
1161 1160 structured_traceback_parts += formatted_exception
1162 1161 else:
1163 1162 structured_traceback_parts += formatted_exception[0]
1164 1163
1165 1164 return structured_traceback_parts
1166 1165
1167 1166 def debugger(self, force=False):
1168 1167 """Call up the pdb debugger if desired, always clean up the tb
1169 1168 reference.
1170 1169
1171 1170 Keywords:
1172 1171
1173 1172 - force(False): by default, this routine checks the instance call_pdb
1174 1173 flag and does not actually invoke the debugger if the flag is false.
1175 1174 The 'force' option forces the debugger to activate even if the flag
1176 1175 is false.
1177 1176
1178 1177 If the call_pdb flag is set, the pdb interactive debugger is
1179 1178 invoked. In all cases, the self.tb reference to the current traceback
1180 1179 is deleted to prevent lingering references which hamper memory
1181 1180 management.
1182 1181
1183 1182 Note that each call to pdb() does an 'import readline', so if your app
1184 1183 requires a special setup for the readline completers, you'll have to
1185 1184 fix that by hand after invoking the exception handler."""
1186 1185
1187 1186 if force or self.call_pdb:
1188 1187 if self.pdb is None:
1189 1188 self.pdb = self.debugger_cls()
1190 1189 # the system displayhook may have changed, restore the original
1191 1190 # for pdb
1192 1191 display_trap = DisplayTrap(hook=sys.__displayhook__)
1193 1192 with display_trap:
1194 1193 self.pdb.reset()
1195 1194 # Find the right frame so we don't pop up inside ipython itself
1196 1195 if hasattr(self, 'tb') and self.tb is not None:
1197 1196 etb = self.tb
1198 1197 else:
1199 1198 etb = self.tb = sys.last_traceback
1200 1199 while self.tb is not None and self.tb.tb_next is not None:
1201 1200 self.tb = self.tb.tb_next
1202 1201 if etb and etb.tb_next:
1203 1202 etb = etb.tb_next
1204 1203 self.pdb.botframe = etb.tb_frame
1205 1204 self.pdb.interaction(self.tb.tb_frame, self.tb)
1206 1205
1207 1206 if hasattr(self, 'tb'):
1208 1207 del self.tb
1209 1208
1210 1209 def handler(self, info=None):
1211 1210 (etype, evalue, etb) = info or sys.exc_info()
1212 1211 self.tb = etb
1213 1212 ostream = self.ostream
1214 1213 ostream.flush()
1215 1214 ostream.write(self.text(etype, evalue, etb))
1216 1215 ostream.write('\n')
1217 1216 ostream.flush()
1218 1217
1219 1218 # Changed so an instance can just be called as VerboseTB_inst() and print
1220 1219 # out the right info on its own.
1221 1220 def __call__(self, etype=None, evalue=None, etb=None):
1222 1221 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1223 1222 if etb is None:
1224 1223 self.handler()
1225 1224 else:
1226 1225 self.handler((etype, evalue, etb))
1227 1226 try:
1228 1227 self.debugger()
1229 1228 except KeyboardInterrupt:
1230 1229 print("\nKeyboardInterrupt")
1231 1230
1232 1231
1233 1232 #----------------------------------------------------------------------------
1234 1233 class FormattedTB(VerboseTB, ListTB):
1235 1234 """Subclass ListTB but allow calling with a traceback.
1236 1235
1237 1236 It can thus be used as a sys.excepthook for Python > 2.1.
1238 1237
1239 1238 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1240 1239
1241 1240 Allows a tb_offset to be specified. This is useful for situations where
1242 1241 one needs to remove a number of topmost frames from the traceback (such as
1243 1242 occurs with python programs that themselves execute other python code,
1244 1243 like Python shells). """
1245 1244
1246 1245 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1247 1246 ostream=None,
1248 1247 tb_offset=0, long_header=False, include_vars=False,
1249 1248 check_cache=None, debugger_cls=None,
1250 1249 parent=None, config=None):
1251 1250
1252 1251 # NEVER change the order of this list. Put new modes at the end:
1253 1252 self.valid_modes = ['Plain', 'Context', 'Verbose']
1254 1253 self.verbose_modes = self.valid_modes[1:3]
1255 1254
1256 1255 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1257 1256 ostream=ostream, tb_offset=tb_offset,
1258 1257 long_header=long_header, include_vars=include_vars,
1259 1258 check_cache=check_cache, debugger_cls=debugger_cls,
1260 1259 parent=parent, config=config)
1261 1260
1262 1261 # Different types of tracebacks are joined with different separators to
1263 1262 # form a single string. They are taken from this dict
1264 1263 self._join_chars = dict(Plain='', Context='\n', Verbose='\n')
1265 1264 # set_mode also sets the tb_join_char attribute
1266 1265 self.set_mode(mode)
1267 1266
1268 1267 def _extract_tb(self, tb):
1269 1268 if tb:
1270 1269 return traceback.extract_tb(tb)
1271 1270 else:
1272 1271 return None
1273 1272
1274 1273 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
1275 1274 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1276 1275 mode = self.mode
1277 1276 if mode in self.verbose_modes:
1278 1277 # Verbose modes need a full traceback
1279 1278 return VerboseTB.structured_traceback(
1280 1279 self, etype, value, tb, tb_offset, number_of_lines_of_context
1281 1280 )
1282 1281 else:
1283 1282 # We must check the source cache because otherwise we can print
1284 1283 # out-of-date source code.
1285 1284 self.check_cache()
1286 1285 # Now we can extract and format the exception
1287 1286 elist = self._extract_tb(tb)
1288 1287 return ListTB.structured_traceback(
1289 1288 self, etype, value, elist, tb_offset, number_of_lines_of_context
1290 1289 )
1291 1290
1292 1291 def stb2text(self, stb):
1293 1292 """Convert a structured traceback (a list) to a string."""
1294 1293 return self.tb_join_char.join(stb)
1295 1294
1296 1295
1297 1296 def set_mode(self, mode=None):
1298 1297 """Switch to the desired mode.
1299 1298
1300 1299 If mode is not specified, cycles through the available modes."""
1301 1300
1302 1301 if not mode:
1303 1302 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
1304 1303 len(self.valid_modes)
1305 1304 self.mode = self.valid_modes[new_idx]
1306 1305 elif mode not in self.valid_modes:
1307 1306 raise ValueError('Unrecognized mode in FormattedTB: <' + mode + '>\n'
1308 1307 'Valid modes: ' + str(self.valid_modes))
1309 1308 else:
1310 1309 self.mode = mode
1311 1310 # include variable details only in 'Verbose' mode
1312 1311 self.include_vars = (self.mode == self.valid_modes[2])
1313 1312 # Set the join character for generating text tracebacks
1314 1313 self.tb_join_char = self._join_chars[self.mode]
1315 1314
1316 1315 # some convenient shortcuts
1317 1316 def plain(self):
1318 1317 self.set_mode(self.valid_modes[0])
1319 1318
1320 1319 def context(self):
1321 1320 self.set_mode(self.valid_modes[1])
1322 1321
1323 1322 def verbose(self):
1324 1323 self.set_mode(self.valid_modes[2])
1325 1324
1326 1325
1327 1326 #----------------------------------------------------------------------------
1328 1327 class AutoFormattedTB(FormattedTB):
1329 1328 """A traceback printer which can be called on the fly.
1330 1329
1331 1330 It will find out about exceptions by itself.
1332 1331
1333 1332 A brief example::
1334 1333
1335 1334 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1336 1335 try:
1337 1336 ...
1338 1337 except:
1339 1338 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1340 1339 """
1341 1340
1342 1341 def __call__(self, etype=None, evalue=None, etb=None,
1343 1342 out=None, tb_offset=None):
1344 1343 """Print out a formatted exception traceback.
1345 1344
1346 1345 Optional arguments:
1347 1346 - out: an open file-like object to direct output to.
1348 1347
1349 1348 - tb_offset: the number of frames to skip over in the stack, on a
1350 1349 per-call basis (this overrides temporarily the instance's tb_offset
1351 1350 given at initialization time. """
1352 1351
1353 1352 if out is None:
1354 1353 out = self.ostream
1355 1354 out.flush()
1356 1355 out.write(self.text(etype, evalue, etb, tb_offset))
1357 1356 out.write('\n')
1358 1357 out.flush()
1359 1358 # FIXME: we should remove the auto pdb behavior from here and leave
1360 1359 # that to the clients.
1361 1360 try:
1362 1361 self.debugger()
1363 1362 except KeyboardInterrupt:
1364 1363 print("\nKeyboardInterrupt")
1365 1364
1366 1365 def structured_traceback(self, etype=None, value=None, tb=None,
1367 1366 tb_offset=None, number_of_lines_of_context=5):
1368 1367 if etype is None:
1369 1368 etype, value, tb = sys.exc_info()
1370 1369 self.tb = tb
1371 1370 return FormattedTB.structured_traceback(
1372 1371 self, etype, value, tb, tb_offset, number_of_lines_of_context)
1373 1372
1374 1373
1375 1374 #---------------------------------------------------------------------------
1376 1375
1377 1376 # A simple class to preserve Nathan's original functionality.
1378 1377 class ColorTB(FormattedTB):
1379 1378 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1380 1379
1381 1380 def __init__(self, color_scheme='Linux', call_pdb=0, **kwargs):
1382 1381 FormattedTB.__init__(self, color_scheme=color_scheme,
1383 1382 call_pdb=call_pdb, **kwargs)
1384 1383
1385 1384
1386 1385 class SyntaxTB(ListTB):
1387 1386 """Extension which holds some state: the last exception value"""
1388 1387
1389 1388 def __init__(self, color_scheme='NoColor', parent=None, config=None):
1390 1389 ListTB.__init__(self, color_scheme, parent=parent, config=config)
1391 1390 self.last_syntax_error = None
1392 1391
1393 1392 def __call__(self, etype, value, elist):
1394 1393 self.last_syntax_error = value
1395 1394
1396 1395 ListTB.__call__(self, etype, value, elist)
1397 1396
1398 1397 def structured_traceback(self, etype, value, elist, tb_offset=None,
1399 1398 context=5):
1400 1399 # If the source file has been edited, the line in the syntax error can
1401 1400 # be wrong (retrieved from an outdated cache). This replaces it with
1402 1401 # the current value.
1403 1402 if isinstance(value, SyntaxError) \
1404 1403 and isinstance(value.filename, str) \
1405 1404 and isinstance(value.lineno, int):
1406 1405 linecache.checkcache(value.filename)
1407 1406 newtext = linecache.getline(value.filename, value.lineno)
1408 1407 if newtext:
1409 1408 value.text = newtext
1410 1409 self.last_syntax_error = value
1411 1410 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1412 1411 tb_offset=tb_offset, context=context)
1413 1412
1414 1413 def clear_err_state(self):
1415 1414 """Return the current error state and clear it"""
1416 1415 e = self.last_syntax_error
1417 1416 self.last_syntax_error = None
1418 1417 return e
1419 1418
1420 1419 def stb2text(self, stb):
1421 1420 """Convert a structured traceback (a list) to a string."""
1422 1421 return ''.join(stb)
1423 1422
1424 1423
1425 1424 # some internal-use functions
1426 1425 def text_repr(value):
1427 1426 """Hopefully pretty robust repr equivalent."""
1428 1427 # this is pretty horrible but should always return *something*
1429 1428 try:
1430 1429 return pydoc.text.repr(value)
1431 1430 except KeyboardInterrupt:
1432 1431 raise
1433 1432 except:
1434 1433 try:
1435 1434 return repr(value)
1436 1435 except KeyboardInterrupt:
1437 1436 raise
1438 1437 except:
1439 1438 try:
1440 1439 # all still in an except block so we catch
1441 1440 # getattr raising
1442 1441 name = getattr(value, '__name__', None)
1443 1442 if name:
1444 1443 # ick, recursion
1445 1444 return text_repr(name)
1446 1445 klass = getattr(value, '__class__', None)
1447 1446 if klass:
1448 1447 return '%s instance' % text_repr(klass)
1449 1448 except KeyboardInterrupt:
1450 1449 raise
1451 1450 except:
1452 1451 return 'UNRECOVERABLE REPR FAILURE'
1453 1452
1454 1453
1455 1454 def eqrepr(value, repr=text_repr):
1456 1455 return '=%s' % repr(value)
1457 1456
1458 1457
1459 1458 def nullrepr(value, repr=text_repr):
1460 1459 return ''
@@ -1,860 +1,859 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 Python advanced pretty printer. This pretty printer is intended to
4 4 replace the old `pprint` python module which does not allow developers
5 5 to provide their own pretty print callbacks.
6 6
7 7 This module is based on ruby's `prettyprint.rb` library by `Tanaka Akira`.
8 8
9 9
10 10 Example Usage
11 11 -------------
12 12
13 13 To directly print the representation of an object use `pprint`::
14 14
15 15 from pretty import pprint
16 16 pprint(complex_object)
17 17
18 18 To get a string of the output use `pretty`::
19 19
20 20 from pretty import pretty
21 21 string = pretty(complex_object)
22 22
23 23
24 24 Extending
25 25 ---------
26 26
27 27 The pretty library allows developers to add pretty printing rules for their
28 28 own objects. This process is straightforward. All you have to do is to
29 29 add a `_repr_pretty_` method to your object and call the methods on the
30 30 pretty printer passed::
31 31
32 32 class MyObject(object):
33 33
34 34 def _repr_pretty_(self, p, cycle):
35 35 ...
36 36
37 37 Here is an example implementation of a `_repr_pretty_` method for a list
38 38 subclass::
39 39
40 40 class MyList(list):
41 41
42 42 def _repr_pretty_(self, p, cycle):
43 43 if cycle:
44 44 p.text('MyList(...)')
45 45 else:
46 46 with p.group(8, 'MyList([', '])'):
47 47 for idx, item in enumerate(self):
48 48 if idx:
49 49 p.text(',')
50 50 p.breakable()
51 51 p.pretty(item)
52 52
53 53 The `cycle` parameter is `True` if pretty detected a cycle. You *have* to
54 54 react to that or the result is an infinite loop. `p.text()` just adds
55 55 non breaking text to the output, `p.breakable()` either adds a whitespace
56 56 or breaks here. If you pass it an argument it's used instead of the
57 57 default space. `p.pretty` prettyprints another object using the pretty print
58 58 method.
59 59
60 60 The first parameter to the `group` function specifies the extra indentation
61 61 of the next line. In this example the next item will either be on the same
62 62 line (if the items are short enough) or aligned with the right edge of the
63 63 opening bracket of `MyList`.
64 64
65 65 If you just want to indent something you can use the group function
66 66 without open / close parameters. You can also use this code::
67 67
68 68 with p.indent(2):
69 69 ...
70 70
71 71 Inheritance diagram:
72 72
73 73 .. inheritance-diagram:: IPython.lib.pretty
74 74 :parts: 3
75 75
76 76 :copyright: 2007 by Armin Ronacher.
77 77 Portions (c) 2009 by Robert Kern.
78 78 :license: BSD License.
79 79 """
80 80 from contextlib import contextmanager
81 81 import sys
82 82 import types
83 83 import re
84 84 import datetime
85 85 from collections import deque
86 86 from io import StringIO
87 87 from warnings import warn
88 88
89 89 from IPython.utils.decorators import undoc
90 from IPython.utils.py3compat import PYPY, cast_unicode
91 from IPython.utils.encoding import get_stream_enc
90 from IPython.utils.py3compat import PYPY
92 91
93 92
94 93 __all__ = ['pretty', 'pprint', 'PrettyPrinter', 'RepresentationPrinter',
95 94 'for_type', 'for_type_by_name']
96 95
97 96
98 97 MAX_SEQ_LENGTH = 1000
99 98 _re_pattern_type = type(re.compile(''))
100 99
101 100 def _safe_getattr(obj, attr, default=None):
102 101 """Safe version of getattr.
103 102
104 103 Same as getattr, but will return ``default`` on any Exception,
105 104 rather than raising.
106 105 """
107 106 try:
108 107 return getattr(obj, attr, default)
109 108 except Exception:
110 109 return default
111 110
112 111 @undoc
113 112 class CUnicodeIO(StringIO):
114 113 def __init__(self, *args, **kwargs):
115 114 super().__init__(*args, **kwargs)
116 115 warn(("CUnicodeIO is deprecated since IPython 6.0. "
117 116 "Please use io.StringIO instead."),
118 117 DeprecationWarning, stacklevel=2)
119 118
120 119 def pretty(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
121 120 """
122 121 Pretty print the object's representation.
123 122 """
124 123 stream = StringIO()
125 124 printer = RepresentationPrinter(stream, verbose, max_width, newline, max_seq_length=max_seq_length)
126 125 printer.pretty(obj)
127 126 printer.flush()
128 127 return stream.getvalue()
129 128
130 129
131 130 def pprint(obj, verbose=False, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
132 131 """
133 132 Like `pretty` but print to stdout.
134 133 """
135 134 printer = RepresentationPrinter(sys.stdout, verbose, max_width, newline, max_seq_length=max_seq_length)
136 135 printer.pretty(obj)
137 136 printer.flush()
138 137 sys.stdout.write(newline)
139 138 sys.stdout.flush()
140 139
141 140 class _PrettyPrinterBase(object):
142 141
143 142 @contextmanager
144 143 def indent(self, indent):
145 144 """with statement support for indenting/dedenting."""
146 145 self.indentation += indent
147 146 try:
148 147 yield
149 148 finally:
150 149 self.indentation -= indent
151 150
152 151 @contextmanager
153 152 def group(self, indent=0, open='', close=''):
154 153 """like begin_group / end_group but for the with statement."""
155 154 self.begin_group(indent, open)
156 155 try:
157 156 yield
158 157 finally:
159 158 self.end_group(indent, close)
160 159
161 160 class PrettyPrinter(_PrettyPrinterBase):
162 161 """
163 162 Baseclass for the `RepresentationPrinter` prettyprinter that is used to
164 163 generate pretty reprs of objects. Contrary to the `RepresentationPrinter`
165 164 this printer knows nothing about the default pprinters or the `_repr_pretty_`
166 165 callback method.
167 166 """
168 167
169 168 def __init__(self, output, max_width=79, newline='\n', max_seq_length=MAX_SEQ_LENGTH):
170 169 self.output = output
171 170 self.max_width = max_width
172 171 self.newline = newline
173 172 self.max_seq_length = max_seq_length
174 173 self.output_width = 0
175 174 self.buffer_width = 0
176 175 self.buffer = deque()
177 176
178 177 root_group = Group(0)
179 178 self.group_stack = [root_group]
180 179 self.group_queue = GroupQueue(root_group)
181 180 self.indentation = 0
182 181
183 182 def _break_outer_groups(self):
184 183 while self.max_width < self.output_width + self.buffer_width:
185 184 group = self.group_queue.deq()
186 185 if not group:
187 186 return
188 187 while group.breakables:
189 188 x = self.buffer.popleft()
190 189 self.output_width = x.output(self.output, self.output_width)
191 190 self.buffer_width -= x.width
192 191 while self.buffer and isinstance(self.buffer[0], Text):
193 192 x = self.buffer.popleft()
194 193 self.output_width = x.output(self.output, self.output_width)
195 194 self.buffer_width -= x.width
196 195
197 196 def text(self, obj):
198 197 """Add literal text to the output."""
199 198 width = len(obj)
200 199 if self.buffer:
201 200 text = self.buffer[-1]
202 201 if not isinstance(text, Text):
203 202 text = Text()
204 203 self.buffer.append(text)
205 204 text.add(obj, width)
206 205 self.buffer_width += width
207 206 self._break_outer_groups()
208 207 else:
209 208 self.output.write(obj)
210 209 self.output_width += width
211 210
212 211 def breakable(self, sep=' '):
213 212 """
214 213 Add a breakable separator to the output. This does not mean that it
215 214 will automatically break here. If no breaking on this position takes
216 215 place the `sep` is inserted which default to one space.
217 216 """
218 217 width = len(sep)
219 218 group = self.group_stack[-1]
220 219 if group.want_break:
221 220 self.flush()
222 221 self.output.write(self.newline)
223 222 self.output.write(' ' * self.indentation)
224 223 self.output_width = self.indentation
225 224 self.buffer_width = 0
226 225 else:
227 226 self.buffer.append(Breakable(sep, width, self))
228 227 self.buffer_width += width
229 228 self._break_outer_groups()
230 229
231 230 def break_(self):
232 231 """
233 232 Explicitly insert a newline into the output, maintaining correct indentation.
234 233 """
235 234 self.flush()
236 235 self.output.write(self.newline)
237 236 self.output.write(' ' * self.indentation)
238 237 self.output_width = self.indentation
239 238 self.buffer_width = 0
240 239
241 240
242 241 def begin_group(self, indent=0, open=''):
243 242 """
244 243 Begin a group. If you want support for python < 2.5 which doesn't has
245 244 the with statement this is the preferred way:
246 245
247 246 p.begin_group(1, '{')
248 247 ...
249 248 p.end_group(1, '}')
250 249
251 250 The python 2.5 expression would be this:
252 251
253 252 with p.group(1, '{', '}'):
254 253 ...
255 254
256 255 The first parameter specifies the indentation for the next line (usually
257 256 the width of the opening text), the second the opening text. All
258 257 parameters are optional.
259 258 """
260 259 if open:
261 260 self.text(open)
262 261 group = Group(self.group_stack[-1].depth + 1)
263 262 self.group_stack.append(group)
264 263 self.group_queue.enq(group)
265 264 self.indentation += indent
266 265
267 266 def _enumerate(self, seq):
268 267 """like enumerate, but with an upper limit on the number of items"""
269 268 for idx, x in enumerate(seq):
270 269 if self.max_seq_length and idx >= self.max_seq_length:
271 270 self.text(',')
272 271 self.breakable()
273 272 self.text('...')
274 273 return
275 274 yield idx, x
276 275
277 276 def end_group(self, dedent=0, close=''):
278 277 """End a group. See `begin_group` for more details."""
279 278 self.indentation -= dedent
280 279 group = self.group_stack.pop()
281 280 if not group.breakables:
282 281 self.group_queue.remove(group)
283 282 if close:
284 283 self.text(close)
285 284
286 285 def flush(self):
287 286 """Flush data that is left in the buffer."""
288 287 for data in self.buffer:
289 288 self.output_width += data.output(self.output, self.output_width)
290 289 self.buffer.clear()
291 290 self.buffer_width = 0
292 291
293 292
294 293 def _get_mro(obj_class):
295 294 """ Get a reasonable method resolution order of a class and its superclasses
296 295 for both old-style and new-style classes.
297 296 """
298 297 if not hasattr(obj_class, '__mro__'):
299 298 # Old-style class. Mix in object to make a fake new-style class.
300 299 try:
301 300 obj_class = type(obj_class.__name__, (obj_class, object), {})
302 301 except TypeError:
303 302 # Old-style extension type that does not descend from object.
304 303 # FIXME: try to construct a more thorough MRO.
305 304 mro = [obj_class]
306 305 else:
307 306 mro = obj_class.__mro__[1:-1]
308 307 else:
309 308 mro = obj_class.__mro__
310 309 return mro
311 310
312 311
313 312 class RepresentationPrinter(PrettyPrinter):
314 313 """
315 314 Special pretty printer that has a `pretty` method that calls the pretty
316 315 printer for a python object.
317 316
318 317 This class stores processing data on `self` so you must *never* use
319 318 this class in a threaded environment. Always lock it or reinstanciate
320 319 it.
321 320
322 321 Instances also have a verbose flag callbacks can access to control their
323 322 output. For example the default instance repr prints all attributes and
324 323 methods that are not prefixed by an underscore if the printer is in
325 324 verbose mode.
326 325 """
327 326
328 327 def __init__(self, output, verbose=False, max_width=79, newline='\n',
329 328 singleton_pprinters=None, type_pprinters=None, deferred_pprinters=None,
330 329 max_seq_length=MAX_SEQ_LENGTH):
331 330
332 331 PrettyPrinter.__init__(self, output, max_width, newline, max_seq_length=max_seq_length)
333 332 self.verbose = verbose
334 333 self.stack = []
335 334 if singleton_pprinters is None:
336 335 singleton_pprinters = _singleton_pprinters.copy()
337 336 self.singleton_pprinters = singleton_pprinters
338 337 if type_pprinters is None:
339 338 type_pprinters = _type_pprinters.copy()
340 339 self.type_pprinters = type_pprinters
341 340 if deferred_pprinters is None:
342 341 deferred_pprinters = _deferred_type_pprinters.copy()
343 342 self.deferred_pprinters = deferred_pprinters
344 343
345 344 def pretty(self, obj):
346 345 """Pretty print the given object."""
347 346 obj_id = id(obj)
348 347 cycle = obj_id in self.stack
349 348 self.stack.append(obj_id)
350 349 self.begin_group()
351 350 try:
352 351 obj_class = _safe_getattr(obj, '__class__', None) or type(obj)
353 352 # First try to find registered singleton printers for the type.
354 353 try:
355 354 printer = self.singleton_pprinters[obj_id]
356 355 except (TypeError, KeyError):
357 356 pass
358 357 else:
359 358 return printer(obj, self, cycle)
360 359 # Next walk the mro and check for either:
361 360 # 1) a registered printer
362 361 # 2) a _repr_pretty_ method
363 362 for cls in _get_mro(obj_class):
364 363 if cls in self.type_pprinters:
365 364 # printer registered in self.type_pprinters
366 365 return self.type_pprinters[cls](obj, self, cycle)
367 366 else:
368 367 # deferred printer
369 368 printer = self._in_deferred_types(cls)
370 369 if printer is not None:
371 370 return printer(obj, self, cycle)
372 371 else:
373 372 # Finally look for special method names.
374 373 # Some objects automatically create any requested
375 374 # attribute. Try to ignore most of them by checking for
376 375 # callability.
377 376 if '_repr_pretty_' in cls.__dict__:
378 377 meth = cls._repr_pretty_
379 378 if callable(meth):
380 379 return meth(obj, self, cycle)
381 380 return _default_pprint(obj, self, cycle)
382 381 finally:
383 382 self.end_group()
384 383 self.stack.pop()
385 384
386 385 def _in_deferred_types(self, cls):
387 386 """
388 387 Check if the given class is specified in the deferred type registry.
389 388
390 389 Returns the printer from the registry if it exists, and None if the
391 390 class is not in the registry. Successful matches will be moved to the
392 391 regular type registry for future use.
393 392 """
394 393 mod = _safe_getattr(cls, '__module__', None)
395 394 name = _safe_getattr(cls, '__name__', None)
396 395 key = (mod, name)
397 396 printer = None
398 397 if key in self.deferred_pprinters:
399 398 # Move the printer over to the regular registry.
400 399 printer = self.deferred_pprinters.pop(key)
401 400 self.type_pprinters[cls] = printer
402 401 return printer
403 402
404 403
405 404 class Printable(object):
406 405
407 406 def output(self, stream, output_width):
408 407 return output_width
409 408
410 409
411 410 class Text(Printable):
412 411
413 412 def __init__(self):
414 413 self.objs = []
415 414 self.width = 0
416 415
417 416 def output(self, stream, output_width):
418 417 for obj in self.objs:
419 418 stream.write(obj)
420 419 return output_width + self.width
421 420
422 421 def add(self, obj, width):
423 422 self.objs.append(obj)
424 423 self.width += width
425 424
426 425
427 426 class Breakable(Printable):
428 427
429 428 def __init__(self, seq, width, pretty):
430 429 self.obj = seq
431 430 self.width = width
432 431 self.pretty = pretty
433 432 self.indentation = pretty.indentation
434 433 self.group = pretty.group_stack[-1]
435 434 self.group.breakables.append(self)
436 435
437 436 def output(self, stream, output_width):
438 437 self.group.breakables.popleft()
439 438 if self.group.want_break:
440 439 stream.write(self.pretty.newline)
441 440 stream.write(' ' * self.indentation)
442 441 return self.indentation
443 442 if not self.group.breakables:
444 443 self.pretty.group_queue.remove(self.group)
445 444 stream.write(self.obj)
446 445 return output_width + self.width
447 446
448 447
449 448 class Group(Printable):
450 449
451 450 def __init__(self, depth):
452 451 self.depth = depth
453 452 self.breakables = deque()
454 453 self.want_break = False
455 454
456 455
457 456 class GroupQueue(object):
458 457
459 458 def __init__(self, *groups):
460 459 self.queue = []
461 460 for group in groups:
462 461 self.enq(group)
463 462
464 463 def enq(self, group):
465 464 depth = group.depth
466 465 while depth > len(self.queue) - 1:
467 466 self.queue.append([])
468 467 self.queue[depth].append(group)
469 468
470 469 def deq(self):
471 470 for stack in self.queue:
472 471 for idx, group in enumerate(reversed(stack)):
473 472 if group.breakables:
474 473 del stack[idx]
475 474 group.want_break = True
476 475 return group
477 476 for group in stack:
478 477 group.want_break = True
479 478 del stack[:]
480 479
481 480 def remove(self, group):
482 481 try:
483 482 self.queue[group.depth].remove(group)
484 483 except ValueError:
485 484 pass
486 485
487 486
488 487 def _default_pprint(obj, p, cycle):
489 488 """
490 489 The default print function. Used if an object does not provide one and
491 490 it's none of the builtin objects.
492 491 """
493 492 klass = _safe_getattr(obj, '__class__', None) or type(obj)
494 493 if _safe_getattr(klass, '__repr__', None) is not object.__repr__:
495 494 # A user-provided repr. Find newlines and replace them with p.break_()
496 495 _repr_pprint(obj, p, cycle)
497 496 return
498 497 p.begin_group(1, '<')
499 498 p.pretty(klass)
500 499 p.text(' at 0x%x' % id(obj))
501 500 if cycle:
502 501 p.text(' ...')
503 502 elif p.verbose:
504 503 first = True
505 504 for key in dir(obj):
506 505 if not key.startswith('_'):
507 506 try:
508 507 value = getattr(obj, key)
509 508 except AttributeError:
510 509 continue
511 510 if isinstance(value, types.MethodType):
512 511 continue
513 512 if not first:
514 513 p.text(',')
515 514 p.breakable()
516 515 p.text(key)
517 516 p.text('=')
518 517 step = len(key) + 1
519 518 p.indentation += step
520 519 p.pretty(value)
521 520 p.indentation -= step
522 521 first = False
523 522 p.end_group(1, '>')
524 523
525 524
526 525 def _seq_pprinter_factory(start, end, basetype):
527 526 """
528 527 Factory that returns a pprint function useful for sequences. Used by
529 528 the default pprint for tuples, dicts, and lists.
530 529 """
531 530 def inner(obj, p, cycle):
532 531 typ = type(obj)
533 532 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
534 533 # If the subclass provides its own repr, use it instead.
535 534 return p.text(typ.__repr__(obj))
536 535
537 536 if cycle:
538 537 return p.text(start + '...' + end)
539 538 step = len(start)
540 539 p.begin_group(step, start)
541 540 for idx, x in p._enumerate(obj):
542 541 if idx:
543 542 p.text(',')
544 543 p.breakable()
545 544 p.pretty(x)
546 545 if len(obj) == 1 and type(obj) is tuple:
547 546 # Special case for 1-item tuples.
548 547 p.text(',')
549 548 p.end_group(step, end)
550 549 return inner
551 550
552 551
553 552 def _set_pprinter_factory(start, end, basetype):
554 553 """
555 554 Factory that returns a pprint function useful for sets and frozensets.
556 555 """
557 556 def inner(obj, p, cycle):
558 557 typ = type(obj)
559 558 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
560 559 # If the subclass provides its own repr, use it instead.
561 560 return p.text(typ.__repr__(obj))
562 561
563 562 if cycle:
564 563 return p.text(start + '...' + end)
565 564 if len(obj) == 0:
566 565 # Special case.
567 566 p.text(basetype.__name__ + '()')
568 567 else:
569 568 step = len(start)
570 569 p.begin_group(step, start)
571 570 # Like dictionary keys, we will try to sort the items if there aren't too many
572 571 items = obj
573 572 if not (p.max_seq_length and len(obj) >= p.max_seq_length):
574 573 try:
575 574 items = sorted(obj)
576 575 except Exception:
577 576 # Sometimes the items don't sort.
578 577 pass
579 578 for idx, x in p._enumerate(items):
580 579 if idx:
581 580 p.text(',')
582 581 p.breakable()
583 582 p.pretty(x)
584 583 p.end_group(step, end)
585 584 return inner
586 585
587 586
588 587 def _dict_pprinter_factory(start, end, basetype=None):
589 588 """
590 589 Factory that returns a pprint function used by the default pprint of
591 590 dicts and dict proxies.
592 591 """
593 592 def inner(obj, p, cycle):
594 593 typ = type(obj)
595 594 if basetype is not None and typ is not basetype and typ.__repr__ != basetype.__repr__:
596 595 # If the subclass provides its own repr, use it instead.
597 596 return p.text(typ.__repr__(obj))
598 597
599 598 if cycle:
600 599 return p.text('{...}')
601 600 step = len(start)
602 601 p.begin_group(step, start)
603 602 keys = obj.keys()
604 603 # if dict isn't large enough to be truncated, sort keys before displaying
605 604 if not (p.max_seq_length and len(obj) >= p.max_seq_length):
606 605 try:
607 606 keys = sorted(keys)
608 607 except Exception:
609 608 # Sometimes the keys don't sort.
610 609 pass
611 610 for idx, key in p._enumerate(keys):
612 611 if idx:
613 612 p.text(',')
614 613 p.breakable()
615 614 p.pretty(key)
616 615 p.text(': ')
617 616 p.pretty(obj[key])
618 617 p.end_group(step, end)
619 618 return inner
620 619
621 620
622 621 def _super_pprint(obj, p, cycle):
623 622 """The pprint for the super type."""
624 623 p.begin_group(8, '<super: ')
625 624 p.pretty(obj.__thisclass__)
626 625 p.text(',')
627 626 p.breakable()
628 627 if PYPY: # In PyPy, super() objects don't have __self__ attributes
629 628 dself = obj.__repr__.__self__
630 629 p.pretty(None if dself is obj else dself)
631 630 else:
632 631 p.pretty(obj.__self__)
633 632 p.end_group(8, '>')
634 633
635 634
636 635 def _re_pattern_pprint(obj, p, cycle):
637 636 """The pprint function for regular expression patterns."""
638 637 p.text('re.compile(')
639 638 pattern = repr(obj.pattern)
640 639 if pattern[:1] in 'uU':
641 640 pattern = pattern[1:]
642 641 prefix = 'ur'
643 642 else:
644 643 prefix = 'r'
645 644 pattern = prefix + pattern.replace('\\\\', '\\')
646 645 p.text(pattern)
647 646 if obj.flags:
648 647 p.text(',')
649 648 p.breakable()
650 649 done_one = False
651 650 for flag in ('TEMPLATE', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL',
652 651 'UNICODE', 'VERBOSE', 'DEBUG'):
653 652 if obj.flags & getattr(re, flag):
654 653 if done_one:
655 654 p.text('|')
656 655 p.text('re.' + flag)
657 656 done_one = True
658 657 p.text(')')
659 658
660 659
661 660 def _type_pprint(obj, p, cycle):
662 661 """The pprint for classes and types."""
663 662 # Heap allocated types might not have the module attribute,
664 663 # and others may set it to None.
665 664
666 665 # Checks for a __repr__ override in the metaclass. Can't compare the
667 666 # type(obj).__repr__ directly because in PyPy the representation function
668 667 # inherited from type isn't the same type.__repr__
669 668 if [m for m in _get_mro(type(obj)) if "__repr__" in vars(m)][:1] != [type]:
670 669 _repr_pprint(obj, p, cycle)
671 670 return
672 671
673 672 mod = _safe_getattr(obj, '__module__', None)
674 673 try:
675 674 name = obj.__qualname__
676 675 if not isinstance(name, str):
677 676 # This can happen if the type implements __qualname__ as a property
678 677 # or other descriptor in Python 2.
679 678 raise Exception("Try __name__")
680 679 except Exception:
681 680 name = obj.__name__
682 681 if not isinstance(name, str):
683 682 name = '<unknown type>'
684 683
685 684 if mod in (None, '__builtin__', 'builtins', 'exceptions'):
686 685 p.text(name)
687 686 else:
688 687 p.text(mod + '.' + name)
689 688
690 689
691 690 def _repr_pprint(obj, p, cycle):
692 691 """A pprint that just redirects to the normal repr function."""
693 692 # Find newlines and replace them with p.break_()
694 693 output = repr(obj)
695 694 for idx,output_line in enumerate(output.splitlines()):
696 695 if idx:
697 696 p.break_()
698 697 p.text(output_line)
699 698
700 699
701 700 def _function_pprint(obj, p, cycle):
702 701 """Base pprint for all functions and builtin functions."""
703 702 name = _safe_getattr(obj, '__qualname__', obj.__name__)
704 703 mod = obj.__module__
705 704 if mod and mod not in ('__builtin__', 'builtins', 'exceptions'):
706 705 name = mod + '.' + name
707 706 p.text('<function %s>' % name)
708 707
709 708
710 709 def _exception_pprint(obj, p, cycle):
711 710 """Base pprint for all exceptions."""
712 711 name = getattr(obj.__class__, '__qualname__', obj.__class__.__name__)
713 712 if obj.__class__.__module__ not in ('exceptions', 'builtins'):
714 713 name = '%s.%s' % (obj.__class__.__module__, name)
715 714 step = len(name) + 1
716 715 p.begin_group(step, name + '(')
717 716 for idx, arg in enumerate(getattr(obj, 'args', ())):
718 717 if idx:
719 718 p.text(',')
720 719 p.breakable()
721 720 p.pretty(arg)
722 721 p.end_group(step, ')')
723 722
724 723
725 724 #: the exception base
726 725 try:
727 726 _exception_base = BaseException
728 727 except NameError:
729 728 _exception_base = Exception
730 729
731 730
732 731 #: printers for builtin types
733 732 _type_pprinters = {
734 733 int: _repr_pprint,
735 734 float: _repr_pprint,
736 735 str: _repr_pprint,
737 736 tuple: _seq_pprinter_factory('(', ')', tuple),
738 737 list: _seq_pprinter_factory('[', ']', list),
739 738 dict: _dict_pprinter_factory('{', '}', dict),
740 739
741 740 set: _set_pprinter_factory('{', '}', set),
742 741 frozenset: _set_pprinter_factory('frozenset({', '})', frozenset),
743 742 super: _super_pprint,
744 743 _re_pattern_type: _re_pattern_pprint,
745 744 type: _type_pprint,
746 745 types.FunctionType: _function_pprint,
747 746 types.BuiltinFunctionType: _function_pprint,
748 747 types.MethodType: _repr_pprint,
749 748
750 749 datetime.datetime: _repr_pprint,
751 750 datetime.timedelta: _repr_pprint,
752 751 _exception_base: _exception_pprint
753 752 }
754 753
755 754 try:
756 755 # In PyPy, types.DictProxyType is dict, setting the dictproxy printer
757 756 # using dict.setdefault avoids overwritting the dict printer
758 757 _type_pprinters.setdefault(types.DictProxyType,
759 758 _dict_pprinter_factory('dict_proxy({', '})'))
760 759 _type_pprinters[types.ClassType] = _type_pprint
761 760 _type_pprinters[types.SliceType] = _repr_pprint
762 761 except AttributeError: # Python 3
763 762 _type_pprinters[types.MappingProxyType] = \
764 763 _dict_pprinter_factory('mappingproxy({', '})')
765 764 _type_pprinters[slice] = _repr_pprint
766 765
767 766 try:
768 767 _type_pprinters[long] = _repr_pprint
769 768 _type_pprinters[unicode] = _repr_pprint
770 769 except NameError:
771 770 _type_pprinters[range] = _repr_pprint
772 771 _type_pprinters[bytes] = _repr_pprint
773 772
774 773 #: printers for types specified by name
775 774 _deferred_type_pprinters = {
776 775 }
777 776
778 777 def for_type(typ, func):
779 778 """
780 779 Add a pretty printer for a given type.
781 780 """
782 781 oldfunc = _type_pprinters.get(typ, None)
783 782 if func is not None:
784 783 # To support easy restoration of old pprinters, we need to ignore Nones.
785 784 _type_pprinters[typ] = func
786 785 return oldfunc
787 786
788 787 def for_type_by_name(type_module, type_name, func):
789 788 """
790 789 Add a pretty printer for a type specified by the module and name of a type
791 790 rather than the type object itself.
792 791 """
793 792 key = (type_module, type_name)
794 793 oldfunc = _deferred_type_pprinters.get(key, None)
795 794 if func is not None:
796 795 # To support easy restoration of old pprinters, we need to ignore Nones.
797 796 _deferred_type_pprinters[key] = func
798 797 return oldfunc
799 798
800 799
801 800 #: printers for the default singletons
802 801 _singleton_pprinters = dict.fromkeys(map(id, [None, True, False, Ellipsis,
803 802 NotImplemented]), _repr_pprint)
804 803
805 804
806 805 def _defaultdict_pprint(obj, p, cycle):
807 806 name = obj.__class__.__name__
808 807 with p.group(len(name) + 1, name + '(', ')'):
809 808 if cycle:
810 809 p.text('...')
811 810 else:
812 811 p.pretty(obj.default_factory)
813 812 p.text(',')
814 813 p.breakable()
815 814 p.pretty(dict(obj))
816 815
817 816 def _ordereddict_pprint(obj, p, cycle):
818 817 name = obj.__class__.__name__
819 818 with p.group(len(name) + 1, name + '(', ')'):
820 819 if cycle:
821 820 p.text('...')
822 821 elif len(obj):
823 822 p.pretty(list(obj.items()))
824 823
825 824 def _deque_pprint(obj, p, cycle):
826 825 name = obj.__class__.__name__
827 826 with p.group(len(name) + 1, name + '(', ')'):
828 827 if cycle:
829 828 p.text('...')
830 829 else:
831 830 p.pretty(list(obj))
832 831
833 832
834 833 def _counter_pprint(obj, p, cycle):
835 834 name = obj.__class__.__name__
836 835 with p.group(len(name) + 1, name + '(', ')'):
837 836 if cycle:
838 837 p.text('...')
839 838 elif len(obj):
840 839 p.pretty(dict(obj))
841 840
842 841 for_type_by_name('collections', 'defaultdict', _defaultdict_pprint)
843 842 for_type_by_name('collections', 'OrderedDict', _ordereddict_pprint)
844 843 for_type_by_name('collections', 'deque', _deque_pprint)
845 844 for_type_by_name('collections', 'Counter', _counter_pprint)
846 845
847 846 if __name__ == '__main__':
848 847 from random import randrange
849 848 class Foo(object):
850 849 def __init__(self):
851 850 self.foo = 1
852 851 self.bar = re.compile(r'\s+')
853 852 self.blub = dict.fromkeys(range(30), randrange(1, 40))
854 853 self.hehe = 23424.234234
855 854 self.list = ["blub", "blah", self]
856 855
857 856 def get_foo(self):
858 857 print("foo")
859 858
860 859 pprint(Foo(), verbose=True)
General Comments 0
You need to be logged in to leave comments. Login now