##// END OF EJS Templates
remove also a bunch of %-format
Matthias Bussonnier -
Show More
@@ -1,488 +1,488 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 logging
18 18 import os
19 19 import shutil
20 20 import sys
21 21
22 22 from pathlib import Path
23 23
24 24 from traitlets.config.application import Application, catch_config_error
25 25 from traitlets.config.loader import ConfigFileNotFound, PyFileConfigLoader
26 26 from IPython.core import release, crashhandler
27 27 from IPython.core.profiledir import ProfileDir, ProfileDirError
28 28 from IPython.paths import get_ipython_dir, get_ipython_package_dir
29 29 from IPython.utils.path import ensure_dir_exists
30 30 from traitlets import (
31 31 List, Unicode, Type, Bool, Set, Instance, Undefined,
32 32 default, observe,
33 33 )
34 34
35 35 if os.name == "nt":
36 36 programdata = os.environ.get("PROGRAMDATA", None)
37 37 if programdata is not None:
38 38 SYSTEM_CONFIG_DIRS = [str(Path(programdata) / "ipython")]
39 39 else: # PROGRAMDATA is not defined by default on XP.
40 40 SYSTEM_CONFIG_DIRS = []
41 41 else:
42 42 SYSTEM_CONFIG_DIRS = [
43 43 "/usr/local/etc/ipython",
44 44 "/etc/ipython",
45 45 ]
46 46
47 47
48 48 ENV_CONFIG_DIRS = []
49 49 _env_config_dir = os.path.join(sys.prefix, 'etc', 'ipython')
50 50 if _env_config_dir not in SYSTEM_CONFIG_DIRS:
51 51 # only add ENV_CONFIG if sys.prefix is not already included
52 52 ENV_CONFIG_DIRS.append(_env_config_dir)
53 53
54 54
55 55 _envvar = os.environ.get('IPYTHON_SUPPRESS_CONFIG_ERRORS')
56 56 if _envvar in {None, ''}:
57 57 IPYTHON_SUPPRESS_CONFIG_ERRORS = None
58 58 else:
59 59 if _envvar.lower() in {'1','true'}:
60 60 IPYTHON_SUPPRESS_CONFIG_ERRORS = True
61 61 elif _envvar.lower() in {'0','false'} :
62 62 IPYTHON_SUPPRESS_CONFIG_ERRORS = False
63 63 else:
64 64 sys.exit("Unsupported value for environment variable: 'IPYTHON_SUPPRESS_CONFIG_ERRORS' is set to '%s' which is none of {'0', '1', 'false', 'true', ''}."% _envvar )
65 65
66 66 # aliases and flags
67 67
68 68 base_aliases = {}
69 69 if isinstance(Application.aliases, dict):
70 70 # traitlets 5
71 71 base_aliases.update(Application.aliases)
72 72 base_aliases.update(
73 73 {
74 74 "profile-dir": "ProfileDir.location",
75 75 "profile": "BaseIPythonApplication.profile",
76 76 "ipython-dir": "BaseIPythonApplication.ipython_dir",
77 77 "log-level": "Application.log_level",
78 78 "config": "BaseIPythonApplication.extra_config_file",
79 79 }
80 80 )
81 81
82 82 base_flags = dict()
83 83 if isinstance(Application.flags, dict):
84 84 # traitlets 5
85 85 base_flags.update(Application.flags)
86 86 base_flags.update(
87 87 dict(
88 88 debug=(
89 89 {"Application": {"log_level": logging.DEBUG}},
90 90 "set log level to logging.DEBUG (maximize logging output)",
91 91 ),
92 92 quiet=(
93 93 {"Application": {"log_level": logging.CRITICAL}},
94 94 "set log level to logging.CRITICAL (minimize logging output)",
95 95 ),
96 96 init=(
97 97 {
98 98 "BaseIPythonApplication": {
99 99 "copy_config_files": True,
100 100 "auto_create": True,
101 101 }
102 102 },
103 103 """Initialize profile with default config files. This is equivalent
104 104 to running `ipython profile create <profile>` prior to startup.
105 105 """,
106 106 ),
107 107 )
108 108 )
109 109
110 110
111 111 class ProfileAwareConfigLoader(PyFileConfigLoader):
112 112 """A Python file config loader that is aware of IPython profiles."""
113 113 def load_subconfig(self, fname, path=None, profile=None):
114 114 if profile is not None:
115 115 try:
116 116 profile_dir = ProfileDir.find_profile_dir_by_name(
117 117 get_ipython_dir(),
118 118 profile,
119 119 )
120 120 except ProfileDirError:
121 121 return
122 122 path = profile_dir.location
123 123 return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path)
124 124
125 125 class BaseIPythonApplication(Application):
126 126 name = "ipython"
127 127 description = "IPython: an enhanced interactive Python shell."
128 128 version = Unicode(release.version)
129 129
130 130 aliases = base_aliases
131 131 flags = base_flags
132 132 classes = List([ProfileDir])
133 133
134 134 # enable `load_subconfig('cfg.py', profile='name')`
135 135 python_config_loader_class = ProfileAwareConfigLoader
136 136
137 137 # Track whether the config_file has changed,
138 138 # because some logic happens only if we aren't using the default.
139 139 config_file_specified = Set()
140 140
141 141 config_file_name = Unicode()
142 142 @default('config_file_name')
143 143 def _config_file_name_default(self):
144 144 return self.name.replace('-','_') + u'_config.py'
145 145 @observe('config_file_name')
146 146 def _config_file_name_changed(self, change):
147 147 if change['new'] != change['old']:
148 148 self.config_file_specified.add(change['new'])
149 149
150 150 # The directory that contains IPython's builtin profiles.
151 151 builtin_profile_dir = Unicode(
152 152 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
153 153 )
154 154
155 155 config_file_paths = List(Unicode())
156 156 @default('config_file_paths')
157 157 def _config_file_paths_default(self):
158 158 return []
159 159
160 160 extra_config_file = Unicode(
161 161 help="""Path to an extra config file to load.
162 162
163 163 If specified, load this config file in addition to any other IPython config.
164 164 """).tag(config=True)
165 165 @observe('extra_config_file')
166 166 def _extra_config_file_changed(self, change):
167 167 old = change['old']
168 168 new = change['new']
169 169 try:
170 170 self.config_files.remove(old)
171 171 except ValueError:
172 172 pass
173 173 self.config_file_specified.add(new)
174 174 self.config_files.append(new)
175 175
176 176 profile = Unicode(u'default',
177 177 help="""The IPython profile to use."""
178 178 ).tag(config=True)
179 179
180 180 @observe('profile')
181 181 def _profile_changed(self, change):
182 182 self.builtin_profile_dir = os.path.join(
183 183 get_ipython_package_dir(), u'config', u'profile', change['new']
184 184 )
185 185
186 186 add_ipython_dir_to_sys_path = Bool(
187 187 False,
188 188 """Should the IPython profile directory be added to sys path ?
189 189
190 190 This option was non-existing before IPython 8.0, and ipython_dir was added to
191 191 sys path to allow import of extensions present there. This was historical
192 192 baggage from when pip did not exist. This now default to false,
193 193 but can be set to true for legacy reasons.
194 194 """,
195 195 ).tag(config=True)
196 196
197 197 ipython_dir = Unicode(
198 198 help="""
199 199 The name of the IPython directory. This directory is used for logging
200 200 configuration (through profiles), history storage, etc. The default
201 201 is usually $HOME/.ipython. This option can also be specified through
202 202 the environment variable IPYTHONDIR.
203 203 """
204 204 ).tag(config=True)
205 205 @default('ipython_dir')
206 206 def _ipython_dir_default(self):
207 207 d = get_ipython_dir()
208 208 self._ipython_dir_changed({
209 209 'name': 'ipython_dir',
210 210 'old': d,
211 211 'new': d,
212 212 })
213 213 return d
214 214
215 215 _in_init_profile_dir = False
216 216 profile_dir = Instance(ProfileDir, allow_none=True)
217 217 @default('profile_dir')
218 218 def _profile_dir_default(self):
219 219 # avoid recursion
220 220 if self._in_init_profile_dir:
221 221 return
222 222 # profile_dir requested early, force initialization
223 223 self.init_profile_dir()
224 224 return self.profile_dir
225 225
226 226 overwrite = Bool(False,
227 227 help="""Whether to overwrite existing config files when copying"""
228 228 ).tag(config=True)
229 229 auto_create = Bool(False,
230 230 help="""Whether to create profile dir if it doesn't exist"""
231 231 ).tag(config=True)
232 232
233 233 config_files = List(Unicode())
234 234 @default('config_files')
235 235 def _config_files_default(self):
236 236 return [self.config_file_name]
237 237
238 238 copy_config_files = Bool(False,
239 239 help="""Whether to install the default config files into the profile dir.
240 240 If a new profile is being created, and IPython contains config files for that
241 241 profile, then they will be staged into the new directory. Otherwise,
242 242 default config files will be automatically generated.
243 243 """).tag(config=True)
244 244
245 245 verbose_crash = Bool(False,
246 246 help="""Create a massive crash report when IPython encounters what may be an
247 247 internal error. The default is to append a short message to the
248 248 usual traceback""").tag(config=True)
249 249
250 250 # The class to use as the crash handler.
251 251 crash_handler_class = Type(crashhandler.CrashHandler)
252 252
253 253 @catch_config_error
254 254 def __init__(self, **kwargs):
255 255 super(BaseIPythonApplication, self).__init__(**kwargs)
256 256 # ensure current working directory exists
257 257 try:
258 258 os.getcwd()
259 259 except:
260 260 # exit if cwd doesn't exist
261 261 self.log.error("Current working directory doesn't exist.")
262 262 self.exit(1)
263 263
264 264 #-------------------------------------------------------------------------
265 265 # Various stages of Application creation
266 266 #-------------------------------------------------------------------------
267 267
268 268 def init_crash_handler(self):
269 269 """Create a crash handler, typically setting sys.excepthook to it."""
270 270 self.crash_handler = self.crash_handler_class(self)
271 271 sys.excepthook = self.excepthook
272 272 def unset_crashhandler():
273 273 sys.excepthook = sys.__excepthook__
274 274 atexit.register(unset_crashhandler)
275 275
276 276 def excepthook(self, etype, evalue, tb):
277 277 """this is sys.excepthook after init_crashhandler
278 278
279 279 set self.verbose_crash=True to use our full crashhandler, instead of
280 280 a regular traceback with a short message (crash_handler_lite)
281 281 """
282 282
283 283 if self.verbose_crash:
284 284 return self.crash_handler(etype, evalue, tb)
285 285 else:
286 286 return crashhandler.crash_handler_lite(etype, evalue, tb)
287 287
288 288 @observe('ipython_dir')
289 289 def _ipython_dir_changed(self, change):
290 290 old = change['old']
291 291 new = change['new']
292 292 if old is not Undefined:
293 293 str_old = os.path.abspath(old)
294 294 if str_old in sys.path:
295 295 sys.path.remove(str_old)
296 296 if self.add_ipython_dir_to_sys_path:
297 297 str_path = os.path.abspath(new)
298 298 sys.path.append(str_path)
299 299 ensure_dir_exists(new)
300 300 readme = os.path.join(new, "README")
301 301 readme_src = os.path.join(
302 302 get_ipython_package_dir(), "config", "profile", "README"
303 303 )
304 304 if not os.path.exists(readme) and os.path.exists(readme_src):
305 305 shutil.copy(readme_src, readme)
306 306 for d in ("extensions", "nbextensions"):
307 307 path = os.path.join(new, d)
308 308 try:
309 309 ensure_dir_exists(path)
310 310 except OSError as e:
311 311 # this will not be EEXIST
312 312 self.log.error("couldn't create path %s: %s", path, e)
313 self.log.debug("IPYTHONDIR set to: %s" % new)
313 self.log.debug("IPYTHONDIR set to: %s", new)
314 314
315 315 def load_config_file(self, suppress_errors=IPYTHON_SUPPRESS_CONFIG_ERRORS):
316 316 """Load the config file.
317 317
318 318 By default, errors in loading config are handled, and a warning
319 319 printed on screen. For testing, the suppress_errors option is set
320 320 to False, so errors will make tests fail.
321 321
322 322 `suppress_errors` default value is to be `None` in which case the
323 323 behavior default to the one of `traitlets.Application`.
324 324
325 325 The default value can be set :
326 326 - to `False` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '0', or 'false' (case insensitive).
327 327 - to `True` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '1' or 'true' (case insensitive).
328 328 - to `None` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '' (empty string) or leaving it unset.
329 329
330 330 Any other value are invalid, and will make IPython exit with a non-zero return code.
331 331 """
332 332
333 333
334 334 self.log.debug("Searching path %s for config files", self.config_file_paths)
335 335 base_config = 'ipython_config.py'
336 336 self.log.debug("Attempting to load config file: %s" %
337 337 base_config)
338 338 try:
339 339 if suppress_errors is not None:
340 340 old_value = Application.raise_config_file_errors
341 341 Application.raise_config_file_errors = not suppress_errors;
342 342 Application.load_config_file(
343 343 self,
344 344 base_config,
345 345 path=self.config_file_paths
346 346 )
347 347 except ConfigFileNotFound:
348 348 # ignore errors loading parent
349 349 self.log.debug("Config file %s not found", base_config)
350 350 pass
351 351 if suppress_errors is not None:
352 352 Application.raise_config_file_errors = old_value
353 353
354 354 for config_file_name in self.config_files:
355 355 if not config_file_name or config_file_name == base_config:
356 356 continue
357 357 self.log.debug("Attempting to load config file: %s" %
358 358 self.config_file_name)
359 359 try:
360 360 Application.load_config_file(
361 361 self,
362 362 config_file_name,
363 363 path=self.config_file_paths
364 364 )
365 365 except ConfigFileNotFound:
366 366 # Only warn if the default config file was NOT being used.
367 367 if config_file_name in self.config_file_specified:
368 368 msg = self.log.warning
369 369 else:
370 370 msg = self.log.debug
371 371 msg("Config file not found, skipping: %s", config_file_name)
372 372 except Exception:
373 373 # For testing purposes.
374 374 if not suppress_errors:
375 375 raise
376 376 self.log.warning("Error loading config file: %s" %
377 377 self.config_file_name, exc_info=True)
378 378
379 379 def init_profile_dir(self):
380 380 """initialize the profile dir"""
381 381 self._in_init_profile_dir = True
382 382 if self.profile_dir is not None:
383 383 # already ran
384 384 return
385 385 if 'ProfileDir.location' not in self.config:
386 386 # location not specified, find by profile name
387 387 try:
388 388 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
389 389 except ProfileDirError:
390 390 # not found, maybe create it (always create default profile)
391 391 if self.auto_create or self.profile == 'default':
392 392 try:
393 393 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
394 394 except ProfileDirError:
395 395 self.log.fatal("Could not create profile: %r"%self.profile)
396 396 self.exit(1)
397 397 else:
398 398 self.log.info("Created profile dir: %r"%p.location)
399 399 else:
400 400 self.log.fatal("Profile %r not found."%self.profile)
401 401 self.exit(1)
402 402 else:
403 403 self.log.debug("Using existing profile dir: %r", p.location)
404 404 else:
405 405 location = self.config.ProfileDir.location
406 406 # location is fully specified
407 407 try:
408 408 p = ProfileDir.find_profile_dir(location, self.config)
409 409 except ProfileDirError:
410 410 # not found, maybe create it
411 411 if self.auto_create:
412 412 try:
413 413 p = ProfileDir.create_profile_dir(location, self.config)
414 414 except ProfileDirError:
415 415 self.log.fatal("Could not create profile directory: %r"%location)
416 416 self.exit(1)
417 417 else:
418 418 self.log.debug("Creating new profile dir: %r"%location)
419 419 else:
420 420 self.log.fatal("Profile directory %r not found."%location)
421 421 self.exit(1)
422 422 else:
423 423 self.log.debug("Using existing profile dir: %r", p.location)
424 424 # if profile_dir is specified explicitly, set profile name
425 425 dir_name = os.path.basename(p.location)
426 426 if dir_name.startswith('profile_'):
427 427 self.profile = dir_name[8:]
428 428
429 429 self.profile_dir = p
430 430 self.config_file_paths.append(p.location)
431 431 self._in_init_profile_dir = False
432 432
433 433 def init_config_files(self):
434 434 """[optionally] copy default config files into profile dir."""
435 435 self.config_file_paths.extend(ENV_CONFIG_DIRS)
436 436 self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
437 437 # copy config files
438 438 path = Path(self.builtin_profile_dir)
439 439 if self.copy_config_files:
440 440 src = self.profile
441 441
442 442 cfg = self.config_file_name
443 443 if path and (path / cfg).exists():
444 444 self.log.warning(
445 445 "Staging %r from %s into %r [overwrite=%s]"
446 446 % (cfg, src, self.profile_dir.location, self.overwrite)
447 447 )
448 448 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
449 449 else:
450 450 self.stage_default_config_file()
451 451 else:
452 452 # Still stage *bundled* config files, but not generated ones
453 453 # This is necessary for `ipython profile=sympy` to load the profile
454 454 # on the first go
455 455 files = path.glob("*.py")
456 456 for fullpath in files:
457 457 cfg = fullpath.name
458 458 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
459 459 # file was copied
460 460 self.log.warning("Staging bundled %s from %s into %r"%(
461 461 cfg, self.profile, self.profile_dir.location)
462 462 )
463 463
464 464
465 465 def stage_default_config_file(self):
466 466 """auto generate default config file, and stage it into the profile."""
467 467 s = self.generate_config_file()
468 468 config_file = Path(self.profile_dir.location) / self.config_file_name
469 469 if self.overwrite or not config_file.exists():
470 self.log.warning("Generating default config file: %r" % (config_file))
470 self.log.warning("Generating default config file: %r", (config_file))
471 471 config_file.write_text(s, encoding="utf-8")
472 472
473 473 @catch_config_error
474 474 def initialize(self, argv=None):
475 475 # don't hook up crash handler before parsing command-line
476 476 self.parse_command_line(argv)
477 477 self.init_crash_handler()
478 478 if self.subapp is not None:
479 479 # stop here if subapp is taking over
480 480 return
481 481 # save a copy of CLI config to re-load after config files
482 482 # so that it has highest priority
483 483 cl_config = deepcopy(self.config)
484 484 self.init_profile_dir()
485 485 self.init_config_files()
486 486 self.load_config_file()
487 487 # enforce cl-opts override configfile opts:
488 488 self.update_config(cl_config)
@@ -1,451 +1,451 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 from itertools import chain
12 12 import os
13 13 import sys
14 14
15 15 from traitlets.config.application import boolean_flag
16 16 from traitlets.config.configurable import Configurable
17 17 from traitlets.config.loader import Config
18 18 from IPython.core.application import SYSTEM_CONFIG_DIRS, ENV_CONFIG_DIRS
19 19 from IPython.core import pylabtools
20 20 from IPython.utils.contexts import preserve_keys
21 21 from IPython.utils.path import filefind
22 22 from traitlets import (
23 23 Unicode, Instance, List, Bool, CaselessStrEnum, observe,
24 24 DottedObjectName,
25 25 )
26 26 from IPython.terminal import pt_inputhooks
27 27
28 28 #-----------------------------------------------------------------------------
29 29 # Aliases and Flags
30 30 #-----------------------------------------------------------------------------
31 31
32 32 gui_keys = tuple(sorted(pt_inputhooks.backends) + sorted(pt_inputhooks.aliases))
33 33
34 34 backend_keys = sorted(pylabtools.backends.keys())
35 35 backend_keys.insert(0, 'auto')
36 36
37 37 shell_flags = {}
38 38
39 39 addflag = lambda *args: shell_flags.update(boolean_flag(*args))
40 40 addflag('autoindent', 'InteractiveShell.autoindent',
41 41 'Turn on autoindenting.', 'Turn off autoindenting.'
42 42 )
43 43 addflag('automagic', 'InteractiveShell.automagic',
44 44 """Turn on the auto calling of magic commands. Type %%magic at the
45 45 IPython prompt for more information.""",
46 46 'Turn off the auto calling of magic commands.'
47 47 )
48 48 addflag('pdb', 'InteractiveShell.pdb',
49 49 "Enable auto calling the pdb debugger after every exception.",
50 50 "Disable auto calling the pdb debugger after every exception."
51 51 )
52 52 addflag('pprint', 'PlainTextFormatter.pprint',
53 53 "Enable auto pretty printing of results.",
54 54 "Disable auto pretty printing of results."
55 55 )
56 56 addflag('color-info', 'InteractiveShell.color_info',
57 57 """IPython can display information about objects via a set of functions,
58 58 and optionally can use colors for this, syntax highlighting
59 59 source code and various other elements. This is on by default, but can cause
60 60 problems with some pagers. If you see such problems, you can disable the
61 61 colours.""",
62 62 "Disable using colors for info related things."
63 63 )
64 64 addflag('ignore-cwd', 'InteractiveShellApp.ignore_cwd',
65 65 "Exclude the current working directory from sys.path",
66 66 "Include the current working directory in sys.path",
67 67 )
68 68 nosep_config = Config()
69 69 nosep_config.InteractiveShell.separate_in = ''
70 70 nosep_config.InteractiveShell.separate_out = ''
71 71 nosep_config.InteractiveShell.separate_out2 = ''
72 72
73 73 shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
74 74 shell_flags['pylab'] = (
75 75 {'InteractiveShellApp' : {'pylab' : 'auto'}},
76 76 """Pre-load matplotlib and numpy for interactive use with
77 77 the default matplotlib backend."""
78 78 )
79 79 shell_flags['matplotlib'] = (
80 80 {'InteractiveShellApp' : {'matplotlib' : 'auto'}},
81 81 """Configure matplotlib for interactive use with
82 82 the default matplotlib backend."""
83 83 )
84 84
85 85 # it's possible we don't want short aliases for *all* of these:
86 86 shell_aliases = dict(
87 87 autocall='InteractiveShell.autocall',
88 88 colors='InteractiveShell.colors',
89 89 logfile='InteractiveShell.logfile',
90 90 logappend='InteractiveShell.logappend',
91 91 c='InteractiveShellApp.code_to_run',
92 92 m='InteractiveShellApp.module_to_run',
93 93 ext="InteractiveShellApp.extra_extensions",
94 94 gui='InteractiveShellApp.gui',
95 95 pylab='InteractiveShellApp.pylab',
96 96 matplotlib='InteractiveShellApp.matplotlib',
97 97 )
98 98 shell_aliases['cache-size'] = 'InteractiveShell.cache_size'
99 99
100 100 #-----------------------------------------------------------------------------
101 101 # Main classes and functions
102 102 #-----------------------------------------------------------------------------
103 103
104 104 class InteractiveShellApp(Configurable):
105 105 """A Mixin for applications that start InteractiveShell instances.
106 106
107 107 Provides configurables for loading extensions and executing files
108 108 as part of configuring a Shell environment.
109 109
110 110 The following methods should be called by the :meth:`initialize` method
111 111 of the subclass:
112 112
113 113 - :meth:`init_path`
114 114 - :meth:`init_shell` (to be implemented by the subclass)
115 115 - :meth:`init_gui_pylab`
116 116 - :meth:`init_extensions`
117 117 - :meth:`init_code`
118 118 """
119 119 extensions = List(Unicode(),
120 120 help="A list of dotted module names of IPython extensions to load."
121 121 ).tag(config=True)
122 122
123 123 extra_extensions = List(
124 124 DottedObjectName(),
125 125 help="""
126 126 Dotted module name(s) of one or more IPython extensions to load.
127 127
128 128 For specifying extra extensions to load on the command-line.
129 129
130 130 .. versionadded:: 7.10
131 131 """,
132 132 ).tag(config=True)
133 133
134 134 reraise_ipython_extension_failures = Bool(False,
135 135 help="Reraise exceptions encountered loading IPython extensions?",
136 136 ).tag(config=True)
137 137
138 138 # Extensions that are always loaded (not configurable)
139 139 default_extensions = List(Unicode(), [u'storemagic']).tag(config=False)
140 140
141 141 hide_initial_ns = Bool(True,
142 142 help="""Should variables loaded at startup (by startup files, exec_lines, etc.)
143 143 be hidden from tools like %who?"""
144 144 ).tag(config=True)
145 145
146 146 exec_files = List(Unicode(),
147 147 help="""List of files to run at IPython startup."""
148 148 ).tag(config=True)
149 149 exec_PYTHONSTARTUP = Bool(True,
150 150 help="""Run the file referenced by the PYTHONSTARTUP environment
151 151 variable at IPython startup."""
152 152 ).tag(config=True)
153 153 file_to_run = Unicode('',
154 154 help="""A file to be run""").tag(config=True)
155 155
156 156 exec_lines = List(Unicode(),
157 157 help="""lines of code to run at IPython startup."""
158 158 ).tag(config=True)
159 159 code_to_run = Unicode('',
160 160 help="Execute the given command string."
161 161 ).tag(config=True)
162 162 module_to_run = Unicode('',
163 163 help="Run the module as a script."
164 164 ).tag(config=True)
165 165 gui = CaselessStrEnum(gui_keys, allow_none=True,
166 166 help="Enable GUI event loop integration with any of {0}.".format(gui_keys)
167 167 ).tag(config=True)
168 168 matplotlib = CaselessStrEnum(backend_keys, allow_none=True,
169 169 help="""Configure matplotlib for interactive use with
170 170 the default matplotlib backend."""
171 171 ).tag(config=True)
172 172 pylab = CaselessStrEnum(backend_keys, allow_none=True,
173 173 help="""Pre-load matplotlib and numpy for interactive use,
174 174 selecting a particular matplotlib backend and loop integration.
175 175 """
176 176 ).tag(config=True)
177 177 pylab_import_all = Bool(True,
178 178 help="""If true, IPython will populate the user namespace with numpy, pylab, etc.
179 179 and an ``import *`` is done from numpy and pylab, when using pylab mode.
180 180
181 181 When False, pylab mode should not import any names into the user namespace.
182 182 """
183 183 ).tag(config=True)
184 184 ignore_cwd = Bool(
185 185 False,
186 186 help="""If True, IPython will not add the current working directory to sys.path.
187 187 When False, the current working directory is added to sys.path, allowing imports
188 188 of modules defined in the current directory."""
189 189 ).tag(config=True)
190 190 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
191 191 allow_none=True)
192 192 # whether interact-loop should start
193 193 interact = Bool(True)
194 194
195 195 user_ns = Instance(dict, args=None, allow_none=True)
196 196 @observe('user_ns')
197 197 def _user_ns_changed(self, change):
198 198 if self.shell is not None:
199 199 self.shell.user_ns = change['new']
200 200 self.shell.init_user_ns()
201 201
202 202 def init_path(self):
203 203 """Add current working directory, '', to sys.path
204 204
205 205 Unlike Python's default, we insert before the first `site-packages`
206 206 or `dist-packages` directory,
207 207 so that it is after the standard library.
208 208
209 209 .. versionchanged:: 7.2
210 210 Try to insert after the standard library, instead of first.
211 211 .. versionchanged:: 8.0
212 212 Allow optionally not including the current directory in sys.path
213 213 """
214 214 if '' in sys.path or self.ignore_cwd:
215 215 return
216 216 for idx, path in enumerate(sys.path):
217 217 parent, last_part = os.path.split(path)
218 218 if last_part in {'site-packages', 'dist-packages'}:
219 219 break
220 220 else:
221 221 # no site-packages or dist-packages found (?!)
222 222 # back to original behavior of inserting at the front
223 223 idx = 0
224 224 sys.path.insert(idx, '')
225 225
226 226 def init_shell(self):
227 227 raise NotImplementedError("Override in subclasses")
228 228
229 229 def init_gui_pylab(self):
230 230 """Enable GUI event loop integration, taking pylab into account."""
231 231 enable = False
232 232 shell = self.shell
233 233 if self.pylab:
234 234 enable = lambda key: shell.enable_pylab(key, import_all=self.pylab_import_all)
235 235 key = self.pylab
236 236 elif self.matplotlib:
237 237 enable = shell.enable_matplotlib
238 238 key = self.matplotlib
239 239 elif self.gui:
240 240 enable = shell.enable_gui
241 241 key = self.gui
242 242
243 243 if not enable:
244 244 return
245 245
246 246 try:
247 247 r = enable(key)
248 248 except ImportError:
249 249 self.log.warning("Eventloop or matplotlib integration failed. Is matplotlib installed?")
250 250 self.shell.showtraceback()
251 251 return
252 252 except Exception:
253 253 self.log.warning("GUI event loop or pylab initialization failed")
254 254 self.shell.showtraceback()
255 255 return
256 256
257 257 if isinstance(r, tuple):
258 258 gui, backend = r[:2]
259 259 self.log.info("Enabling GUI event loop integration, "
260 260 "eventloop=%s, matplotlib=%s", gui, backend)
261 261 if key == "auto":
262 262 print("Using matplotlib backend: %s" % backend)
263 263 else:
264 264 gui = r
265 265 self.log.info("Enabling GUI event loop integration, "
266 266 "eventloop=%s", gui)
267 267
268 268 def init_extensions(self):
269 269 """Load all IPython extensions in IPythonApp.extensions.
270 270
271 271 This uses the :meth:`ExtensionManager.load_extensions` to load all
272 272 the extensions listed in ``self.extensions``.
273 273 """
274 274 try:
275 275 self.log.debug("Loading IPython extensions...")
276 276 extensions = (
277 277 self.default_extensions + self.extensions + self.extra_extensions
278 278 )
279 279 for ext in extensions:
280 280 try:
281 self.log.info("Loading IPython extension: %s" % ext)
281 self.log.info("Loading IPython extension: %s", ext)
282 282 self.shell.extension_manager.load_extension(ext)
283 283 except:
284 284 if self.reraise_ipython_extension_failures:
285 285 raise
286 286 msg = ("Error in loading extension: {ext}\n"
287 287 "Check your config files in {location}".format(
288 288 ext=ext,
289 289 location=self.profile_dir.location
290 290 ))
291 291 self.log.warning(msg, exc_info=True)
292 292 except:
293 293 if self.reraise_ipython_extension_failures:
294 294 raise
295 295 self.log.warning("Unknown error in loading extensions:", exc_info=True)
296 296
297 297 def init_code(self):
298 298 """run the pre-flight code, specified via exec_lines"""
299 299 self._run_startup_files()
300 300 self._run_exec_lines()
301 301 self._run_exec_files()
302 302
303 303 # Hide variables defined here from %who etc.
304 304 if self.hide_initial_ns:
305 305 self.shell.user_ns_hidden.update(self.shell.user_ns)
306 306
307 307 # command-line execution (ipython -i script.py, ipython -m module)
308 308 # should *not* be excluded from %whos
309 309 self._run_cmd_line_code()
310 310 self._run_module()
311 311
312 312 # flush output, so itwon't be attached to the first cell
313 313 sys.stdout.flush()
314 314 sys.stderr.flush()
315 315 self.shell._sys_modules_keys = set(sys.modules.keys())
316 316
317 317 def _run_exec_lines(self):
318 318 """Run lines of code in IPythonApp.exec_lines in the user's namespace."""
319 319 if not self.exec_lines:
320 320 return
321 321 try:
322 322 self.log.debug("Running code from IPythonApp.exec_lines...")
323 323 for line in self.exec_lines:
324 324 try:
325 325 self.log.info("Running code in user namespace: %s" %
326 326 line)
327 327 self.shell.run_cell(line, store_history=False)
328 328 except:
329 329 self.log.warning("Error in executing line in user "
330 330 "namespace: %s" % line)
331 331 self.shell.showtraceback()
332 332 except:
333 333 self.log.warning("Unknown error in handling IPythonApp.exec_lines:")
334 334 self.shell.showtraceback()
335 335
336 336 def _exec_file(self, fname, shell_futures=False):
337 337 try:
338 338 full_filename = filefind(fname, [u'.', self.ipython_dir])
339 339 except IOError:
340 340 self.log.warning("File not found: %r"%fname)
341 341 return
342 342 # Make sure that the running script gets a proper sys.argv as if it
343 343 # were run from a system shell.
344 344 save_argv = sys.argv
345 345 sys.argv = [full_filename] + self.extra_args[1:]
346 346 try:
347 347 if os.path.isfile(full_filename):
348 348 self.log.info("Running file in user namespace: %s" %
349 349 full_filename)
350 350 # Ensure that __file__ is always defined to match Python
351 351 # behavior.
352 352 with preserve_keys(self.shell.user_ns, '__file__'):
353 353 self.shell.user_ns['__file__'] = fname
354 354 if full_filename.endswith('.ipy') or full_filename.endswith('.ipynb'):
355 355 self.shell.safe_execfile_ipy(full_filename,
356 356 shell_futures=shell_futures)
357 357 else:
358 358 # default to python, even without extension
359 359 self.shell.safe_execfile(full_filename,
360 360 self.shell.user_ns,
361 361 shell_futures=shell_futures,
362 362 raise_exceptions=True)
363 363 finally:
364 364 sys.argv = save_argv
365 365
366 366 def _run_startup_files(self):
367 367 """Run files from profile startup directory"""
368 368 startup_dirs = [self.profile_dir.startup_dir] + [
369 369 os.path.join(p, 'startup') for p in chain(ENV_CONFIG_DIRS, SYSTEM_CONFIG_DIRS)
370 370 ]
371 371 startup_files = []
372 372
373 373 if self.exec_PYTHONSTARTUP and os.environ.get('PYTHONSTARTUP', False) and \
374 374 not (self.file_to_run or self.code_to_run or self.module_to_run):
375 375 python_startup = os.environ['PYTHONSTARTUP']
376 376 self.log.debug("Running PYTHONSTARTUP file %s...", python_startup)
377 377 try:
378 378 self._exec_file(python_startup)
379 379 except:
380 380 self.log.warning("Unknown error in handling PYTHONSTARTUP file %s:", python_startup)
381 381 self.shell.showtraceback()
382 382 for startup_dir in startup_dirs[::-1]:
383 383 startup_files += glob.glob(os.path.join(startup_dir, '*.py'))
384 384 startup_files += glob.glob(os.path.join(startup_dir, '*.ipy'))
385 385 if not startup_files:
386 386 return
387 387
388 388 self.log.debug("Running startup files from %s...", startup_dir)
389 389 try:
390 390 for fname in sorted(startup_files):
391 391 self._exec_file(fname)
392 392 except:
393 393 self.log.warning("Unknown error in handling startup files:")
394 394 self.shell.showtraceback()
395 395
396 396 def _run_exec_files(self):
397 397 """Run files from IPythonApp.exec_files"""
398 398 if not self.exec_files:
399 399 return
400 400
401 401 self.log.debug("Running files in IPythonApp.exec_files...")
402 402 try:
403 403 for fname in self.exec_files:
404 404 self._exec_file(fname)
405 405 except:
406 406 self.log.warning("Unknown error in handling IPythonApp.exec_files:")
407 407 self.shell.showtraceback()
408 408
409 409 def _run_cmd_line_code(self):
410 410 """Run code or file specified at the command-line"""
411 411 if self.code_to_run:
412 412 line = self.code_to_run
413 413 try:
414 414 self.log.info("Running code given at command line (c=): %s" %
415 415 line)
416 416 self.shell.run_cell(line, store_history=False)
417 417 except:
418 418 self.log.warning("Error in executing line in user namespace: %s" %
419 419 line)
420 420 self.shell.showtraceback()
421 421 if not self.interact:
422 422 self.exit(1)
423 423
424 424 # Like Python itself, ignore the second if the first of these is present
425 425 elif self.file_to_run:
426 426 fname = self.file_to_run
427 427 if os.path.isdir(fname):
428 428 fname = os.path.join(fname, "__main__.py")
429 429 if not os.path.exists(fname):
430 430 self.log.warning("File '%s' doesn't exist", fname)
431 431 if not self.interact:
432 432 self.exit(2)
433 433 try:
434 434 self._exec_file(fname, shell_futures=True)
435 435 except:
436 436 self.shell.showtraceback(tb_offset=4)
437 437 if not self.interact:
438 438 self.exit(1)
439 439
440 440 def _run_module(self):
441 441 """Run module specified at the command-line."""
442 442 if self.module_to_run:
443 443 # Make sure that the module gets a proper sys.argv as if it were
444 444 # run using `python -m`.
445 445 save_argv = sys.argv
446 446 sys.argv = [sys.executable] + self.extra_args
447 447 try:
448 448 self.shell.safe_run_module(self.module_to_run,
449 449 self.shell.user_ns)
450 450 finally:
451 451 sys.argv = save_argv
General Comments 0
You need to be logged in to leave comments. Login now