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