##// END OF EJS Templates
Merge pull request #4016 from takluyver/IPython-start-funcs...
Min RK -
r12189:d3e2f732 merge
parent child Browse files
Show More
@@ -0,0 +1,17 b''
1 import nose.tools as nt
2
3 from .test_embed_kernel import setup, teardown, setup_kernel
4
5 TIMEOUT = 15
6
7 def test_ipython_start_kernel_userns():
8 cmd = ('from IPython import start_kernel\n'
9 'ns = {"tre": 123}\n'
10 'start_kernel(user_ns=ns)')
11
12 with setup_kernel(cmd) as client:
13 msg_id = client.object_info('tre')
14 msg = client.get_shell_msg(block=True, timeout=TIMEOUT)
15 content = msg['content']
16 assert content['found']
17 nt.assert_equal(content['string_form'], u'123') No newline at end of file
@@ -1,400 +1,406 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 Authors
6 Authors
7 -------
7 -------
8
8
9 * Min Ragan-Kelley
9 * Min Ragan-Kelley
10 """
10 """
11
11
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Copyright (C) 2008-2011 The IPython Development Team
13 # Copyright (C) 2008-2011 The IPython Development Team
14 #
14 #
15 # Distributed under the terms of the BSD License. The full license is in
15 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
16 # the file COPYING, distributed as part of this software.
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Imports
20 # Imports
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 from __future__ import absolute_import
23 from __future__ import absolute_import
24
24
25 import glob
25 import glob
26 import os
26 import os
27 import sys
27 import sys
28
28
29 from IPython.config.application import boolean_flag
29 from IPython.config.application import boolean_flag
30 from IPython.config.configurable import Configurable
30 from IPython.config.configurable import Configurable
31 from IPython.config.loader import Config
31 from IPython.config.loader import Config
32 from IPython.core import pylabtools
32 from IPython.core import pylabtools
33 from IPython.utils import py3compat
33 from IPython.utils import py3compat
34 from IPython.utils.contexts import preserve_keys
34 from IPython.utils.contexts import preserve_keys
35 from IPython.utils.path import filefind
35 from IPython.utils.path import filefind
36 from IPython.utils.traitlets import (
36 from IPython.utils.traitlets import (
37 Unicode, Instance, List, Bool, CaselessStrEnum
37 Unicode, Instance, List, Bool, CaselessStrEnum, Dict
38 )
38 )
39
39
40 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
41 # Aliases and Flags
41 # Aliases and Flags
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43
43
44 backend_keys = sorted(pylabtools.backends.keys())
44 backend_keys = sorted(pylabtools.backends.keys())
45 backend_keys.insert(0, 'auto')
45 backend_keys.insert(0, 'auto')
46
46
47 shell_flags = {}
47 shell_flags = {}
48
48
49 addflag = lambda *args: shell_flags.update(boolean_flag(*args))
49 addflag = lambda *args: shell_flags.update(boolean_flag(*args))
50 addflag('autoindent', 'InteractiveShell.autoindent',
50 addflag('autoindent', 'InteractiveShell.autoindent',
51 'Turn on autoindenting.', 'Turn off autoindenting.'
51 'Turn on autoindenting.', 'Turn off autoindenting.'
52 )
52 )
53 addflag('automagic', 'InteractiveShell.automagic',
53 addflag('automagic', 'InteractiveShell.automagic',
54 """Turn on the auto calling of magic commands. Type %%magic at the
54 """Turn on the auto calling of magic commands. Type %%magic at the
55 IPython prompt for more information.""",
55 IPython prompt for more information.""",
56 'Turn off the auto calling of magic commands.'
56 'Turn off the auto calling of magic commands.'
57 )
57 )
58 addflag('pdb', 'InteractiveShell.pdb',
58 addflag('pdb', 'InteractiveShell.pdb',
59 "Enable auto calling the pdb debugger after every exception.",
59 "Enable auto calling the pdb debugger after every exception.",
60 "Disable auto calling the pdb debugger after every exception."
60 "Disable auto calling the pdb debugger after every exception."
61 )
61 )
62 # pydb flag doesn't do any config, as core.debugger switches on import,
62 # pydb flag doesn't do any config, as core.debugger switches on import,
63 # which is before parsing. This just allows the flag to be passed.
63 # which is before parsing. This just allows the flag to be passed.
64 shell_flags.update(dict(
64 shell_flags.update(dict(
65 pydb = ({},
65 pydb = ({},
66 """Use the third party 'pydb' package as debugger, instead of pdb.
66 """Use the third party 'pydb' package as debugger, instead of pdb.
67 Requires that pydb is installed."""
67 Requires that pydb is installed."""
68 )
68 )
69 ))
69 ))
70 addflag('pprint', 'PlainTextFormatter.pprint',
70 addflag('pprint', 'PlainTextFormatter.pprint',
71 "Enable auto pretty printing of results.",
71 "Enable auto pretty printing of results.",
72 "Disable auto pretty printing of results."
72 "Disable auto pretty printing of results."
73 )
73 )
74 addflag('color-info', 'InteractiveShell.color_info',
74 addflag('color-info', 'InteractiveShell.color_info',
75 """IPython can display information about objects via a set of func-
75 """IPython can display information about objects via a set of func-
76 tions, and optionally can use colors for this, syntax highlighting
76 tions, and optionally can use colors for this, syntax highlighting
77 source code and various other elements. However, because this
77 source code and various other elements. However, because this
78 information is passed through a pager (like 'less') and many pagers get
78 information is passed through a pager (like 'less') and many pagers get
79 confused with color codes, this option is off by default. You can test
79 confused with color codes, this option is off by default. You can test
80 it and turn it on permanently in your ipython_config.py file if it
80 it and turn it on permanently in your ipython_config.py file if it
81 works for you. Test it and turn it on permanently if it works with
81 works for you. Test it and turn it on permanently if it works with
82 your system. The magic function %%color_info allows you to toggle this
82 your system. The magic function %%color_info allows you to toggle this
83 interactively for testing.""",
83 interactively for testing.""",
84 "Disable using colors for info related things."
84 "Disable using colors for info related things."
85 )
85 )
86 addflag('deep-reload', 'InteractiveShell.deep_reload',
86 addflag('deep-reload', 'InteractiveShell.deep_reload',
87 """Enable deep (recursive) reloading by default. IPython can use the
87 """Enable deep (recursive) reloading by default. IPython can use the
88 deep_reload module which reloads changes in modules recursively (it
88 deep_reload module which reloads changes in modules recursively (it
89 replaces the reload() function, so you don't need to change anything to
89 replaces the reload() function, so you don't need to change anything to
90 use it). deep_reload() forces a full reload of modules whose code may
90 use it). deep_reload() forces a full reload of modules whose code may
91 have changed, which the default reload() function does not. When
91 have changed, which the default reload() function does not. When
92 deep_reload is off, IPython will use the normal reload(), but
92 deep_reload is off, IPython will use the normal reload(), but
93 deep_reload will still be available as dreload(). This feature is off
93 deep_reload will still be available as dreload(). This feature is off
94 by default [which means that you have both normal reload() and
94 by default [which means that you have both normal reload() and
95 dreload()].""",
95 dreload()].""",
96 "Disable deep (recursive) reloading by default."
96 "Disable deep (recursive) reloading by default."
97 )
97 )
98 nosep_config = Config()
98 nosep_config = Config()
99 nosep_config.InteractiveShell.separate_in = ''
99 nosep_config.InteractiveShell.separate_in = ''
100 nosep_config.InteractiveShell.separate_out = ''
100 nosep_config.InteractiveShell.separate_out = ''
101 nosep_config.InteractiveShell.separate_out2 = ''
101 nosep_config.InteractiveShell.separate_out2 = ''
102
102
103 shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
103 shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
104 shell_flags['pylab'] = (
104 shell_flags['pylab'] = (
105 {'InteractiveShellApp' : {'pylab' : 'auto'}},
105 {'InteractiveShellApp' : {'pylab' : 'auto'}},
106 """Pre-load matplotlib and numpy for interactive use with
106 """Pre-load matplotlib and numpy for interactive use with
107 the default matplotlib backend."""
107 the default matplotlib backend."""
108 )
108 )
109 shell_flags['matplotlib'] = (
109 shell_flags['matplotlib'] = (
110 {'InteractiveShellApp' : {'matplotlib' : 'auto'}},
110 {'InteractiveShellApp' : {'matplotlib' : 'auto'}},
111 """Configure matplotlib for interactive use with
111 """Configure matplotlib for interactive use with
112 the default matplotlib backend."""
112 the default matplotlib backend."""
113 )
113 )
114
114
115 # it's possible we don't want short aliases for *all* of these:
115 # it's possible we don't want short aliases for *all* of these:
116 shell_aliases = dict(
116 shell_aliases = dict(
117 autocall='InteractiveShell.autocall',
117 autocall='InteractiveShell.autocall',
118 colors='InteractiveShell.colors',
118 colors='InteractiveShell.colors',
119 logfile='InteractiveShell.logfile',
119 logfile='InteractiveShell.logfile',
120 logappend='InteractiveShell.logappend',
120 logappend='InteractiveShell.logappend',
121 c='InteractiveShellApp.code_to_run',
121 c='InteractiveShellApp.code_to_run',
122 m='InteractiveShellApp.module_to_run',
122 m='InteractiveShellApp.module_to_run',
123 ext='InteractiveShellApp.extra_extension',
123 ext='InteractiveShellApp.extra_extension',
124 gui='InteractiveShellApp.gui',
124 gui='InteractiveShellApp.gui',
125 pylab='InteractiveShellApp.pylab',
125 pylab='InteractiveShellApp.pylab',
126 matplotlib='InteractiveShellApp.matplotlib',
126 matplotlib='InteractiveShellApp.matplotlib',
127 )
127 )
128 shell_aliases['cache-size'] = 'InteractiveShell.cache_size'
128 shell_aliases['cache-size'] = 'InteractiveShell.cache_size'
129
129
130 #-----------------------------------------------------------------------------
130 #-----------------------------------------------------------------------------
131 # Main classes and functions
131 # Main classes and functions
132 #-----------------------------------------------------------------------------
132 #-----------------------------------------------------------------------------
133
133
134 class InteractiveShellApp(Configurable):
134 class InteractiveShellApp(Configurable):
135 """A Mixin for applications that start InteractiveShell instances.
135 """A Mixin for applications that start InteractiveShell instances.
136
136
137 Provides configurables for loading extensions and executing files
137 Provides configurables for loading extensions and executing files
138 as part of configuring a Shell environment.
138 as part of configuring a Shell environment.
139
139
140 The following methods should be called by the :meth:`initialize` method
140 The following methods should be called by the :meth:`initialize` method
141 of the subclass:
141 of the subclass:
142
142
143 - :meth:`init_path`
143 - :meth:`init_path`
144 - :meth:`init_shell` (to be implemented by the subclass)
144 - :meth:`init_shell` (to be implemented by the subclass)
145 - :meth:`init_gui_pylab`
145 - :meth:`init_gui_pylab`
146 - :meth:`init_extensions`
146 - :meth:`init_extensions`
147 - :meth:`init_code`
147 - :meth:`init_code`
148 """
148 """
149 extensions = List(Unicode, config=True,
149 extensions = List(Unicode, config=True,
150 help="A list of dotted module names of IPython extensions to load."
150 help="A list of dotted module names of IPython extensions to load."
151 )
151 )
152 extra_extension = Unicode('', config=True,
152 extra_extension = Unicode('', config=True,
153 help="dotted module name of an IPython extension to load."
153 help="dotted module name of an IPython extension to load."
154 )
154 )
155 def _extra_extension_changed(self, name, old, new):
155 def _extra_extension_changed(self, name, old, new):
156 if new:
156 if new:
157 # add to self.extensions
157 # add to self.extensions
158 self.extensions.append(new)
158 self.extensions.append(new)
159
159
160 # Extensions that are always loaded (not configurable)
160 # Extensions that are always loaded (not configurable)
161 default_extensions = List(Unicode, [u'storemagic'], config=False)
161 default_extensions = List(Unicode, [u'storemagic'], config=False)
162
162
163 exec_files = List(Unicode, config=True,
163 exec_files = List(Unicode, config=True,
164 help="""List of files to run at IPython startup."""
164 help="""List of files to run at IPython startup."""
165 )
165 )
166 file_to_run = Unicode('', config=True,
166 file_to_run = Unicode('', config=True,
167 help="""A file to be run""")
167 help="""A file to be run""")
168
168
169 exec_lines = List(Unicode, config=True,
169 exec_lines = List(Unicode, config=True,
170 help="""lines of code to run at IPython startup."""
170 help="""lines of code to run at IPython startup."""
171 )
171 )
172 code_to_run = Unicode('', config=True,
172 code_to_run = Unicode('', config=True,
173 help="Execute the given command string."
173 help="Execute the given command string."
174 )
174 )
175 module_to_run = Unicode('', config=True,
175 module_to_run = Unicode('', config=True,
176 help="Run the module as a script."
176 help="Run the module as a script."
177 )
177 )
178 gui = CaselessStrEnum(('qt', 'wx', 'gtk', 'glut', 'pyglet', 'osx'), config=True,
178 gui = CaselessStrEnum(('qt', 'wx', 'gtk', 'glut', 'pyglet', 'osx'), config=True,
179 help="Enable GUI event loop integration ('qt', 'wx', 'gtk', 'glut', 'pyglet', 'osx')."
179 help="Enable GUI event loop integration ('qt', 'wx', 'gtk', 'glut', 'pyglet', 'osx')."
180 )
180 )
181 matplotlib = CaselessStrEnum(backend_keys,
181 matplotlib = CaselessStrEnum(backend_keys,
182 config=True,
182 config=True,
183 help="""Configure matplotlib for interactive use with
183 help="""Configure matplotlib for interactive use with
184 the default matplotlib backend."""
184 the default matplotlib backend."""
185 )
185 )
186 pylab = CaselessStrEnum(backend_keys,
186 pylab = CaselessStrEnum(backend_keys,
187 config=True,
187 config=True,
188 help="""Pre-load matplotlib and numpy for interactive use,
188 help="""Pre-load matplotlib and numpy for interactive use,
189 selecting a particular matplotlib backend and loop integration.
189 selecting a particular matplotlib backend and loop integration.
190 """
190 """
191 )
191 )
192 pylab_import_all = Bool(True, config=True,
192 pylab_import_all = Bool(True, config=True,
193 help="""If true, IPython will populate the user namespace with numpy, pylab, etc.
193 help="""If true, IPython will populate the user namespace with numpy, pylab, etc.
194 and an 'import *' is done from numpy and pylab, when using pylab mode.
194 and an 'import *' is done from numpy and pylab, when using pylab mode.
195
195
196 When False, pylab mode should not import any names into the user namespace.
196 When False, pylab mode should not import any names into the user namespace.
197 """
197 """
198 )
198 )
199 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
199 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
200
200
201 user_ns = Dict(default_value=None)
202 def _user_ns_changed(self, name, old, new):
203 if self.shell is not None:
204 self.shell.user_ns = new
205 self.shell.init_user_ns()
206
201 def init_path(self):
207 def init_path(self):
202 """Add current working directory, '', to sys.path"""
208 """Add current working directory, '', to sys.path"""
203 if sys.path[0] != '':
209 if sys.path[0] != '':
204 sys.path.insert(0, '')
210 sys.path.insert(0, '')
205
211
206 def init_shell(self):
212 def init_shell(self):
207 raise NotImplementedError("Override in subclasses")
213 raise NotImplementedError("Override in subclasses")
208
214
209 def init_gui_pylab(self):
215 def init_gui_pylab(self):
210 """Enable GUI event loop integration, taking pylab into account."""
216 """Enable GUI event loop integration, taking pylab into account."""
211 enable = False
217 enable = False
212 shell = self.shell
218 shell = self.shell
213 if self.pylab:
219 if self.pylab:
214 enable = shell.enable_pylab
220 enable = shell.enable_pylab
215 key = self.pylab
221 key = self.pylab
216 elif self.matplotlib:
222 elif self.matplotlib:
217 enable = shell.enable_matplotlib
223 enable = shell.enable_matplotlib
218 key = self.matplotlib
224 key = self.matplotlib
219 elif self.gui:
225 elif self.gui:
220 enable = shell.enable_gui
226 enable = shell.enable_gui
221 key = self.gui
227 key = self.gui
222
228
223 if not enable:
229 if not enable:
224 return
230 return
225
231
226 try:
232 try:
227 r = enable(key)
233 r = enable(key)
228 except ImportError:
234 except ImportError:
229 self.log.warn("Eventloop or matplotlib integration failed. Is matplotlib installed?")
235 self.log.warn("Eventloop or matplotlib integration failed. Is matplotlib installed?")
230 self.shell.showtraceback()
236 self.shell.showtraceback()
231 return
237 return
232 except Exception:
238 except Exception:
233 self.log.warn("GUI event loop or pylab initialization failed")
239 self.log.warn("GUI event loop or pylab initialization failed")
234 self.shell.showtraceback()
240 self.shell.showtraceback()
235 return
241 return
236
242
237 if isinstance(r, tuple):
243 if isinstance(r, tuple):
238 gui, backend = r[:2]
244 gui, backend = r[:2]
239 self.log.info("Enabling GUI event loop integration, "
245 self.log.info("Enabling GUI event loop integration, "
240 "eventloop=%s, matplotlib=%s", gui, backend)
246 "eventloop=%s, matplotlib=%s", gui, backend)
241 if key == "auto":
247 if key == "auto":
242 print ("Using matplotlib backend: %s" % backend)
248 print ("Using matplotlib backend: %s" % backend)
243 else:
249 else:
244 gui = r
250 gui = r
245 self.log.info("Enabling GUI event loop integration, "
251 self.log.info("Enabling GUI event loop integration, "
246 "eventloop=%s", gui)
252 "eventloop=%s", gui)
247
253
248 def init_extensions(self):
254 def init_extensions(self):
249 """Load all IPython extensions in IPythonApp.extensions.
255 """Load all IPython extensions in IPythonApp.extensions.
250
256
251 This uses the :meth:`ExtensionManager.load_extensions` to load all
257 This uses the :meth:`ExtensionManager.load_extensions` to load all
252 the extensions listed in ``self.extensions``.
258 the extensions listed in ``self.extensions``.
253 """
259 """
254 try:
260 try:
255 self.log.debug("Loading IPython extensions...")
261 self.log.debug("Loading IPython extensions...")
256 extensions = self.default_extensions + self.extensions
262 extensions = self.default_extensions + self.extensions
257 for ext in extensions:
263 for ext in extensions:
258 try:
264 try:
259 self.log.info("Loading IPython extension: %s" % ext)
265 self.log.info("Loading IPython extension: %s" % ext)
260 self.shell.extension_manager.load_extension(ext)
266 self.shell.extension_manager.load_extension(ext)
261 except:
267 except:
262 self.log.warn("Error in loading extension: %s" % ext +
268 self.log.warn("Error in loading extension: %s" % ext +
263 "\nCheck your config files in %s" % self.profile_dir.location
269 "\nCheck your config files in %s" % self.profile_dir.location
264 )
270 )
265 self.shell.showtraceback()
271 self.shell.showtraceback()
266 except:
272 except:
267 self.log.warn("Unknown error in loading extensions:")
273 self.log.warn("Unknown error in loading extensions:")
268 self.shell.showtraceback()
274 self.shell.showtraceback()
269
275
270 def init_code(self):
276 def init_code(self):
271 """run the pre-flight code, specified via exec_lines"""
277 """run the pre-flight code, specified via exec_lines"""
272 self._run_startup_files()
278 self._run_startup_files()
273 self._run_exec_lines()
279 self._run_exec_lines()
274 self._run_exec_files()
280 self._run_exec_files()
275 self._run_cmd_line_code()
281 self._run_cmd_line_code()
276 self._run_module()
282 self._run_module()
277
283
278 # flush output, so itwon't be attached to the first cell
284 # flush output, so itwon't be attached to the first cell
279 sys.stdout.flush()
285 sys.stdout.flush()
280 sys.stderr.flush()
286 sys.stderr.flush()
281
287
282 # Hide variables defined here from %who etc.
288 # Hide variables defined here from %who etc.
283 self.shell.user_ns_hidden.update(self.shell.user_ns)
289 self.shell.user_ns_hidden.update(self.shell.user_ns)
284
290
285 def _run_exec_lines(self):
291 def _run_exec_lines(self):
286 """Run lines of code in IPythonApp.exec_lines in the user's namespace."""
292 """Run lines of code in IPythonApp.exec_lines in the user's namespace."""
287 if not self.exec_lines:
293 if not self.exec_lines:
288 return
294 return
289 try:
295 try:
290 self.log.debug("Running code from IPythonApp.exec_lines...")
296 self.log.debug("Running code from IPythonApp.exec_lines...")
291 for line in self.exec_lines:
297 for line in self.exec_lines:
292 try:
298 try:
293 self.log.info("Running code in user namespace: %s" %
299 self.log.info("Running code in user namespace: %s" %
294 line)
300 line)
295 self.shell.run_cell(line, store_history=False)
301 self.shell.run_cell(line, store_history=False)
296 except:
302 except:
297 self.log.warn("Error in executing line in user "
303 self.log.warn("Error in executing line in user "
298 "namespace: %s" % line)
304 "namespace: %s" % line)
299 self.shell.showtraceback()
305 self.shell.showtraceback()
300 except:
306 except:
301 self.log.warn("Unknown error in handling IPythonApp.exec_lines:")
307 self.log.warn("Unknown error in handling IPythonApp.exec_lines:")
302 self.shell.showtraceback()
308 self.shell.showtraceback()
303
309
304 def _exec_file(self, fname):
310 def _exec_file(self, fname):
305 try:
311 try:
306 full_filename = filefind(fname, [u'.', self.ipython_dir])
312 full_filename = filefind(fname, [u'.', self.ipython_dir])
307 except IOError as e:
313 except IOError as e:
308 self.log.warn("File not found: %r"%fname)
314 self.log.warn("File not found: %r"%fname)
309 return
315 return
310 # Make sure that the running script gets a proper sys.argv as if it
316 # Make sure that the running script gets a proper sys.argv as if it
311 # were run from a system shell.
317 # were run from a system shell.
312 save_argv = sys.argv
318 save_argv = sys.argv
313 sys.argv = [full_filename] + self.extra_args[1:]
319 sys.argv = [full_filename] + self.extra_args[1:]
314 # protect sys.argv from potential unicode strings on Python 2:
320 # protect sys.argv from potential unicode strings on Python 2:
315 if not py3compat.PY3:
321 if not py3compat.PY3:
316 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
322 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
317 try:
323 try:
318 if os.path.isfile(full_filename):
324 if os.path.isfile(full_filename):
319 self.log.info("Running file in user namespace: %s" %
325 self.log.info("Running file in user namespace: %s" %
320 full_filename)
326 full_filename)
321 # Ensure that __file__ is always defined to match Python
327 # Ensure that __file__ is always defined to match Python
322 # behavior.
328 # behavior.
323 with preserve_keys(self.shell.user_ns, '__file__'):
329 with preserve_keys(self.shell.user_ns, '__file__'):
324 self.shell.user_ns['__file__'] = fname
330 self.shell.user_ns['__file__'] = fname
325 if full_filename.endswith('.ipy'):
331 if full_filename.endswith('.ipy'):
326 self.shell.safe_execfile_ipy(full_filename)
332 self.shell.safe_execfile_ipy(full_filename)
327 else:
333 else:
328 # default to python, even without extension
334 # default to python, even without extension
329 self.shell.safe_execfile(full_filename,
335 self.shell.safe_execfile(full_filename,
330 self.shell.user_ns)
336 self.shell.user_ns)
331 finally:
337 finally:
332 sys.argv = save_argv
338 sys.argv = save_argv
333
339
334 def _run_startup_files(self):
340 def _run_startup_files(self):
335 """Run files from profile startup directory"""
341 """Run files from profile startup directory"""
336 startup_dir = self.profile_dir.startup_dir
342 startup_dir = self.profile_dir.startup_dir
337 startup_files = []
343 startup_files = []
338 if os.environ.get('PYTHONSTARTUP', False):
344 if os.environ.get('PYTHONSTARTUP', False):
339 startup_files.append(os.environ['PYTHONSTARTUP'])
345 startup_files.append(os.environ['PYTHONSTARTUP'])
340 startup_files += glob.glob(os.path.join(startup_dir, '*.py'))
346 startup_files += glob.glob(os.path.join(startup_dir, '*.py'))
341 startup_files += glob.glob(os.path.join(startup_dir, '*.ipy'))
347 startup_files += glob.glob(os.path.join(startup_dir, '*.ipy'))
342 if not startup_files:
348 if not startup_files:
343 return
349 return
344
350
345 self.log.debug("Running startup files from %s...", startup_dir)
351 self.log.debug("Running startup files from %s...", startup_dir)
346 try:
352 try:
347 for fname in sorted(startup_files):
353 for fname in sorted(startup_files):
348 self._exec_file(fname)
354 self._exec_file(fname)
349 except:
355 except:
350 self.log.warn("Unknown error in handling startup files:")
356 self.log.warn("Unknown error in handling startup files:")
351 self.shell.showtraceback()
357 self.shell.showtraceback()
352
358
353 def _run_exec_files(self):
359 def _run_exec_files(self):
354 """Run files from IPythonApp.exec_files"""
360 """Run files from IPythonApp.exec_files"""
355 if not self.exec_files:
361 if not self.exec_files:
356 return
362 return
357
363
358 self.log.debug("Running files in IPythonApp.exec_files...")
364 self.log.debug("Running files in IPythonApp.exec_files...")
359 try:
365 try:
360 for fname in self.exec_files:
366 for fname in self.exec_files:
361 self._exec_file(fname)
367 self._exec_file(fname)
362 except:
368 except:
363 self.log.warn("Unknown error in handling IPythonApp.exec_files:")
369 self.log.warn("Unknown error in handling IPythonApp.exec_files:")
364 self.shell.showtraceback()
370 self.shell.showtraceback()
365
371
366 def _run_cmd_line_code(self):
372 def _run_cmd_line_code(self):
367 """Run code or file specified at the command-line"""
373 """Run code or file specified at the command-line"""
368 if self.code_to_run:
374 if self.code_to_run:
369 line = self.code_to_run
375 line = self.code_to_run
370 try:
376 try:
371 self.log.info("Running code given at command line (c=): %s" %
377 self.log.info("Running code given at command line (c=): %s" %
372 line)
378 line)
373 self.shell.run_cell(line, store_history=False)
379 self.shell.run_cell(line, store_history=False)
374 except:
380 except:
375 self.log.warn("Error in executing line in user namespace: %s" %
381 self.log.warn("Error in executing line in user namespace: %s" %
376 line)
382 line)
377 self.shell.showtraceback()
383 self.shell.showtraceback()
378
384
379 # Like Python itself, ignore the second if the first of these is present
385 # Like Python itself, ignore the second if the first of these is present
380 elif self.file_to_run:
386 elif self.file_to_run:
381 fname = self.file_to_run
387 fname = self.file_to_run
382 try:
388 try:
383 self._exec_file(fname)
389 self._exec_file(fname)
384 except:
390 except:
385 self.log.warn("Error in executing file in user namespace: %s" %
391 self.log.warn("Error in executing file in user namespace: %s" %
386 fname)
392 fname)
387 self.shell.showtraceback()
393 self.shell.showtraceback()
388
394
389 def _run_module(self):
395 def _run_module(self):
390 """Run module specified at the command-line."""
396 """Run module specified at the command-line."""
391 if self.module_to_run:
397 if self.module_to_run:
392 # Make sure that the module gets a proper sys.argv as if it were
398 # Make sure that the module gets a proper sys.argv as if it were
393 # run using `python -m`.
399 # run using `python -m`.
394 save_argv = sys.argv
400 save_argv = sys.argv
395 sys.argv = [sys.executable] + self.extra_args
401 sys.argv = [sys.executable] + self.extra_args
396 try:
402 try:
397 self.shell.safe_run_module(self.module_to_run,
403 self.shell.safe_run_module(self.module_to_run,
398 self.shell.user_ns)
404 self.shell.user_ns)
399 finally:
405 finally:
400 sys.argv = save_argv
406 sys.argv = save_argv
@@ -1,470 +1,472 b''
1 """An Application for launching a kernel
1 """An Application for launching a kernel
2
2
3 Authors
3 Authors
4 -------
4 -------
5 * MinRK
5 * MinRK
6 """
6 """
7 #-----------------------------------------------------------------------------
7 #-----------------------------------------------------------------------------
8 # Copyright (C) 2011 The IPython Development Team
8 # Copyright (C) 2011 The IPython Development Team
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING.txt, distributed as part of this software.
11 # the file COPYING.txt, distributed as part of this software.
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 from __future__ import print_function
18 from __future__ import print_function
19
19
20 # Standard library imports
20 # Standard library imports
21 import atexit
21 import atexit
22 import json
22 import json
23 import os
23 import os
24 import sys
24 import sys
25 import signal
25 import signal
26
26
27 # System library imports
27 # System library imports
28 import zmq
28 import zmq
29 from zmq.eventloop import ioloop
29 from zmq.eventloop import ioloop
30 from zmq.eventloop.zmqstream import ZMQStream
30 from zmq.eventloop.zmqstream import ZMQStream
31
31
32 # IPython imports
32 # IPython imports
33 from IPython.core.ultratb import FormattedTB
33 from IPython.core.ultratb import FormattedTB
34 from IPython.core.application import (
34 from IPython.core.application import (
35 BaseIPythonApplication, base_flags, base_aliases, catch_config_error
35 BaseIPythonApplication, base_flags, base_aliases, catch_config_error
36 )
36 )
37 from IPython.core.profiledir import ProfileDir
37 from IPython.core.profiledir import ProfileDir
38 from IPython.core.shellapp import (
38 from IPython.core.shellapp import (
39 InteractiveShellApp, shell_flags, shell_aliases
39 InteractiveShellApp, shell_flags, shell_aliases
40 )
40 )
41 from IPython.utils import io
41 from IPython.utils import io
42 from IPython.utils.localinterfaces import LOCALHOST
42 from IPython.utils.localinterfaces import LOCALHOST
43 from IPython.utils.path import filefind
43 from IPython.utils.path import filefind
44 from IPython.utils.py3compat import str_to_bytes
44 from IPython.utils.py3compat import str_to_bytes
45 from IPython.utils.traitlets import (
45 from IPython.utils.traitlets import (
46 Any, Instance, Dict, Unicode, Integer, Bool, CaselessStrEnum,
46 Any, Instance, Dict, Unicode, Integer, Bool, CaselessStrEnum,
47 DottedObjectName,
47 DottedObjectName,
48 )
48 )
49 from IPython.utils.importstring import import_item
49 from IPython.utils.importstring import import_item
50 from IPython.kernel import write_connection_file
50 from IPython.kernel import write_connection_file
51
51
52 # local imports
52 # local imports
53 from heartbeat import Heartbeat
53 from heartbeat import Heartbeat
54 from ipkernel import Kernel
54 from ipkernel import Kernel
55 from parentpoller import ParentPollerUnix, ParentPollerWindows
55 from parentpoller import ParentPollerUnix, ParentPollerWindows
56 from session import (
56 from session import (
57 Session, session_flags, session_aliases, default_secure,
57 Session, session_flags, session_aliases, default_secure,
58 )
58 )
59 from zmqshell import ZMQInteractiveShell
59 from zmqshell import ZMQInteractiveShell
60
60
61 #-----------------------------------------------------------------------------
61 #-----------------------------------------------------------------------------
62 # Flags and Aliases
62 # Flags and Aliases
63 #-----------------------------------------------------------------------------
63 #-----------------------------------------------------------------------------
64
64
65 kernel_aliases = dict(base_aliases)
65 kernel_aliases = dict(base_aliases)
66 kernel_aliases.update({
66 kernel_aliases.update({
67 'ip' : 'IPKernelApp.ip',
67 'ip' : 'IPKernelApp.ip',
68 'hb' : 'IPKernelApp.hb_port',
68 'hb' : 'IPKernelApp.hb_port',
69 'shell' : 'IPKernelApp.shell_port',
69 'shell' : 'IPKernelApp.shell_port',
70 'iopub' : 'IPKernelApp.iopub_port',
70 'iopub' : 'IPKernelApp.iopub_port',
71 'stdin' : 'IPKernelApp.stdin_port',
71 'stdin' : 'IPKernelApp.stdin_port',
72 'control' : 'IPKernelApp.control_port',
72 'control' : 'IPKernelApp.control_port',
73 'f' : 'IPKernelApp.connection_file',
73 'f' : 'IPKernelApp.connection_file',
74 'parent': 'IPKernelApp.parent_handle',
74 'parent': 'IPKernelApp.parent_handle',
75 'transport': 'IPKernelApp.transport',
75 'transport': 'IPKernelApp.transport',
76 })
76 })
77 if sys.platform.startswith('win'):
77 if sys.platform.startswith('win'):
78 kernel_aliases['interrupt'] = 'IPKernelApp.interrupt'
78 kernel_aliases['interrupt'] = 'IPKernelApp.interrupt'
79
79
80 kernel_flags = dict(base_flags)
80 kernel_flags = dict(base_flags)
81 kernel_flags.update({
81 kernel_flags.update({
82 'no-stdout' : (
82 'no-stdout' : (
83 {'IPKernelApp' : {'no_stdout' : True}},
83 {'IPKernelApp' : {'no_stdout' : True}},
84 "redirect stdout to the null device"),
84 "redirect stdout to the null device"),
85 'no-stderr' : (
85 'no-stderr' : (
86 {'IPKernelApp' : {'no_stderr' : True}},
86 {'IPKernelApp' : {'no_stderr' : True}},
87 "redirect stderr to the null device"),
87 "redirect stderr to the null device"),
88 'pylab' : (
88 'pylab' : (
89 {'IPKernelApp' : {'pylab' : 'auto'}},
89 {'IPKernelApp' : {'pylab' : 'auto'}},
90 """Pre-load matplotlib and numpy for interactive use with
90 """Pre-load matplotlib and numpy for interactive use with
91 the default matplotlib backend."""),
91 the default matplotlib backend."""),
92 })
92 })
93
93
94 # inherit flags&aliases for any IPython shell apps
94 # inherit flags&aliases for any IPython shell apps
95 kernel_aliases.update(shell_aliases)
95 kernel_aliases.update(shell_aliases)
96 kernel_flags.update(shell_flags)
96 kernel_flags.update(shell_flags)
97
97
98 # inherit flags&aliases for Sessions
98 # inherit flags&aliases for Sessions
99 kernel_aliases.update(session_aliases)
99 kernel_aliases.update(session_aliases)
100 kernel_flags.update(session_flags)
100 kernel_flags.update(session_flags)
101
101
102 _ctrl_c_message = """\
102 _ctrl_c_message = """\
103 NOTE: When using the `ipython kernel` entry point, Ctrl-C will not work.
103 NOTE: When using the `ipython kernel` entry point, Ctrl-C will not work.
104
104
105 To exit, you will have to explicitly quit this process, by either sending
105 To exit, you will have to explicitly quit this process, by either sending
106 "quit" from a client, or using Ctrl-\\ in UNIX-like environments.
106 "quit" from a client, or using Ctrl-\\ in UNIX-like environments.
107
107
108 To read more about this, see https://github.com/ipython/ipython/issues/2049
108 To read more about this, see https://github.com/ipython/ipython/issues/2049
109
109
110 """
110 """
111
111
112 #-----------------------------------------------------------------------------
112 #-----------------------------------------------------------------------------
113 # Application class for starting an IPython Kernel
113 # Application class for starting an IPython Kernel
114 #-----------------------------------------------------------------------------
114 #-----------------------------------------------------------------------------
115
115
116 class IPKernelApp(BaseIPythonApplication, InteractiveShellApp):
116 class IPKernelApp(BaseIPythonApplication, InteractiveShellApp):
117 name='ipkernel'
117 name='ipkernel'
118 aliases = Dict(kernel_aliases)
118 aliases = Dict(kernel_aliases)
119 flags = Dict(kernel_flags)
119 flags = Dict(kernel_flags)
120 classes = [Kernel, ZMQInteractiveShell, ProfileDir, Session]
120 classes = [Kernel, ZMQInteractiveShell, ProfileDir, Session]
121 # the kernel class, as an importstring
121 # the kernel class, as an importstring
122 kernel_class = DottedObjectName('IPython.kernel.zmq.ipkernel.Kernel', config=True,
122 kernel_class = DottedObjectName('IPython.kernel.zmq.ipkernel.Kernel', config=True,
123 help="""The Kernel subclass to be used.
123 help="""The Kernel subclass to be used.
124
124
125 This should allow easy re-use of the IPKernelApp entry point
125 This should allow easy re-use of the IPKernelApp entry point
126 to configure and launch kernels other than IPython's own.
126 to configure and launch kernels other than IPython's own.
127 """)
127 """)
128 kernel = Any()
128 kernel = Any()
129 poller = Any() # don't restrict this even though current pollers are all Threads
129 poller = Any() # don't restrict this even though current pollers are all Threads
130 heartbeat = Instance(Heartbeat)
130 heartbeat = Instance(Heartbeat)
131 session = Instance('IPython.kernel.zmq.session.Session')
131 session = Instance('IPython.kernel.zmq.session.Session')
132 ports = Dict()
132 ports = Dict()
133
133
134 # ipkernel doesn't get its own config file
134 # ipkernel doesn't get its own config file
135 def _config_file_name_default(self):
135 def _config_file_name_default(self):
136 return 'ipython_config.py'
136 return 'ipython_config.py'
137
137
138 # inherit config file name from parent:
138 # inherit config file name from parent:
139 parent_appname = Unicode(config=True)
139 parent_appname = Unicode(config=True)
140 def _parent_appname_changed(self, name, old, new):
140 def _parent_appname_changed(self, name, old, new):
141 if self.config_file_specified:
141 if self.config_file_specified:
142 # it was manually specified, ignore
142 # it was manually specified, ignore
143 return
143 return
144 self.config_file_name = new.replace('-','_') + u'_config.py'
144 self.config_file_name = new.replace('-','_') + u'_config.py'
145 # don't let this count as specifying the config file
145 # don't let this count as specifying the config file
146 self.config_file_specified.remove(self.config_file_name)
146 self.config_file_specified.remove(self.config_file_name)
147
147
148 # connection info:
148 # connection info:
149 transport = CaselessStrEnum(['tcp', 'ipc'], default_value='tcp', config=True)
149 transport = CaselessStrEnum(['tcp', 'ipc'], default_value='tcp', config=True)
150 ip = Unicode(config=True,
150 ip = Unicode(config=True,
151 help="Set the IP or interface on which the kernel will listen.")
151 help="Set the IP or interface on which the kernel will listen.")
152 def _ip_default(self):
152 def _ip_default(self):
153 if self.transport == 'ipc':
153 if self.transport == 'ipc':
154 if self.connection_file:
154 if self.connection_file:
155 return os.path.splitext(self.abs_connection_file)[0] + '-ipc'
155 return os.path.splitext(self.abs_connection_file)[0] + '-ipc'
156 else:
156 else:
157 return 'kernel-ipc'
157 return 'kernel-ipc'
158 else:
158 else:
159 return LOCALHOST
159 return LOCALHOST
160 hb_port = Integer(0, config=True, help="set the heartbeat port [default: random]")
160 hb_port = Integer(0, config=True, help="set the heartbeat port [default: random]")
161 shell_port = Integer(0, config=True, help="set the shell (ROUTER) port [default: random]")
161 shell_port = Integer(0, config=True, help="set the shell (ROUTER) port [default: random]")
162 iopub_port = Integer(0, config=True, help="set the iopub (PUB) port [default: random]")
162 iopub_port = Integer(0, config=True, help="set the iopub (PUB) port [default: random]")
163 stdin_port = Integer(0, config=True, help="set the stdin (ROUTER) port [default: random]")
163 stdin_port = Integer(0, config=True, help="set the stdin (ROUTER) port [default: random]")
164 control_port = Integer(0, config=True, help="set the control (ROUTER) port [default: random]")
164 control_port = Integer(0, config=True, help="set the control (ROUTER) port [default: random]")
165 connection_file = Unicode('', config=True,
165 connection_file = Unicode('', config=True,
166 help="""JSON file in which to store connection info [default: kernel-<pid>.json]
166 help="""JSON file in which to store connection info [default: kernel-<pid>.json]
167
167
168 This file will contain the IP, ports, and authentication key needed to connect
168 This file will contain the IP, ports, and authentication key needed to connect
169 clients to this kernel. By default, this file will be created in the security dir
169 clients to this kernel. By default, this file will be created in the security dir
170 of the current profile, but can be specified by absolute path.
170 of the current profile, but can be specified by absolute path.
171 """)
171 """)
172 @property
172 @property
173 def abs_connection_file(self):
173 def abs_connection_file(self):
174 if os.path.basename(self.connection_file) == self.connection_file:
174 if os.path.basename(self.connection_file) == self.connection_file:
175 return os.path.join(self.profile_dir.security_dir, self.connection_file)
175 return os.path.join(self.profile_dir.security_dir, self.connection_file)
176 else:
176 else:
177 return self.connection_file
177 return self.connection_file
178
178
179
179
180 # streams, etc.
180 # streams, etc.
181 no_stdout = Bool(False, config=True, help="redirect stdout to the null device")
181 no_stdout = Bool(False, config=True, help="redirect stdout to the null device")
182 no_stderr = Bool(False, config=True, help="redirect stderr to the null device")
182 no_stderr = Bool(False, config=True, help="redirect stderr to the null device")
183 outstream_class = DottedObjectName('IPython.kernel.zmq.iostream.OutStream',
183 outstream_class = DottedObjectName('IPython.kernel.zmq.iostream.OutStream',
184 config=True, help="The importstring for the OutStream factory")
184 config=True, help="The importstring for the OutStream factory")
185 displayhook_class = DottedObjectName('IPython.kernel.zmq.displayhook.ZMQDisplayHook',
185 displayhook_class = DottedObjectName('IPython.kernel.zmq.displayhook.ZMQDisplayHook',
186 config=True, help="The importstring for the DisplayHook factory")
186 config=True, help="The importstring for the DisplayHook factory")
187
187
188 # polling
188 # polling
189 parent_handle = Integer(0, config=True,
189 parent_handle = Integer(0, config=True,
190 help="""kill this process if its parent dies. On Windows, the argument
190 help="""kill this process if its parent dies. On Windows, the argument
191 specifies the HANDLE of the parent process, otherwise it is simply boolean.
191 specifies the HANDLE of the parent process, otherwise it is simply boolean.
192 """)
192 """)
193 interrupt = Integer(0, config=True,
193 interrupt = Integer(0, config=True,
194 help="""ONLY USED ON WINDOWS
194 help="""ONLY USED ON WINDOWS
195 Interrupt this process when the parent is signaled.
195 Interrupt this process when the parent is signaled.
196 """)
196 """)
197
197
198 def init_crash_handler(self):
198 def init_crash_handler(self):
199 # Install minimal exception handling
199 # Install minimal exception handling
200 sys.excepthook = FormattedTB(mode='Verbose', color_scheme='NoColor',
200 sys.excepthook = FormattedTB(mode='Verbose', color_scheme='NoColor',
201 ostream=sys.__stdout__)
201 ostream=sys.__stdout__)
202
202
203 def init_poller(self):
203 def init_poller(self):
204 if sys.platform == 'win32':
204 if sys.platform == 'win32':
205 if self.interrupt or self.parent_handle:
205 if self.interrupt or self.parent_handle:
206 self.poller = ParentPollerWindows(self.interrupt, self.parent_handle)
206 self.poller = ParentPollerWindows(self.interrupt, self.parent_handle)
207 elif self.parent_handle:
207 elif self.parent_handle:
208 self.poller = ParentPollerUnix()
208 self.poller = ParentPollerUnix()
209
209
210 def _bind_socket(self, s, port):
210 def _bind_socket(self, s, port):
211 iface = '%s://%s' % (self.transport, self.ip)
211 iface = '%s://%s' % (self.transport, self.ip)
212 if self.transport == 'tcp':
212 if self.transport == 'tcp':
213 if port <= 0:
213 if port <= 0:
214 port = s.bind_to_random_port(iface)
214 port = s.bind_to_random_port(iface)
215 else:
215 else:
216 s.bind("tcp://%s:%i" % (self.ip, port))
216 s.bind("tcp://%s:%i" % (self.ip, port))
217 elif self.transport == 'ipc':
217 elif self.transport == 'ipc':
218 if port <= 0:
218 if port <= 0:
219 port = 1
219 port = 1
220 path = "%s-%i" % (self.ip, port)
220 path = "%s-%i" % (self.ip, port)
221 while os.path.exists(path):
221 while os.path.exists(path):
222 port = port + 1
222 port = port + 1
223 path = "%s-%i" % (self.ip, port)
223 path = "%s-%i" % (self.ip, port)
224 else:
224 else:
225 path = "%s-%i" % (self.ip, port)
225 path = "%s-%i" % (self.ip, port)
226 s.bind("ipc://%s" % path)
226 s.bind("ipc://%s" % path)
227 return port
227 return port
228
228
229 def load_connection_file(self):
229 def load_connection_file(self):
230 """load ip/port/hmac config from JSON connection file"""
230 """load ip/port/hmac config from JSON connection file"""
231 try:
231 try:
232 fname = filefind(self.connection_file, ['.', self.profile_dir.security_dir])
232 fname = filefind(self.connection_file, ['.', self.profile_dir.security_dir])
233 except IOError:
233 except IOError:
234 self.log.debug("Connection file not found: %s", self.connection_file)
234 self.log.debug("Connection file not found: %s", self.connection_file)
235 # This means I own it, so I will clean it up:
235 # This means I own it, so I will clean it up:
236 atexit.register(self.cleanup_connection_file)
236 atexit.register(self.cleanup_connection_file)
237 return
237 return
238 self.log.debug(u"Loading connection file %s", fname)
238 self.log.debug(u"Loading connection file %s", fname)
239 with open(fname) as f:
239 with open(fname) as f:
240 s = f.read()
240 s = f.read()
241 cfg = json.loads(s)
241 cfg = json.loads(s)
242 self.transport = cfg.get('transport', self.transport)
242 self.transport = cfg.get('transport', self.transport)
243 if self.ip == self._ip_default() and 'ip' in cfg:
243 if self.ip == self._ip_default() and 'ip' in cfg:
244 # not overridden by config or cl_args
244 # not overridden by config or cl_args
245 self.ip = cfg['ip']
245 self.ip = cfg['ip']
246 for channel in ('hb', 'shell', 'iopub', 'stdin', 'control'):
246 for channel in ('hb', 'shell', 'iopub', 'stdin', 'control'):
247 name = channel + '_port'
247 name = channel + '_port'
248 if getattr(self, name) == 0 and name in cfg:
248 if getattr(self, name) == 0 and name in cfg:
249 # not overridden by config or cl_args
249 # not overridden by config or cl_args
250 setattr(self, name, cfg[name])
250 setattr(self, name, cfg[name])
251 if 'key' in cfg:
251 if 'key' in cfg:
252 self.config.Session.key = str_to_bytes(cfg['key'])
252 self.config.Session.key = str_to_bytes(cfg['key'])
253
253
254 def write_connection_file(self):
254 def write_connection_file(self):
255 """write connection info to JSON file"""
255 """write connection info to JSON file"""
256 cf = self.abs_connection_file
256 cf = self.abs_connection_file
257 self.log.debug("Writing connection file: %s", cf)
257 self.log.debug("Writing connection file: %s", cf)
258 write_connection_file(cf, ip=self.ip, key=self.session.key, transport=self.transport,
258 write_connection_file(cf, ip=self.ip, key=self.session.key, transport=self.transport,
259 shell_port=self.shell_port, stdin_port=self.stdin_port, hb_port=self.hb_port,
259 shell_port=self.shell_port, stdin_port=self.stdin_port, hb_port=self.hb_port,
260 iopub_port=self.iopub_port, control_port=self.control_port)
260 iopub_port=self.iopub_port, control_port=self.control_port)
261
261
262 def cleanup_connection_file(self):
262 def cleanup_connection_file(self):
263 cf = self.abs_connection_file
263 cf = self.abs_connection_file
264 self.log.debug("Cleaning up connection file: %s", cf)
264 self.log.debug("Cleaning up connection file: %s", cf)
265 try:
265 try:
266 os.remove(cf)
266 os.remove(cf)
267 except (IOError, OSError):
267 except (IOError, OSError):
268 pass
268 pass
269
269
270 self.cleanup_ipc_files()
270 self.cleanup_ipc_files()
271
271
272 def cleanup_ipc_files(self):
272 def cleanup_ipc_files(self):
273 """cleanup ipc files if we wrote them"""
273 """cleanup ipc files if we wrote them"""
274 if self.transport != 'ipc':
274 if self.transport != 'ipc':
275 return
275 return
276 for port in (self.shell_port, self.iopub_port, self.stdin_port, self.hb_port, self.control_port):
276 for port in (self.shell_port, self.iopub_port, self.stdin_port, self.hb_port, self.control_port):
277 ipcfile = "%s-%i" % (self.ip, port)
277 ipcfile = "%s-%i" % (self.ip, port)
278 try:
278 try:
279 os.remove(ipcfile)
279 os.remove(ipcfile)
280 except (IOError, OSError):
280 except (IOError, OSError):
281 pass
281 pass
282
282
283 def init_connection_file(self):
283 def init_connection_file(self):
284 if not self.connection_file:
284 if not self.connection_file:
285 self.connection_file = "kernel-%s.json"%os.getpid()
285 self.connection_file = "kernel-%s.json"%os.getpid()
286 try:
286 try:
287 self.load_connection_file()
287 self.load_connection_file()
288 except Exception:
288 except Exception:
289 self.log.error("Failed to load connection file: %r", self.connection_file, exc_info=True)
289 self.log.error("Failed to load connection file: %r", self.connection_file, exc_info=True)
290 self.exit(1)
290 self.exit(1)
291
291
292 def init_sockets(self):
292 def init_sockets(self):
293 # Create a context, a session, and the kernel sockets.
293 # Create a context, a session, and the kernel sockets.
294 self.log.info("Starting the kernel at pid: %i", os.getpid())
294 self.log.info("Starting the kernel at pid: %i", os.getpid())
295 context = zmq.Context.instance()
295 context = zmq.Context.instance()
296 # Uncomment this to try closing the context.
296 # Uncomment this to try closing the context.
297 # atexit.register(context.term)
297 # atexit.register(context.term)
298
298
299 self.shell_socket = context.socket(zmq.ROUTER)
299 self.shell_socket = context.socket(zmq.ROUTER)
300 self.shell_port = self._bind_socket(self.shell_socket, self.shell_port)
300 self.shell_port = self._bind_socket(self.shell_socket, self.shell_port)
301 self.log.debug("shell ROUTER Channel on port: %i" % self.shell_port)
301 self.log.debug("shell ROUTER Channel on port: %i" % self.shell_port)
302
302
303 self.iopub_socket = context.socket(zmq.PUB)
303 self.iopub_socket = context.socket(zmq.PUB)
304 self.iopub_port = self._bind_socket(self.iopub_socket, self.iopub_port)
304 self.iopub_port = self._bind_socket(self.iopub_socket, self.iopub_port)
305 self.log.debug("iopub PUB Channel on port: %i" % self.iopub_port)
305 self.log.debug("iopub PUB Channel on port: %i" % self.iopub_port)
306
306
307 self.stdin_socket = context.socket(zmq.ROUTER)
307 self.stdin_socket = context.socket(zmq.ROUTER)
308 self.stdin_port = self._bind_socket(self.stdin_socket, self.stdin_port)
308 self.stdin_port = self._bind_socket(self.stdin_socket, self.stdin_port)
309 self.log.debug("stdin ROUTER Channel on port: %i" % self.stdin_port)
309 self.log.debug("stdin ROUTER Channel on port: %i" % self.stdin_port)
310
310
311 self.control_socket = context.socket(zmq.ROUTER)
311 self.control_socket = context.socket(zmq.ROUTER)
312 self.control_port = self._bind_socket(self.control_socket, self.control_port)
312 self.control_port = self._bind_socket(self.control_socket, self.control_port)
313 self.log.debug("control ROUTER Channel on port: %i" % self.control_port)
313 self.log.debug("control ROUTER Channel on port: %i" % self.control_port)
314
314
315 def init_heartbeat(self):
315 def init_heartbeat(self):
316 """start the heart beating"""
316 """start the heart beating"""
317 # heartbeat doesn't share context, because it mustn't be blocked
317 # heartbeat doesn't share context, because it mustn't be blocked
318 # by the GIL, which is accessed by libzmq when freeing zero-copy messages
318 # by the GIL, which is accessed by libzmq when freeing zero-copy messages
319 hb_ctx = zmq.Context()
319 hb_ctx = zmq.Context()
320 self.heartbeat = Heartbeat(hb_ctx, (self.transport, self.ip, self.hb_port))
320 self.heartbeat = Heartbeat(hb_ctx, (self.transport, self.ip, self.hb_port))
321 self.hb_port = self.heartbeat.port
321 self.hb_port = self.heartbeat.port
322 self.log.debug("Heartbeat REP Channel on port: %i" % self.hb_port)
322 self.log.debug("Heartbeat REP Channel on port: %i" % self.hb_port)
323 self.heartbeat.start()
323 self.heartbeat.start()
324
324
325 def log_connection_info(self):
325 def log_connection_info(self):
326 """display connection info, and store ports"""
326 """display connection info, and store ports"""
327 basename = os.path.basename(self.connection_file)
327 basename = os.path.basename(self.connection_file)
328 if basename == self.connection_file or \
328 if basename == self.connection_file or \
329 os.path.dirname(self.connection_file) == self.profile_dir.security_dir:
329 os.path.dirname(self.connection_file) == self.profile_dir.security_dir:
330 # use shortname
330 # use shortname
331 tail = basename
331 tail = basename
332 if self.profile != 'default':
332 if self.profile != 'default':
333 tail += " --profile %s" % self.profile
333 tail += " --profile %s" % self.profile
334 else:
334 else:
335 tail = self.connection_file
335 tail = self.connection_file
336 lines = [
336 lines = [
337 "To connect another client to this kernel, use:",
337 "To connect another client to this kernel, use:",
338 " --existing %s" % tail,
338 " --existing %s" % tail,
339 ]
339 ]
340 # log connection info
340 # log connection info
341 # info-level, so often not shown.
341 # info-level, so often not shown.
342 # frontends should use the %connect_info magic
342 # frontends should use the %connect_info magic
343 # to see the connection info
343 # to see the connection info
344 for line in lines:
344 for line in lines:
345 self.log.info(line)
345 self.log.info(line)
346 # also raw print to the terminal if no parent_handle (`ipython kernel`)
346 # also raw print to the terminal if no parent_handle (`ipython kernel`)
347 if not self.parent_handle:
347 if not self.parent_handle:
348 io.rprint(_ctrl_c_message)
348 io.rprint(_ctrl_c_message)
349 for line in lines:
349 for line in lines:
350 io.rprint(line)
350 io.rprint(line)
351
351
352 self.ports = dict(shell=self.shell_port, iopub=self.iopub_port,
352 self.ports = dict(shell=self.shell_port, iopub=self.iopub_port,
353 stdin=self.stdin_port, hb=self.hb_port,
353 stdin=self.stdin_port, hb=self.hb_port,
354 control=self.control_port)
354 control=self.control_port)
355
355
356 def init_session(self):
356 def init_session(self):
357 """create our session object"""
357 """create our session object"""
358 default_secure(self.config)
358 default_secure(self.config)
359 self.session = Session(parent=self, username=u'kernel')
359 self.session = Session(parent=self, username=u'kernel')
360
360
361 def init_blackhole(self):
361 def init_blackhole(self):
362 """redirects stdout/stderr to devnull if necessary"""
362 """redirects stdout/stderr to devnull if necessary"""
363 if self.no_stdout or self.no_stderr:
363 if self.no_stdout or self.no_stderr:
364 blackhole = open(os.devnull, 'w')
364 blackhole = open(os.devnull, 'w')
365 if self.no_stdout:
365 if self.no_stdout:
366 sys.stdout = sys.__stdout__ = blackhole
366 sys.stdout = sys.__stdout__ = blackhole
367 if self.no_stderr:
367 if self.no_stderr:
368 sys.stderr = sys.__stderr__ = blackhole
368 sys.stderr = sys.__stderr__ = blackhole
369
369
370 def init_io(self):
370 def init_io(self):
371 """Redirect input streams and set a display hook."""
371 """Redirect input streams and set a display hook."""
372 if self.outstream_class:
372 if self.outstream_class:
373 outstream_factory = import_item(str(self.outstream_class))
373 outstream_factory = import_item(str(self.outstream_class))
374 sys.stdout = outstream_factory(self.session, self.iopub_socket, u'stdout')
374 sys.stdout = outstream_factory(self.session, self.iopub_socket, u'stdout')
375 sys.stderr = outstream_factory(self.session, self.iopub_socket, u'stderr')
375 sys.stderr = outstream_factory(self.session, self.iopub_socket, u'stderr')
376 if self.displayhook_class:
376 if self.displayhook_class:
377 displayhook_factory = import_item(str(self.displayhook_class))
377 displayhook_factory = import_item(str(self.displayhook_class))
378 sys.displayhook = displayhook_factory(self.session, self.iopub_socket)
378 sys.displayhook = displayhook_factory(self.session, self.iopub_socket)
379
379
380 def init_signal(self):
380 def init_signal(self):
381 signal.signal(signal.SIGINT, signal.SIG_IGN)
381 signal.signal(signal.SIGINT, signal.SIG_IGN)
382
382
383 def init_kernel(self):
383 def init_kernel(self):
384 """Create the Kernel object itself"""
384 """Create the Kernel object itself"""
385 shell_stream = ZMQStream(self.shell_socket)
385 shell_stream = ZMQStream(self.shell_socket)
386 control_stream = ZMQStream(self.control_socket)
386 control_stream = ZMQStream(self.control_socket)
387
387
388 kernel_factory = import_item(str(self.kernel_class))
388 kernel_factory = import_item(str(self.kernel_class))
389
389
390 kernel = kernel_factory(parent=self, session=self.session,
390 kernel = kernel_factory(parent=self, session=self.session,
391 shell_streams=[shell_stream, control_stream],
391 shell_streams=[shell_stream, control_stream],
392 iopub_socket=self.iopub_socket,
392 iopub_socket=self.iopub_socket,
393 stdin_socket=self.stdin_socket,
393 stdin_socket=self.stdin_socket,
394 log=self.log,
394 log=self.log,
395 profile_dir=self.profile_dir,
395 profile_dir=self.profile_dir,
396 user_ns=self.user_ns,
396 )
397 )
397 kernel.record_ports(self.ports)
398 kernel.record_ports(self.ports)
398 self.kernel = kernel
399 self.kernel = kernel
399
400
400 def init_gui_pylab(self):
401 def init_gui_pylab(self):
401 """Enable GUI event loop integration, taking pylab into account."""
402 """Enable GUI event loop integration, taking pylab into account."""
402
403
403 # Provide a wrapper for :meth:`InteractiveShellApp.init_gui_pylab`
404 # Provide a wrapper for :meth:`InteractiveShellApp.init_gui_pylab`
404 # to ensure that any exception is printed straight to stderr.
405 # to ensure that any exception is printed straight to stderr.
405 # Normally _showtraceback associates the reply with an execution,
406 # Normally _showtraceback associates the reply with an execution,
406 # which means frontends will never draw it, as this exception
407 # which means frontends will never draw it, as this exception
407 # is not associated with any execute request.
408 # is not associated with any execute request.
408
409
409 shell = self.shell
410 shell = self.shell
410 _showtraceback = shell._showtraceback
411 _showtraceback = shell._showtraceback
411 try:
412 try:
412 # replace pyerr-sending traceback with stderr
413 # replace pyerr-sending traceback with stderr
413 def print_tb(etype, evalue, stb):
414 def print_tb(etype, evalue, stb):
414 print ("GUI event loop or pylab initialization failed",
415 print ("GUI event loop or pylab initialization failed",
415 file=io.stderr)
416 file=io.stderr)
416 print (shell.InteractiveTB.stb2text(stb), file=io.stderr)
417 print (shell.InteractiveTB.stb2text(stb), file=io.stderr)
417 shell._showtraceback = print_tb
418 shell._showtraceback = print_tb
418 InteractiveShellApp.init_gui_pylab(self)
419 InteractiveShellApp.init_gui_pylab(self)
419 finally:
420 finally:
420 shell._showtraceback = _showtraceback
421 shell._showtraceback = _showtraceback
421
422
422 def init_shell(self):
423 def init_shell(self):
423 self.shell = self.kernel.shell
424 self.shell = self.kernel.shell
424 self.shell.configurables.append(self)
425 self.shell.configurables.append(self)
425
426
426 @catch_config_error
427 @catch_config_error
427 def initialize(self, argv=None):
428 def initialize(self, argv=None):
428 super(IPKernelApp, self).initialize(argv)
429 super(IPKernelApp, self).initialize(argv)
429 self.init_blackhole()
430 self.init_blackhole()
430 self.init_connection_file()
431 self.init_connection_file()
431 self.init_session()
432 self.init_session()
432 self.init_poller()
433 self.init_poller()
433 self.init_sockets()
434 self.init_sockets()
434 self.init_heartbeat()
435 self.init_heartbeat()
435 # writing/displaying connection info must be *after* init_sockets/heartbeat
436 # writing/displaying connection info must be *after* init_sockets/heartbeat
436 self.log_connection_info()
437 self.log_connection_info()
437 self.write_connection_file()
438 self.write_connection_file()
438 self.init_io()
439 self.init_io()
439 self.init_signal()
440 self.init_signal()
440 self.init_kernel()
441 self.init_kernel()
441 # shell init steps
442 # shell init steps
442 self.init_path()
443 self.init_path()
443 self.init_shell()
444 self.init_shell()
444 self.init_gui_pylab()
445 self.init_gui_pylab()
445 self.init_extensions()
446 self.init_extensions()
446 self.init_code()
447 self.init_code()
447 # flush stdout/stderr, so that anything written to these streams during
448 # flush stdout/stderr, so that anything written to these streams during
448 # initialization do not get associated with the first execution request
449 # initialization do not get associated with the first execution request
449 sys.stdout.flush()
450 sys.stdout.flush()
450 sys.stderr.flush()
451 sys.stderr.flush()
451
452
452 def start(self):
453 def start(self):
453 if self.poller is not None:
454 if self.poller is not None:
454 self.poller.start()
455 self.poller.start()
455 self.kernel.start()
456 self.kernel.start()
456 try:
457 try:
457 ioloop.IOLoop.instance().start()
458 ioloop.IOLoop.instance().start()
458 except KeyboardInterrupt:
459 except KeyboardInterrupt:
459 pass
460 pass
460
461
462 launch_new_instance = IPKernelApp.launch_instance
461
463
462 def main():
464 def main():
463 """Run an IPKernel as an application"""
465 """Run an IPKernel as an application"""
464 app = IPKernelApp.instance()
466 app = IPKernelApp.instance()
465 app.initialize()
467 app.initialize()
466 app.start()
468 app.start()
467
469
468
470
469 if __name__ == '__main__':
471 if __name__ == '__main__':
470 main()
472 main()
@@ -1,386 +1,386 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 """
3 """
4 The :class:`~IPython.core.application.Application` object for the command
4 The :class:`~IPython.core.application.Application` object for the command
5 line :command:`ipython` program.
5 line :command:`ipython` program.
6
6
7 Authors
7 Authors
8 -------
8 -------
9
9
10 * Brian Granger
10 * Brian Granger
11 * Fernando Perez
11 * Fernando Perez
12 * Min Ragan-Kelley
12 * Min Ragan-Kelley
13 """
13 """
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Copyright (C) 2008-2011 The IPython Development Team
16 # Copyright (C) 2008-2011 The IPython Development Team
17 #
17 #
18 # Distributed under the terms of the BSD License. The full license is in
18 # Distributed under the terms of the BSD License. The full license is in
19 # the file COPYING, distributed as part of this software.
19 # the file COPYING, distributed as part of this software.
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21
21
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23 # Imports
23 # Imports
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25
25
26 from __future__ import absolute_import
26 from __future__ import absolute_import
27
27
28 import logging
28 import logging
29 import os
29 import os
30 import sys
30 import sys
31
31
32 from IPython.config.loader import (
32 from IPython.config.loader import (
33 Config, PyFileConfigLoader, ConfigFileNotFound
33 Config, PyFileConfigLoader, ConfigFileNotFound
34 )
34 )
35 from IPython.config.application import boolean_flag, catch_config_error
35 from IPython.config.application import boolean_flag, catch_config_error
36 from IPython.core import release
36 from IPython.core import release
37 from IPython.core import usage
37 from IPython.core import usage
38 from IPython.core.completer import IPCompleter
38 from IPython.core.completer import IPCompleter
39 from IPython.core.crashhandler import CrashHandler
39 from IPython.core.crashhandler import CrashHandler
40 from IPython.core.formatters import PlainTextFormatter
40 from IPython.core.formatters import PlainTextFormatter
41 from IPython.core.history import HistoryManager
41 from IPython.core.history import HistoryManager
42 from IPython.core.prompts import PromptManager
42 from IPython.core.prompts import PromptManager
43 from IPython.core.application import (
43 from IPython.core.application import (
44 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
44 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
45 )
45 )
46 from IPython.core.magics import ScriptMagics
46 from IPython.core.magics import ScriptMagics
47 from IPython.core.shellapp import (
47 from IPython.core.shellapp import (
48 InteractiveShellApp, shell_flags, shell_aliases
48 InteractiveShellApp, shell_flags, shell_aliases
49 )
49 )
50 from IPython.terminal.interactiveshell import TerminalInteractiveShell
50 from IPython.terminal.interactiveshell import TerminalInteractiveShell
51 from IPython.utils import warn
51 from IPython.utils import warn
52 from IPython.utils.path import get_ipython_dir, check_for_old_config
52 from IPython.utils.path import get_ipython_dir, check_for_old_config
53 from IPython.utils.traitlets import (
53 from IPython.utils.traitlets import (
54 Bool, List, Dict,
54 Bool, List, Dict,
55 )
55 )
56
56
57 #-----------------------------------------------------------------------------
57 #-----------------------------------------------------------------------------
58 # Globals, utilities and helpers
58 # Globals, utilities and helpers
59 #-----------------------------------------------------------------------------
59 #-----------------------------------------------------------------------------
60
60
61 _examples = """
61 _examples = """
62 ipython --matplotlib # enable matplotlib integration
62 ipython --matplotlib # enable matplotlib integration
63 ipython --matplotlib=qt # enable matplotlib integration with qt4 backend
63 ipython --matplotlib=qt # enable matplotlib integration with qt4 backend
64
64
65 ipython --log-level=DEBUG # set logging to DEBUG
65 ipython --log-level=DEBUG # set logging to DEBUG
66 ipython --profile=foo # start with profile foo
66 ipython --profile=foo # start with profile foo
67
67
68 ipython qtconsole # start the qtconsole GUI application
68 ipython qtconsole # start the qtconsole GUI application
69 ipython help qtconsole # show the help for the qtconsole subcmd
69 ipython help qtconsole # show the help for the qtconsole subcmd
70
70
71 ipython console # start the terminal-based console application
71 ipython console # start the terminal-based console application
72 ipython help console # show the help for the console subcmd
72 ipython help console # show the help for the console subcmd
73
73
74 ipython notebook # start the IPython notebook
74 ipython notebook # start the IPython notebook
75 ipython help notebook # show the help for the notebook subcmd
75 ipython help notebook # show the help for the notebook subcmd
76
76
77 ipython profile create foo # create profile foo w/ default config files
77 ipython profile create foo # create profile foo w/ default config files
78 ipython help profile # show the help for the profile subcmd
78 ipython help profile # show the help for the profile subcmd
79
79
80 ipython locate # print the path to the IPython directory
80 ipython locate # print the path to the IPython directory
81 ipython locate profile foo # print the path to the directory for profile `foo`
81 ipython locate profile foo # print the path to the directory for profile `foo`
82
82
83 ipython nbconvert # convert notebooks to/from other formats
83 ipython nbconvert # convert notebooks to/from other formats
84 """
84 """
85
85
86 #-----------------------------------------------------------------------------
86 #-----------------------------------------------------------------------------
87 # Crash handler for this application
87 # Crash handler for this application
88 #-----------------------------------------------------------------------------
88 #-----------------------------------------------------------------------------
89
89
90 class IPAppCrashHandler(CrashHandler):
90 class IPAppCrashHandler(CrashHandler):
91 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
91 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
92
92
93 def __init__(self, app):
93 def __init__(self, app):
94 contact_name = release.author
94 contact_name = release.author
95 contact_email = release.author_email
95 contact_email = release.author_email
96 bug_tracker = 'https://github.com/ipython/ipython/issues'
96 bug_tracker = 'https://github.com/ipython/ipython/issues'
97 super(IPAppCrashHandler,self).__init__(
97 super(IPAppCrashHandler,self).__init__(
98 app, contact_name, contact_email, bug_tracker
98 app, contact_name, contact_email, bug_tracker
99 )
99 )
100
100
101 def make_report(self,traceback):
101 def make_report(self,traceback):
102 """Return a string containing a crash report."""
102 """Return a string containing a crash report."""
103
103
104 sec_sep = self.section_sep
104 sec_sep = self.section_sep
105 # Start with parent report
105 # Start with parent report
106 report = [super(IPAppCrashHandler, self).make_report(traceback)]
106 report = [super(IPAppCrashHandler, self).make_report(traceback)]
107 # Add interactive-specific info we may have
107 # Add interactive-specific info we may have
108 rpt_add = report.append
108 rpt_add = report.append
109 try:
109 try:
110 rpt_add(sec_sep+"History of session input:")
110 rpt_add(sec_sep+"History of session input:")
111 for line in self.app.shell.user_ns['_ih']:
111 for line in self.app.shell.user_ns['_ih']:
112 rpt_add(line)
112 rpt_add(line)
113 rpt_add('\n*** Last line of input (may not be in above history):\n')
113 rpt_add('\n*** Last line of input (may not be in above history):\n')
114 rpt_add(self.app.shell._last_input_line+'\n')
114 rpt_add(self.app.shell._last_input_line+'\n')
115 except:
115 except:
116 pass
116 pass
117
117
118 return ''.join(report)
118 return ''.join(report)
119
119
120 #-----------------------------------------------------------------------------
120 #-----------------------------------------------------------------------------
121 # Aliases and Flags
121 # Aliases and Flags
122 #-----------------------------------------------------------------------------
122 #-----------------------------------------------------------------------------
123 flags = dict(base_flags)
123 flags = dict(base_flags)
124 flags.update(shell_flags)
124 flags.update(shell_flags)
125 frontend_flags = {}
125 frontend_flags = {}
126 addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
126 addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
127 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
127 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
128 'Turn on auto editing of files with syntax errors.',
128 'Turn on auto editing of files with syntax errors.',
129 'Turn off auto editing of files with syntax errors.'
129 'Turn off auto editing of files with syntax errors.'
130 )
130 )
131 addflag('banner', 'TerminalIPythonApp.display_banner',
131 addflag('banner', 'TerminalIPythonApp.display_banner',
132 "Display a banner upon starting IPython.",
132 "Display a banner upon starting IPython.",
133 "Don't display a banner upon starting IPython."
133 "Don't display a banner upon starting IPython."
134 )
134 )
135 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
135 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
136 """Set to confirm when you try to exit IPython with an EOF (Control-D
136 """Set to confirm when you try to exit IPython with an EOF (Control-D
137 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
137 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
138 you can force a direct exit without any confirmation.""",
138 you can force a direct exit without any confirmation.""",
139 "Don't prompt the user when exiting."
139 "Don't prompt the user when exiting."
140 )
140 )
141 addflag('term-title', 'TerminalInteractiveShell.term_title',
141 addflag('term-title', 'TerminalInteractiveShell.term_title',
142 "Enable auto setting the terminal title.",
142 "Enable auto setting the terminal title.",
143 "Disable auto setting the terminal title."
143 "Disable auto setting the terminal title."
144 )
144 )
145 classic_config = Config()
145 classic_config = Config()
146 classic_config.InteractiveShell.cache_size = 0
146 classic_config.InteractiveShell.cache_size = 0
147 classic_config.PlainTextFormatter.pprint = False
147 classic_config.PlainTextFormatter.pprint = False
148 classic_config.PromptManager.in_template = '>>> '
148 classic_config.PromptManager.in_template = '>>> '
149 classic_config.PromptManager.in2_template = '... '
149 classic_config.PromptManager.in2_template = '... '
150 classic_config.PromptManager.out_template = ''
150 classic_config.PromptManager.out_template = ''
151 classic_config.InteractiveShell.separate_in = ''
151 classic_config.InteractiveShell.separate_in = ''
152 classic_config.InteractiveShell.separate_out = ''
152 classic_config.InteractiveShell.separate_out = ''
153 classic_config.InteractiveShell.separate_out2 = ''
153 classic_config.InteractiveShell.separate_out2 = ''
154 classic_config.InteractiveShell.colors = 'NoColor'
154 classic_config.InteractiveShell.colors = 'NoColor'
155 classic_config.InteractiveShell.xmode = 'Plain'
155 classic_config.InteractiveShell.xmode = 'Plain'
156
156
157 frontend_flags['classic']=(
157 frontend_flags['classic']=(
158 classic_config,
158 classic_config,
159 "Gives IPython a similar feel to the classic Python prompt."
159 "Gives IPython a similar feel to the classic Python prompt."
160 )
160 )
161 # # log doesn't make so much sense this way anymore
161 # # log doesn't make so much sense this way anymore
162 # paa('--log','-l',
162 # paa('--log','-l',
163 # action='store_true', dest='InteractiveShell.logstart',
163 # action='store_true', dest='InteractiveShell.logstart',
164 # help="Start logging to the default log file (./ipython_log.py).")
164 # help="Start logging to the default log file (./ipython_log.py).")
165 #
165 #
166 # # quick is harder to implement
166 # # quick is harder to implement
167 frontend_flags['quick']=(
167 frontend_flags['quick']=(
168 {'TerminalIPythonApp' : {'quick' : True}},
168 {'TerminalIPythonApp' : {'quick' : True}},
169 "Enable quick startup with no config files."
169 "Enable quick startup with no config files."
170 )
170 )
171
171
172 frontend_flags['i'] = (
172 frontend_flags['i'] = (
173 {'TerminalIPythonApp' : {'force_interact' : True}},
173 {'TerminalIPythonApp' : {'force_interact' : True}},
174 """If running code from the command line, become interactive afterwards.
174 """If running code from the command line, become interactive afterwards.
175 Note: can also be given simply as '-i.'"""
175 Note: can also be given simply as '-i.'"""
176 )
176 )
177 flags.update(frontend_flags)
177 flags.update(frontend_flags)
178
178
179 aliases = dict(base_aliases)
179 aliases = dict(base_aliases)
180 aliases.update(shell_aliases)
180 aliases.update(shell_aliases)
181
181
182 #-----------------------------------------------------------------------------
182 #-----------------------------------------------------------------------------
183 # Main classes and functions
183 # Main classes and functions
184 #-----------------------------------------------------------------------------
184 #-----------------------------------------------------------------------------
185
185
186
186
187 class LocateIPythonApp(BaseIPythonApplication):
187 class LocateIPythonApp(BaseIPythonApplication):
188 description = """print the path to the IPython dir"""
188 description = """print the path to the IPython dir"""
189 subcommands = Dict(dict(
189 subcommands = Dict(dict(
190 profile=('IPython.core.profileapp.ProfileLocate',
190 profile=('IPython.core.profileapp.ProfileLocate',
191 "print the path to an IPython profile directory",
191 "print the path to an IPython profile directory",
192 ),
192 ),
193 ))
193 ))
194 def start(self):
194 def start(self):
195 if self.subapp is not None:
195 if self.subapp is not None:
196 return self.subapp.start()
196 return self.subapp.start()
197 else:
197 else:
198 print self.ipython_dir
198 print self.ipython_dir
199
199
200
200
201 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
201 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
202 name = u'ipython'
202 name = u'ipython'
203 description = usage.cl_usage
203 description = usage.cl_usage
204 crash_handler_class = IPAppCrashHandler
204 crash_handler_class = IPAppCrashHandler
205 examples = _examples
205 examples = _examples
206
206
207 flags = Dict(flags)
207 flags = Dict(flags)
208 aliases = Dict(aliases)
208 aliases = Dict(aliases)
209 classes = List()
209 classes = List()
210 def _classes_default(self):
210 def _classes_default(self):
211 """This has to be in a method, for TerminalIPythonApp to be available."""
211 """This has to be in a method, for TerminalIPythonApp to be available."""
212 return [
212 return [
213 InteractiveShellApp, # ShellApp comes before TerminalApp, because
213 InteractiveShellApp, # ShellApp comes before TerminalApp, because
214 self.__class__, # it will also affect subclasses (e.g. QtConsole)
214 self.__class__, # it will also affect subclasses (e.g. QtConsole)
215 TerminalInteractiveShell,
215 TerminalInteractiveShell,
216 PromptManager,
216 PromptManager,
217 HistoryManager,
217 HistoryManager,
218 ProfileDir,
218 ProfileDir,
219 PlainTextFormatter,
219 PlainTextFormatter,
220 IPCompleter,
220 IPCompleter,
221 ScriptMagics,
221 ScriptMagics,
222 ]
222 ]
223
223
224 subcommands = Dict(dict(
224 subcommands = Dict(dict(
225 qtconsole=('IPython.qt.console.qtconsoleapp.IPythonQtConsoleApp',
225 qtconsole=('IPython.qt.console.qtconsoleapp.IPythonQtConsoleApp',
226 """Launch the IPython Qt Console."""
226 """Launch the IPython Qt Console."""
227 ),
227 ),
228 notebook=('IPython.html.notebookapp.NotebookApp',
228 notebook=('IPython.html.notebookapp.NotebookApp',
229 """Launch the IPython HTML Notebook Server."""
229 """Launch the IPython HTML Notebook Server."""
230 ),
230 ),
231 profile = ("IPython.core.profileapp.ProfileApp",
231 profile = ("IPython.core.profileapp.ProfileApp",
232 "Create and manage IPython profiles."
232 "Create and manage IPython profiles."
233 ),
233 ),
234 kernel = ("IPython.kernel.zmq.kernelapp.IPKernelApp",
234 kernel = ("IPython.kernel.zmq.kernelapp.IPKernelApp",
235 "Start a kernel without an attached frontend."
235 "Start a kernel without an attached frontend."
236 ),
236 ),
237 console=('IPython.terminal.console.app.ZMQTerminalIPythonApp',
237 console=('IPython.terminal.console.app.ZMQTerminalIPythonApp',
238 """Launch the IPython terminal-based Console."""
238 """Launch the IPython terminal-based Console."""
239 ),
239 ),
240 locate=('IPython.terminal.ipapp.LocateIPythonApp',
240 locate=('IPython.terminal.ipapp.LocateIPythonApp',
241 LocateIPythonApp.description
241 LocateIPythonApp.description
242 ),
242 ),
243 history=('IPython.core.historyapp.HistoryApp',
243 history=('IPython.core.historyapp.HistoryApp',
244 "Manage the IPython history database."
244 "Manage the IPython history database."
245 ),
245 ),
246 nbconvert=('IPython.nbconvert.nbconvertapp.NbConvertApp',
246 nbconvert=('IPython.nbconvert.nbconvertapp.NbConvertApp',
247 "Convert notebooks to/from other formats."
247 "Convert notebooks to/from other formats."
248 ),
248 ),
249 ))
249 ))
250
250
251 # *do* autocreate requested profile, but don't create the config file.
251 # *do* autocreate requested profile, but don't create the config file.
252 auto_create=Bool(True)
252 auto_create=Bool(True)
253 # configurables
253 # configurables
254 ignore_old_config=Bool(False, config=True,
254 ignore_old_config=Bool(False, config=True,
255 help="Suppress warning messages about legacy config files"
255 help="Suppress warning messages about legacy config files"
256 )
256 )
257 quick = Bool(False, config=True,
257 quick = Bool(False, config=True,
258 help="""Start IPython quickly by skipping the loading of config files."""
258 help="""Start IPython quickly by skipping the loading of config files."""
259 )
259 )
260 def _quick_changed(self, name, old, new):
260 def _quick_changed(self, name, old, new):
261 if new:
261 if new:
262 self.load_config_file = lambda *a, **kw: None
262 self.load_config_file = lambda *a, **kw: None
263 self.ignore_old_config=True
263 self.ignore_old_config=True
264
264
265 display_banner = Bool(True, config=True,
265 display_banner = Bool(True, config=True,
266 help="Whether to display a banner upon starting IPython."
266 help="Whether to display a banner upon starting IPython."
267 )
267 )
268
268
269 # if there is code of files to run from the cmd line, don't interact
269 # if there is code of files to run from the cmd line, don't interact
270 # unless the --i flag (App.force_interact) is true.
270 # unless the --i flag (App.force_interact) is true.
271 force_interact = Bool(False, config=True,
271 force_interact = Bool(False, config=True,
272 help="""If a command or file is given via the command-line,
272 help="""If a command or file is given via the command-line,
273 e.g. 'ipython foo.py"""
273 e.g. 'ipython foo.py"""
274 )
274 )
275 def _force_interact_changed(self, name, old, new):
275 def _force_interact_changed(self, name, old, new):
276 if new:
276 if new:
277 self.interact = True
277 self.interact = True
278
278
279 def _file_to_run_changed(self, name, old, new):
279 def _file_to_run_changed(self, name, old, new):
280 if new:
280 if new:
281 self.something_to_run = True
281 self.something_to_run = True
282 if new and not self.force_interact:
282 if new and not self.force_interact:
283 self.interact = False
283 self.interact = False
284 _code_to_run_changed = _file_to_run_changed
284 _code_to_run_changed = _file_to_run_changed
285 _module_to_run_changed = _file_to_run_changed
285 _module_to_run_changed = _file_to_run_changed
286
286
287 # internal, not-configurable
287 # internal, not-configurable
288 interact=Bool(True)
288 interact=Bool(True)
289 something_to_run=Bool(False)
289 something_to_run=Bool(False)
290
290
291 def parse_command_line(self, argv=None):
291 def parse_command_line(self, argv=None):
292 """override to allow old '-pylab' flag with deprecation warning"""
292 """override to allow old '-pylab' flag with deprecation warning"""
293
293
294 argv = sys.argv[1:] if argv is None else argv
294 argv = sys.argv[1:] if argv is None else argv
295
295
296 if '-pylab' in argv:
296 if '-pylab' in argv:
297 # deprecated `-pylab` given,
297 # deprecated `-pylab` given,
298 # warn and transform into current syntax
298 # warn and transform into current syntax
299 argv = argv[:] # copy, don't clobber
299 argv = argv[:] # copy, don't clobber
300 idx = argv.index('-pylab')
300 idx = argv.index('-pylab')
301 warn.warn("`-pylab` flag has been deprecated.\n"
301 warn.warn("`-pylab` flag has been deprecated.\n"
302 " Use `--matplotlib <backend>` and import pylab manually.")
302 " Use `--matplotlib <backend>` and import pylab manually.")
303 argv[idx] = '--pylab'
303 argv[idx] = '--pylab'
304
304
305 return super(TerminalIPythonApp, self).parse_command_line(argv)
305 return super(TerminalIPythonApp, self).parse_command_line(argv)
306
306
307 @catch_config_error
307 @catch_config_error
308 def initialize(self, argv=None):
308 def initialize(self, argv=None):
309 """Do actions after construct, but before starting the app."""
309 """Do actions after construct, but before starting the app."""
310 super(TerminalIPythonApp, self).initialize(argv)
310 super(TerminalIPythonApp, self).initialize(argv)
311 if self.subapp is not None:
311 if self.subapp is not None:
312 # don't bother initializing further, starting subapp
312 # don't bother initializing further, starting subapp
313 return
313 return
314 if not self.ignore_old_config:
314 if not self.ignore_old_config:
315 check_for_old_config(self.ipython_dir)
315 check_for_old_config(self.ipython_dir)
316 # print self.extra_args
316 # print self.extra_args
317 if self.extra_args and not self.something_to_run:
317 if self.extra_args and not self.something_to_run:
318 self.file_to_run = self.extra_args[0]
318 self.file_to_run = self.extra_args[0]
319 self.init_path()
319 self.init_path()
320 # create the shell
320 # create the shell
321 self.init_shell()
321 self.init_shell()
322 # and draw the banner
322 # and draw the banner
323 self.init_banner()
323 self.init_banner()
324 # Now a variety of things that happen after the banner is printed.
324 # Now a variety of things that happen after the banner is printed.
325 self.init_gui_pylab()
325 self.init_gui_pylab()
326 self.init_extensions()
326 self.init_extensions()
327 self.init_code()
327 self.init_code()
328
328
329 def init_shell(self):
329 def init_shell(self):
330 """initialize the InteractiveShell instance"""
330 """initialize the InteractiveShell instance"""
331 # Create an InteractiveShell instance.
331 # Create an InteractiveShell instance.
332 # shell.display_banner should always be False for the terminal
332 # shell.display_banner should always be False for the terminal
333 # based app, because we call shell.show_banner() by hand below
333 # based app, because we call shell.show_banner() by hand below
334 # so the banner shows *before* all extension loading stuff.
334 # so the banner shows *before* all extension loading stuff.
335 self.shell = TerminalInteractiveShell.instance(parent=self,
335 self.shell = TerminalInteractiveShell.instance(parent=self,
336 display_banner=False, profile_dir=self.profile_dir,
336 display_banner=False, profile_dir=self.profile_dir,
337 ipython_dir=self.ipython_dir)
337 ipython_dir=self.ipython_dir, user_ns=self.user_ns)
338 self.shell.configurables.append(self)
338 self.shell.configurables.append(self)
339
339
340 def init_banner(self):
340 def init_banner(self):
341 """optionally display the banner"""
341 """optionally display the banner"""
342 if self.display_banner and self.interact:
342 if self.display_banner and self.interact:
343 self.shell.show_banner()
343 self.shell.show_banner()
344 # Make sure there is a space below the banner.
344 # Make sure there is a space below the banner.
345 if self.log_level <= logging.INFO: print
345 if self.log_level <= logging.INFO: print
346
346
347 def _pylab_changed(self, name, old, new):
347 def _pylab_changed(self, name, old, new):
348 """Replace --pylab='inline' with --pylab='auto'"""
348 """Replace --pylab='inline' with --pylab='auto'"""
349 if new == 'inline':
349 if new == 'inline':
350 warn.warn("'inline' not available as pylab backend, "
350 warn.warn("'inline' not available as pylab backend, "
351 "using 'auto' instead.")
351 "using 'auto' instead.")
352 self.pylab = 'auto'
352 self.pylab = 'auto'
353
353
354 def start(self):
354 def start(self):
355 if self.subapp is not None:
355 if self.subapp is not None:
356 return self.subapp.start()
356 return self.subapp.start()
357 # perform any prexec steps:
357 # perform any prexec steps:
358 if self.interact:
358 if self.interact:
359 self.log.debug("Starting IPython's mainloop...")
359 self.log.debug("Starting IPython's mainloop...")
360 self.shell.mainloop()
360 self.shell.mainloop()
361 else:
361 else:
362 self.log.debug("IPython not interactive...")
362 self.log.debug("IPython not interactive...")
363
363
364
364
365 def load_default_config(ipython_dir=None):
365 def load_default_config(ipython_dir=None):
366 """Load the default config file from the default ipython_dir.
366 """Load the default config file from the default ipython_dir.
367
367
368 This is useful for embedded shells.
368 This is useful for embedded shells.
369 """
369 """
370 if ipython_dir is None:
370 if ipython_dir is None:
371 ipython_dir = get_ipython_dir()
371 ipython_dir = get_ipython_dir()
372 profile_dir = os.path.join(ipython_dir, 'profile_default')
372 profile_dir = os.path.join(ipython_dir, 'profile_default')
373 cl = PyFileConfigLoader("ipython_config.py", profile_dir)
373 cl = PyFileConfigLoader("ipython_config.py", profile_dir)
374 try:
374 try:
375 config = cl.load_config()
375 config = cl.load_config()
376 except ConfigFileNotFound:
376 except ConfigFileNotFound:
377 # no config found
377 # no config found
378 config = Config()
378 config = Config()
379 return config
379 return config
380
380
381
381
382 launch_new_instance = TerminalIPythonApp.launch_instance
382 launch_new_instance = TerminalIPythonApp.launch_instance
383
383
384
384
385 if __name__ == '__main__':
385 if __name__ == '__main__':
386 launch_new_instance()
386 launch_new_instance()
General Comments 0
You need to be logged in to leave comments. Login now