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