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