##// END OF EJS Templates
Set exit code on script errors....
Fairly -
Show More

The requested changes are too big and content was truncated. Show full diff

1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,433 +1,433 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 traitlets.config.application import boolean_flag
18 18 from traitlets.config.configurable import Configurable
19 19 from traitlets.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 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 """ **Deprecated** 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 143 reraise_ipython_extension_failures = Bool(
144 144 False,
145 145 config=True,
146 146 help="Reraise exceptions encountered loading IPython extensions?",
147 147 )
148 148
149 149 # Extensions that are always loaded (not configurable)
150 150 default_extensions = List(Unicode(), [u'storemagic'], config=False)
151 151
152 152 hide_initial_ns = Bool(True, config=True,
153 153 help="""Should variables loaded at startup (by startup files, exec_lines, etc.)
154 154 be hidden from tools like %who?"""
155 155 )
156 156
157 157 exec_files = List(Unicode(), config=True,
158 158 help="""List of files to run at IPython startup."""
159 159 )
160 160 exec_PYTHONSTARTUP = Bool(True, config=True,
161 161 help="""Run the file referenced by the PYTHONSTARTUP environment
162 162 variable at IPython startup."""
163 163 )
164 164 file_to_run = Unicode('', config=True,
165 165 help="""A file to be run""")
166 166
167 167 exec_lines = List(Unicode(), config=True,
168 168 help="""lines of code to run at IPython startup."""
169 169 )
170 170 code_to_run = Unicode('', config=True,
171 171 help="Execute the given command string."
172 172 )
173 173 module_to_run = Unicode('', config=True,
174 174 help="Run the module as a script."
175 175 )
176 176 gui = CaselessStrEnum(gui_keys, config=True, allow_none=True,
177 177 help="Enable GUI event loop integration with any of {0}.".format(gui_keys)
178 178 )
179 179 matplotlib = CaselessStrEnum(backend_keys, allow_none=True,
180 180 config=True,
181 181 help="""Configure matplotlib for interactive use with
182 182 the default matplotlib backend."""
183 183 )
184 184 pylab = CaselessStrEnum(backend_keys, allow_none=True,
185 185 config=True,
186 186 help="""Pre-load matplotlib and numpy for interactive use,
187 187 selecting a particular matplotlib backend and loop integration.
188 188 """
189 189 )
190 190 pylab_import_all = Bool(True, config=True,
191 191 help="""If true, IPython will populate the user namespace with numpy, pylab, etc.
192 192 and an ``import *`` is done from numpy and pylab, when using pylab mode.
193 193
194 194 When False, pylab mode should not import any names into the user namespace.
195 195 """
196 196 )
197 197 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
198 198 allow_none=True)
199 199
200 200 user_ns = Instance(dict, args=None, allow_none=True)
201 201 def _user_ns_changed(self, name, old, new):
202 202 if self.shell is not None:
203 203 self.shell.user_ns = new
204 204 self.shell.init_user_ns()
205 205
206 206 def init_path(self):
207 207 """Add current working directory, '', to sys.path"""
208 208 if sys.path[0] != '':
209 209 sys.path.insert(0, '')
210 210
211 211 def init_shell(self):
212 212 raise NotImplementedError("Override in subclasses")
213 213
214 214 def init_gui_pylab(self):
215 215 """Enable GUI event loop integration, taking pylab into account."""
216 216 enable = False
217 217 shell = self.shell
218 218 if self.pylab:
219 219 enable = lambda key: shell.enable_pylab(key, import_all=self.pylab_import_all)
220 220 key = self.pylab
221 221 elif self.matplotlib:
222 222 enable = shell.enable_matplotlib
223 223 key = self.matplotlib
224 224 elif self.gui:
225 225 enable = shell.enable_gui
226 226 key = self.gui
227 227
228 228 if not enable:
229 229 return
230 230
231 231 try:
232 232 r = enable(key)
233 233 except ImportError:
234 234 self.log.warn("Eventloop or matplotlib integration failed. Is matplotlib installed?")
235 235 self.shell.showtraceback()
236 236 return
237 237 except Exception:
238 238 self.log.warn("GUI event loop or pylab initialization failed")
239 239 self.shell.showtraceback()
240 240 return
241 241
242 242 if isinstance(r, tuple):
243 243 gui, backend = r[:2]
244 244 self.log.info("Enabling GUI event loop integration, "
245 245 "eventloop=%s, matplotlib=%s", gui, backend)
246 246 if key == "auto":
247 247 print("Using matplotlib backend: %s" % backend)
248 248 else:
249 249 gui = r
250 250 self.log.info("Enabling GUI event loop integration, "
251 251 "eventloop=%s", gui)
252 252
253 253 def init_extensions(self):
254 254 """Load all IPython extensions in IPythonApp.extensions.
255 255
256 256 This uses the :meth:`ExtensionManager.load_extensions` to load all
257 257 the extensions listed in ``self.extensions``.
258 258 """
259 259 try:
260 260 self.log.debug("Loading IPython extensions...")
261 261 extensions = self.default_extensions + self.extensions
262 262 if self.extra_extension:
263 263 extensions.append(self.extra_extension)
264 264 for ext in extensions:
265 265 try:
266 266 self.log.info("Loading IPython extension: %s" % ext)
267 267 self.shell.extension_manager.load_extension(ext)
268 268 except:
269 269 if self.reraise_ipython_extension_failures:
270 270 raise
271 271 msg = ("Error in loading extension: {ext}\n"
272 272 "Check your config files in {location}".format(
273 273 ext=ext,
274 274 location=self.profile_dir.location
275 275 ))
276 276 self.log.warn(msg, exc_info=True)
277 277 except:
278 278 if self.reraise_ipython_extension_failures:
279 279 raise
280 280 self.log.warn("Unknown error in loading extensions:", exc_info=True)
281 281
282 282 def init_code(self):
283 283 """run the pre-flight code, specified via exec_lines"""
284 284 self._run_startup_files()
285 285 self._run_exec_lines()
286 286 self._run_exec_files()
287 287
288 288 # Hide variables defined here from %who etc.
289 289 if self.hide_initial_ns:
290 290 self.shell.user_ns_hidden.update(self.shell.user_ns)
291 291
292 292 # command-line execution (ipython -i script.py, ipython -m module)
293 293 # should *not* be excluded from %whos
294 294 self._run_cmd_line_code()
295 295 self._run_module()
296 296
297 297 # flush output, so itwon't be attached to the first cell
298 298 sys.stdout.flush()
299 299 sys.stderr.flush()
300 300
301 301 def _run_exec_lines(self):
302 302 """Run lines of code in IPythonApp.exec_lines in the user's namespace."""
303 303 if not self.exec_lines:
304 304 return
305 305 try:
306 306 self.log.debug("Running code from IPythonApp.exec_lines...")
307 307 for line in self.exec_lines:
308 308 try:
309 309 self.log.info("Running code in user namespace: %s" %
310 310 line)
311 311 self.shell.run_cell(line, store_history=False)
312 312 except:
313 313 self.log.warn("Error in executing line in user "
314 314 "namespace: %s" % line)
315 315 self.shell.showtraceback()
316 316 except:
317 317 self.log.warn("Unknown error in handling IPythonApp.exec_lines:")
318 318 self.shell.showtraceback()
319 319
320 320 def _exec_file(self, fname, shell_futures=False):
321 321 try:
322 322 full_filename = filefind(fname, [u'.', self.ipython_dir])
323 323 except IOError as e:
324 324 self.log.warn("File not found: %r"%fname)
325 325 return
326 326 # Make sure that the running script gets a proper sys.argv as if it
327 327 # were run from a system shell.
328 328 save_argv = sys.argv
329 329 sys.argv = [full_filename] + self.extra_args[1:]
330 330 # protect sys.argv from potential unicode strings on Python 2:
331 331 if not py3compat.PY3:
332 332 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
333 333 try:
334 334 if os.path.isfile(full_filename):
335 335 self.log.info("Running file in user namespace: %s" %
336 336 full_filename)
337 337 # Ensure that __file__ is always defined to match Python
338 338 # behavior.
339 339 with preserve_keys(self.shell.user_ns, '__file__'):
340 340 self.shell.user_ns['__file__'] = fname
341 341 if full_filename.endswith('.ipy'):
342 342 self.shell.safe_execfile_ipy(full_filename,
343 343 shell_futures=shell_futures)
344 344 else:
345 345 # default to python, even without extension
346 346 self.shell.safe_execfile(full_filename,
347 347 self.shell.user_ns,
348 shell_futures=shell_futures)
348 shell_futures=shell_futures,
349 raise_exceptions=True)
349 350 finally:
350 351 sys.argv = save_argv
351 352
352 353 def _run_startup_files(self):
353 354 """Run files from profile startup directory"""
354 355 startup_dir = self.profile_dir.startup_dir
355 356 startup_files = []
356 357
357 358 if self.exec_PYTHONSTARTUP and os.environ.get('PYTHONSTARTUP', False) and \
358 359 not (self.file_to_run or self.code_to_run or self.module_to_run):
359 360 python_startup = os.environ['PYTHONSTARTUP']
360 361 self.log.debug("Running PYTHONSTARTUP file %s...", python_startup)
361 362 try:
362 363 self._exec_file(python_startup)
363 364 except:
364 365 self.log.warn("Unknown error in handling PYTHONSTARTUP file %s:", python_startup)
365 366 self.shell.showtraceback()
366 367 finally:
367 368 # Many PYTHONSTARTUP files set up the readline completions,
368 369 # but this is often at odds with IPython's own completions.
369 370 # Do not allow PYTHONSTARTUP to set up readline.
370 371 if self.shell.has_readline:
371 372 self.shell.set_readline_completer()
372 373
373 374 startup_files += glob.glob(os.path.join(startup_dir, '*.py'))
374 375 startup_files += glob.glob(os.path.join(startup_dir, '*.ipy'))
375 376 if not startup_files:
376 377 return
377 378
378 379 self.log.debug("Running startup files from %s...", startup_dir)
379 380 try:
380 381 for fname in sorted(startup_files):
381 382 self._exec_file(fname)
382 383 except:
383 384 self.log.warn("Unknown error in handling startup files:")
384 385 self.shell.showtraceback()
385 386
386 387 def _run_exec_files(self):
387 388 """Run files from IPythonApp.exec_files"""
388 389 if not self.exec_files:
389 390 return
390 391
391 392 self.log.debug("Running files in IPythonApp.exec_files...")
392 393 try:
393 394 for fname in self.exec_files:
394 395 self._exec_file(fname)
395 396 except:
396 397 self.log.warn("Unknown error in handling IPythonApp.exec_files:")
397 398 self.shell.showtraceback()
398 399
399 400 def _run_cmd_line_code(self):
400 401 """Run code or file specified at the command-line"""
401 402 if self.code_to_run:
402 403 line = self.code_to_run
403 404 try:
404 405 self.log.info("Running code given at command line (c=): %s" %
405 406 line)
406 407 self.shell.run_cell(line, store_history=False)
407 408 except:
408 409 self.log.warn("Error in executing line in user namespace: %s" %
409 410 line)
410 411 self.shell.showtraceback()
411 412
412 413 # Like Python itself, ignore the second if the first of these is present
413 414 elif self.file_to_run:
414 415 fname = self.file_to_run
415 416 try:
416 417 self._exec_file(fname, shell_futures=True)
417 418 except:
418 self.log.warn("Error in executing file in user namespace: %s" %
419 fname)
420 self.shell.showtraceback()
419 self.shell.showtraceback(tb_offset=4)
420 self.exit(1)
421 421
422 422 def _run_module(self):
423 423 """Run module specified at the command-line."""
424 424 if self.module_to_run:
425 425 # Make sure that the module gets a proper sys.argv as if it were
426 426 # run using `python -m`.
427 427 save_argv = sys.argv
428 428 sys.argv = [sys.executable] + self.extra_args
429 429 try:
430 430 self.shell.safe_run_module(self.module_to_run,
431 431 self.shell.user_ns)
432 432 finally:
433 433 sys.argv = save_argv
General Comments 0
You need to be logged in to leave comments. Login now