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