##// END OF EJS Templates
DEV: Add exit_on_extension_load_failure to InteractiveShellApp.
Scott Sanderson -
Show More
@@ -1,422 +1,432 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 from __future__ import absolute_import
11 11 from __future__ import print_function
12 12
13 13 import glob
14 14 import os
15 15 import sys
16 16
17 17 from IPython.config.application import boolean_flag
18 18 from IPython.config.configurable import Configurable
19 19 from IPython.config.loader import Config
20 20 from IPython.core import pylabtools
21 21 from IPython.utils import py3compat
22 22 from IPython.utils.contexts import preserve_keys
23 23 from IPython.utils.path import filefind
24 24 from IPython.utils.traitlets import (
25 25 Unicode, Instance, List, Bool, CaselessStrEnum
26 26 )
27 27 from IPython.lib.inputhook import guis
28 28
29 29 #-----------------------------------------------------------------------------
30 30 # Aliases and Flags
31 31 #-----------------------------------------------------------------------------
32 32
33 33 gui_keys = tuple(sorted([ key for key in guis if key is not None ]))
34 34
35 35 backend_keys = sorted(pylabtools.backends.keys())
36 36 backend_keys.insert(0, 'auto')
37 37
38 38 shell_flags = {}
39 39
40 40 addflag = lambda *args: shell_flags.update(boolean_flag(*args))
41 41 addflag('autoindent', 'InteractiveShell.autoindent',
42 42 'Turn on autoindenting.', 'Turn off autoindenting.'
43 43 )
44 44 addflag('automagic', 'InteractiveShell.automagic',
45 45 """Turn on the auto calling of magic commands. Type %%magic at the
46 46 IPython prompt for more information.""",
47 47 'Turn off the auto calling of magic commands.'
48 48 )
49 49 addflag('pdb', 'InteractiveShell.pdb',
50 50 "Enable auto calling the pdb debugger after every exception.",
51 51 "Disable auto calling the pdb debugger after every exception."
52 52 )
53 53 # pydb flag doesn't do any config, as core.debugger switches on import,
54 54 # which is before parsing. This just allows the flag to be passed.
55 55 shell_flags.update(dict(
56 56 pydb = ({},
57 57 """Use the third party 'pydb' package as debugger, instead of pdb.
58 58 Requires that pydb is installed."""
59 59 )
60 60 ))
61 61 addflag('pprint', 'PlainTextFormatter.pprint',
62 62 "Enable auto pretty printing of results.",
63 63 "Disable auto pretty printing of results."
64 64 )
65 65 addflag('color-info', 'InteractiveShell.color_info',
66 66 """IPython can display information about objects via a set of functions,
67 67 and optionally can use colors for this, syntax highlighting
68 68 source code and various other elements. This is on by default, but can cause
69 69 problems with some pagers. If you see such problems, you can disable the
70 70 colours.""",
71 71 "Disable using colors for info related things."
72 72 )
73 73 addflag('deep-reload', 'InteractiveShell.deep_reload',
74 74 """Enable deep (recursive) reloading by default. IPython can use the
75 75 deep_reload module which reloads changes in modules recursively (it
76 76 replaces the reload() function, so you don't need to change anything to
77 77 use it). deep_reload() forces a full reload of modules whose code may
78 78 have changed, which the default reload() function does not. When
79 79 deep_reload is off, IPython will use the normal reload(), but
80 80 deep_reload will still be available as dreload(). This feature is off
81 81 by default [which means that you have both normal reload() and
82 82 dreload()].""",
83 83 "Disable deep (recursive) reloading by default."
84 84 )
85 85 nosep_config = Config()
86 86 nosep_config.InteractiveShell.separate_in = ''
87 87 nosep_config.InteractiveShell.separate_out = ''
88 88 nosep_config.InteractiveShell.separate_out2 = ''
89 89
90 90 shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
91 91 shell_flags['pylab'] = (
92 92 {'InteractiveShellApp' : {'pylab' : 'auto'}},
93 93 """Pre-load matplotlib and numpy for interactive use with
94 94 the default matplotlib backend."""
95 95 )
96 96 shell_flags['matplotlib'] = (
97 97 {'InteractiveShellApp' : {'matplotlib' : 'auto'}},
98 98 """Configure matplotlib for interactive use with
99 99 the default matplotlib backend."""
100 100 )
101 101
102 102 # it's possible we don't want short aliases for *all* of these:
103 103 shell_aliases = dict(
104 104 autocall='InteractiveShell.autocall',
105 105 colors='InteractiveShell.colors',
106 106 logfile='InteractiveShell.logfile',
107 107 logappend='InteractiveShell.logappend',
108 108 c='InteractiveShellApp.code_to_run',
109 109 m='InteractiveShellApp.module_to_run',
110 110 ext='InteractiveShellApp.extra_extension',
111 111 gui='InteractiveShellApp.gui',
112 112 pylab='InteractiveShellApp.pylab',
113 113 matplotlib='InteractiveShellApp.matplotlib',
114 114 )
115 115 shell_aliases['cache-size'] = 'InteractiveShell.cache_size'
116 116
117 117 #-----------------------------------------------------------------------------
118 118 # Main classes and functions
119 119 #-----------------------------------------------------------------------------
120 120
121 121 class InteractiveShellApp(Configurable):
122 122 """A Mixin for applications that start InteractiveShell instances.
123 123
124 124 Provides configurables for loading extensions and executing files
125 125 as part of configuring a Shell environment.
126 126
127 127 The following methods should be called by the :meth:`initialize` method
128 128 of the subclass:
129 129
130 130 - :meth:`init_path`
131 131 - :meth:`init_shell` (to be implemented by the subclass)
132 132 - :meth:`init_gui_pylab`
133 133 - :meth:`init_extensions`
134 134 - :meth:`init_code`
135 135 """
136 136 extensions = List(Unicode, config=True,
137 137 help="A list of dotted module names of IPython extensions to load."
138 138 )
139 139 extra_extension = Unicode('', config=True,
140 140 help="dotted module name of an IPython extension to load."
141 141 )
142
142
143 reraise_ipython_extension_failures = Bool(
144 False,
145 config=True,
146 help="If True, exit on failure to load any extensions.",
147 )
148
143 149 # Extensions that are always loaded (not configurable)
144 150 default_extensions = List(Unicode, [u'storemagic'], config=False)
145 151
146 152 hide_initial_ns = Bool(True, config=True,
147 153 help="""Should variables loaded at startup (by startup files, exec_lines, etc.)
148 154 be hidden from tools like %who?"""
149 155 )
150 156
151 157 exec_files = List(Unicode, config=True,
152 158 help="""List of files to run at IPython startup."""
153 159 )
154 160 exec_PYTHONSTARTUP = Bool(True, config=True,
155 161 help="""Run the file referenced by the PYTHONSTARTUP environment
156 162 variable at IPython startup."""
157 163 )
158 164 file_to_run = Unicode('', config=True,
159 165 help="""A file to be run""")
160 166
161 167 exec_lines = List(Unicode, config=True,
162 168 help="""lines of code to run at IPython startup."""
163 169 )
164 170 code_to_run = Unicode('', config=True,
165 171 help="Execute the given command string."
166 172 )
167 173 module_to_run = Unicode('', config=True,
168 174 help="Run the module as a script."
169 175 )
170 176 gui = CaselessStrEnum(gui_keys, config=True,
171 177 help="Enable GUI event loop integration with any of {0}.".format(gui_keys)
172 178 )
173 179 matplotlib = CaselessStrEnum(backend_keys,
174 180 config=True,
175 181 help="""Configure matplotlib for interactive use with
176 182 the default matplotlib backend."""
177 183 )
178 184 pylab = CaselessStrEnum(backend_keys,
179 185 config=True,
180 186 help="""Pre-load matplotlib and numpy for interactive use,
181 187 selecting a particular matplotlib backend and loop integration.
182 188 """
183 189 )
184 190 pylab_import_all = Bool(True, config=True,
185 191 help="""If true, IPython will populate the user namespace with numpy, pylab, etc.
186 192 and an ``import *`` is done from numpy and pylab, when using pylab mode.
187 193
188 194 When False, pylab mode should not import any names into the user namespace.
189 195 """
190 196 )
191 197 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
192 198
193 199 user_ns = Instance(dict, args=None, allow_none=True)
194 200 def _user_ns_changed(self, name, old, new):
195 201 if self.shell is not None:
196 202 self.shell.user_ns = new
197 203 self.shell.init_user_ns()
198 204
199 205 def init_path(self):
200 206 """Add current working directory, '', to sys.path"""
201 207 if sys.path[0] != '':
202 208 sys.path.insert(0, '')
203 209
204 210 def init_shell(self):
205 211 raise NotImplementedError("Override in subclasses")
206 212
207 213 def init_gui_pylab(self):
208 214 """Enable GUI event loop integration, taking pylab into account."""
209 215 enable = False
210 216 shell = self.shell
211 217 if self.pylab:
212 218 enable = lambda key: shell.enable_pylab(key, import_all=self.pylab_import_all)
213 219 key = self.pylab
214 220 elif self.matplotlib:
215 221 enable = shell.enable_matplotlib
216 222 key = self.matplotlib
217 223 elif self.gui:
218 224 enable = shell.enable_gui
219 225 key = self.gui
220 226
221 227 if not enable:
222 228 return
223 229
224 230 try:
225 231 r = enable(key)
226 232 except ImportError:
227 233 self.log.warn("Eventloop or matplotlib integration failed. Is matplotlib installed?")
228 234 self.shell.showtraceback()
229 235 return
230 236 except Exception:
231 237 self.log.warn("GUI event loop or pylab initialization failed")
232 238 self.shell.showtraceback()
233 239 return
234 240
235 241 if isinstance(r, tuple):
236 242 gui, backend = r[:2]
237 243 self.log.info("Enabling GUI event loop integration, "
238 244 "eventloop=%s, matplotlib=%s", gui, backend)
239 245 if key == "auto":
240 246 print("Using matplotlib backend: %s" % backend)
241 247 else:
242 248 gui = r
243 249 self.log.info("Enabling GUI event loop integration, "
244 250 "eventloop=%s", gui)
245 251
246 252 def init_extensions(self):
247 253 """Load all IPython extensions in IPythonApp.extensions.
248 254
249 255 This uses the :meth:`ExtensionManager.load_extensions` to load all
250 256 the extensions listed in ``self.extensions``.
251 257 """
252 258 try:
253 259 self.log.debug("Loading IPython extensions...")
254 260 extensions = self.default_extensions + self.extensions
255 261 if self.extra_extension:
256 262 extensions.append(self.extra_extension)
257 263 for ext in extensions:
258 264 try:
259 265 self.log.info("Loading IPython extension: %s" % ext)
260 266 self.shell.extension_manager.load_extension(ext)
261 267 except:
268 if self.exit_on_extension_load_failure:
269 raise
262 270 msg = ("Error in loading extension: {ext}\n"
263 271 "Check your config files in {location}".format(
264 272 ext=ext,
265 273 location=self.profile_dir.location
266 274 ))
267 275 self.log.warn(msg, exc_info=True)
268 276 except:
277 if self.exit_on_extension_load_failure:
278 raise
269 279 self.log.warn("Unknown error in loading extensions:", exc_info=True)
270 280
271 281 def init_code(self):
272 282 """run the pre-flight code, specified via exec_lines"""
273 283 self._run_startup_files()
274 284 self._run_exec_lines()
275 285 self._run_exec_files()
276 286
277 287 # Hide variables defined here from %who etc.
278 288 if self.hide_initial_ns:
279 289 self.shell.user_ns_hidden.update(self.shell.user_ns)
280 290
281 291 # command-line execution (ipython -i script.py, ipython -m module)
282 292 # should *not* be excluded from %whos
283 293 self._run_cmd_line_code()
284 294 self._run_module()
285 295
286 296 # flush output, so itwon't be attached to the first cell
287 297 sys.stdout.flush()
288 298 sys.stderr.flush()
289 299
290 300 def _run_exec_lines(self):
291 301 """Run lines of code in IPythonApp.exec_lines in the user's namespace."""
292 302 if not self.exec_lines:
293 303 return
294 304 try:
295 305 self.log.debug("Running code from IPythonApp.exec_lines...")
296 306 for line in self.exec_lines:
297 307 try:
298 308 self.log.info("Running code in user namespace: %s" %
299 309 line)
300 310 self.shell.run_cell(line, store_history=False)
301 311 except:
302 312 self.log.warn("Error in executing line in user "
303 313 "namespace: %s" % line)
304 314 self.shell.showtraceback()
305 315 except:
306 316 self.log.warn("Unknown error in handling IPythonApp.exec_lines:")
307 317 self.shell.showtraceback()
308 318
309 319 def _exec_file(self, fname, shell_futures=False):
310 320 try:
311 321 full_filename = filefind(fname, [u'.', self.ipython_dir])
312 322 except IOError as e:
313 323 self.log.warn("File not found: %r"%fname)
314 324 return
315 325 # Make sure that the running script gets a proper sys.argv as if it
316 326 # were run from a system shell.
317 327 save_argv = sys.argv
318 328 sys.argv = [full_filename] + self.extra_args[1:]
319 329 # protect sys.argv from potential unicode strings on Python 2:
320 330 if not py3compat.PY3:
321 331 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
322 332 try:
323 333 if os.path.isfile(full_filename):
324 334 self.log.info("Running file in user namespace: %s" %
325 335 full_filename)
326 336 # Ensure that __file__ is always defined to match Python
327 337 # behavior.
328 338 with preserve_keys(self.shell.user_ns, '__file__'):
329 339 self.shell.user_ns['__file__'] = fname
330 340 if full_filename.endswith('.ipy'):
331 341 self.shell.safe_execfile_ipy(full_filename,
332 342 shell_futures=shell_futures)
333 343 else:
334 344 # default to python, even without extension
335 345 self.shell.safe_execfile(full_filename,
336 346 self.shell.user_ns,
337 347 shell_futures=shell_futures)
338 348 finally:
339 349 sys.argv = save_argv
340 350
341 351 def _run_startup_files(self):
342 352 """Run files from profile startup directory"""
343 353 startup_dir = self.profile_dir.startup_dir
344 354 startup_files = []
345 355
346 356 if self.exec_PYTHONSTARTUP and os.environ.get('PYTHONSTARTUP', False) and \
347 357 not (self.file_to_run or self.code_to_run or self.module_to_run):
348 358 python_startup = os.environ['PYTHONSTARTUP']
349 359 self.log.debug("Running PYTHONSTARTUP file %s...", python_startup)
350 360 try:
351 361 self._exec_file(python_startup)
352 362 except:
353 363 self.log.warn("Unknown error in handling PYTHONSTARTUP file %s:", python_startup)
354 364 self.shell.showtraceback()
355 365 finally:
356 366 # Many PYTHONSTARTUP files set up the readline completions,
357 367 # but this is often at odds with IPython's own completions.
358 368 # Do not allow PYTHONSTARTUP to set up readline.
359 369 if self.shell.has_readline:
360 370 self.shell.set_readline_completer()
361 371
362 372 startup_files += glob.glob(os.path.join(startup_dir, '*.py'))
363 373 startup_files += glob.glob(os.path.join(startup_dir, '*.ipy'))
364 374 if not startup_files:
365 375 return
366 376
367 377 self.log.debug("Running startup files from %s...", startup_dir)
368 378 try:
369 379 for fname in sorted(startup_files):
370 380 self._exec_file(fname)
371 381 except:
372 382 self.log.warn("Unknown error in handling startup files:")
373 383 self.shell.showtraceback()
374 384
375 385 def _run_exec_files(self):
376 386 """Run files from IPythonApp.exec_files"""
377 387 if not self.exec_files:
378 388 return
379 389
380 390 self.log.debug("Running files in IPythonApp.exec_files...")
381 391 try:
382 392 for fname in self.exec_files:
383 393 self._exec_file(fname)
384 394 except:
385 395 self.log.warn("Unknown error in handling IPythonApp.exec_files:")
386 396 self.shell.showtraceback()
387 397
388 398 def _run_cmd_line_code(self):
389 399 """Run code or file specified at the command-line"""
390 400 if self.code_to_run:
391 401 line = self.code_to_run
392 402 try:
393 403 self.log.info("Running code given at command line (c=): %s" %
394 404 line)
395 405 self.shell.run_cell(line, store_history=False)
396 406 except:
397 407 self.log.warn("Error in executing line in user namespace: %s" %
398 408 line)
399 409 self.shell.showtraceback()
400 410
401 411 # Like Python itself, ignore the second if the first of these is present
402 412 elif self.file_to_run:
403 413 fname = self.file_to_run
404 414 try:
405 415 self._exec_file(fname, shell_futures=True)
406 416 except:
407 417 self.log.warn("Error in executing file in user namespace: %s" %
408 418 fname)
409 419 self.shell.showtraceback()
410 420
411 421 def _run_module(self):
412 422 """Run module specified at the command-line."""
413 423 if self.module_to_run:
414 424 # Make sure that the module gets a proper sys.argv as if it were
415 425 # run using `python -m`.
416 426 save_argv = sys.argv
417 427 sys.argv = [sys.executable] + self.extra_args
418 428 try:
419 429 self.shell.safe_run_module(self.module_to_run,
420 430 self.shell.user_ns)
421 431 finally:
422 432 sys.argv = save_argv
General Comments 0
You need to be logged in to leave comments. Login now