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