##// END OF EJS Templates
Move sys.path.insert(0, '') from subclasses to InteractiveShellApp
Bradley M. Froehle -
Show More
@@ -1,313 +1,319 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.utils import py3compat
32 from IPython.utils import py3compat
33 from IPython.utils.path import filefind
33 from IPython.utils.path import filefind
34 from IPython.utils.traitlets import Unicode, Instance, List, Bool
34 from IPython.utils.traitlets import Unicode, Instance, List, Bool
35
35
36 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
37 # Aliases and Flags
37 # Aliases and Flags
38 #-----------------------------------------------------------------------------
38 #-----------------------------------------------------------------------------
39
39
40 shell_flags = {}
40 shell_flags = {}
41
41
42 addflag = lambda *args: shell_flags.update(boolean_flag(*args))
42 addflag = lambda *args: shell_flags.update(boolean_flag(*args))
43 addflag('autoindent', 'InteractiveShell.autoindent',
43 addflag('autoindent', 'InteractiveShell.autoindent',
44 'Turn on autoindenting.', 'Turn off autoindenting.'
44 'Turn on autoindenting.', 'Turn off autoindenting.'
45 )
45 )
46 addflag('automagic', 'InteractiveShell.automagic',
46 addflag('automagic', 'InteractiveShell.automagic',
47 """Turn on the auto calling of magic commands. Type %%magic at the
47 """Turn on the auto calling of magic commands. Type %%magic at the
48 IPython prompt for more information.""",
48 IPython prompt for more information.""",
49 'Turn off the auto calling of magic commands.'
49 'Turn off the auto calling of magic commands.'
50 )
50 )
51 addflag('pdb', 'InteractiveShell.pdb',
51 addflag('pdb', 'InteractiveShell.pdb',
52 "Enable auto calling the pdb debugger after every exception.",
52 "Enable auto calling the pdb debugger after every exception.",
53 "Disable auto calling the pdb debugger after every exception."
53 "Disable auto calling the pdb debugger after every exception."
54 )
54 )
55 # pydb flag doesn't do any config, as core.debugger switches on import,
55 # pydb flag doesn't do any config, as core.debugger switches on import,
56 # which is before parsing. This just allows the flag to be passed.
56 # which is before parsing. This just allows the flag to be passed.
57 shell_flags.update(dict(
57 shell_flags.update(dict(
58 pydb = ({},
58 pydb = ({},
59 """"Use the third party 'pydb' package as debugger, instead of pdb.
59 """"Use the third party 'pydb' package as debugger, instead of pdb.
60 Requires that pydb is installed."""
60 Requires that pydb is installed."""
61 )
61 )
62 ))
62 ))
63 addflag('pprint', 'PlainTextFormatter.pprint',
63 addflag('pprint', 'PlainTextFormatter.pprint',
64 "Enable auto pretty printing of results.",
64 "Enable auto pretty printing of results.",
65 "Disable auto auto pretty printing of results."
65 "Disable auto auto pretty printing of results."
66 )
66 )
67 addflag('color-info', 'InteractiveShell.color_info',
67 addflag('color-info', 'InteractiveShell.color_info',
68 """IPython can display information about objects via a set of func-
68 """IPython can display information about objects via a set of func-
69 tions, and optionally can use colors for this, syntax highlighting
69 tions, and optionally can use colors for this, syntax highlighting
70 source code and various other elements. However, because this
70 source code and various other elements. However, because this
71 information is passed through a pager (like 'less') and many pagers get
71 information is passed through a pager (like 'less') and many pagers get
72 confused with color codes, this option is off by default. You can test
72 confused with color codes, this option is off by default. You can test
73 it and turn it on permanently in your ipython_config.py file if it
73 it and turn it on permanently in your ipython_config.py file if it
74 works for you. Test it and turn it on permanently if it works with
74 works for you. Test it and turn it on permanently if it works with
75 your system. The magic function %%color_info allows you to toggle this
75 your system. The magic function %%color_info allows you to toggle this
76 interactively for testing.""",
76 interactively for testing.""",
77 "Disable using colors for info related things."
77 "Disable using colors for info related things."
78 )
78 )
79 addflag('deep-reload', 'InteractiveShell.deep_reload',
79 addflag('deep-reload', 'InteractiveShell.deep_reload',
80 """Enable deep (recursive) reloading by default. IPython can use the
80 """Enable deep (recursive) reloading by default. IPython can use the
81 deep_reload module which reloads changes in modules recursively (it
81 deep_reload module which reloads changes in modules recursively (it
82 replaces the reload() function, so you don't need to change anything to
82 replaces the reload() function, so you don't need to change anything to
83 use it). deep_reload() forces a full reload of modules whose code may
83 use it). deep_reload() forces a full reload of modules whose code may
84 have changed, which the default reload() function does not. When
84 have changed, which the default reload() function does not. When
85 deep_reload is off, IPython will use the normal reload(), but
85 deep_reload is off, IPython will use the normal reload(), but
86 deep_reload will still be available as dreload(). This feature is off
86 deep_reload will still be available as dreload(). This feature is off
87 by default [which means that you have both normal reload() and
87 by default [which means that you have both normal reload() and
88 dreload()].""",
88 dreload()].""",
89 "Disable deep (recursive) reloading by default."
89 "Disable deep (recursive) reloading by default."
90 )
90 )
91 nosep_config = Config()
91 nosep_config = Config()
92 nosep_config.InteractiveShell.separate_in = ''
92 nosep_config.InteractiveShell.separate_in = ''
93 nosep_config.InteractiveShell.separate_out = ''
93 nosep_config.InteractiveShell.separate_out = ''
94 nosep_config.InteractiveShell.separate_out2 = ''
94 nosep_config.InteractiveShell.separate_out2 = ''
95
95
96 shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
96 shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
97
97
98
98
99 # it's possible we don't want short aliases for *all* of these:
99 # it's possible we don't want short aliases for *all* of these:
100 shell_aliases = dict(
100 shell_aliases = dict(
101 autocall='InteractiveShell.autocall',
101 autocall='InteractiveShell.autocall',
102 colors='InteractiveShell.colors',
102 colors='InteractiveShell.colors',
103 logfile='InteractiveShell.logfile',
103 logfile='InteractiveShell.logfile',
104 logappend='InteractiveShell.logappend',
104 logappend='InteractiveShell.logappend',
105 c='InteractiveShellApp.code_to_run',
105 c='InteractiveShellApp.code_to_run',
106 m='InteractiveShellApp.module_to_run',
106 m='InteractiveShellApp.module_to_run',
107 ext='InteractiveShellApp.extra_extension',
107 ext='InteractiveShellApp.extra_extension',
108 )
108 )
109 shell_aliases['cache-size'] = 'InteractiveShell.cache_size'
109 shell_aliases['cache-size'] = 'InteractiveShell.cache_size'
110
110
111 #-----------------------------------------------------------------------------
111 #-----------------------------------------------------------------------------
112 # Main classes and functions
112 # Main classes and functions
113 #-----------------------------------------------------------------------------
113 #-----------------------------------------------------------------------------
114
114
115 class InteractiveShellApp(Configurable):
115 class InteractiveShellApp(Configurable):
116 """A Mixin for applications that start InteractiveShell instances.
116 """A Mixin for applications that start InteractiveShell instances.
117
117
118 Provides configurables for loading extensions and executing files
118 Provides configurables for loading extensions and executing files
119 as part of configuring a Shell environment.
119 as part of configuring a Shell environment.
120
120
121 Provides init_extensions() and init_code() methods, to be called
121 Provides init_path(), to be called before, and init_extensions() and
122 after init_shell(), which must be implemented by subclasses.
122 init_code() methods, to be called after init_shell(), which must be
123 implemented by subclasses.
123 """
124 """
124 extensions = List(Unicode, config=True,
125 extensions = List(Unicode, config=True,
125 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."
126 )
127 )
127 extra_extension = Unicode('', config=True,
128 extra_extension = Unicode('', config=True,
128 help="dotted module name of an IPython extension to load."
129 help="dotted module name of an IPython extension to load."
129 )
130 )
130 def _extra_extension_changed(self, name, old, new):
131 def _extra_extension_changed(self, name, old, new):
131 if new:
132 if new:
132 # add to self.extensions
133 # add to self.extensions
133 self.extensions.append(new)
134 self.extensions.append(new)
134
135
135 # Extensions that are always loaded (not configurable)
136 # Extensions that are always loaded (not configurable)
136 default_extensions = List(Unicode, [u'storemagic'], config=False)
137 default_extensions = List(Unicode, [u'storemagic'], config=False)
137
138
138 exec_files = List(Unicode, config=True,
139 exec_files = List(Unicode, config=True,
139 help="""List of files to run at IPython startup."""
140 help="""List of files to run at IPython startup."""
140 )
141 )
141 file_to_run = Unicode('', config=True,
142 file_to_run = Unicode('', config=True,
142 help="""A file to be run""")
143 help="""A file to be run""")
143
144
144 exec_lines = List(Unicode, config=True,
145 exec_lines = List(Unicode, config=True,
145 help="""lines of code to run at IPython startup."""
146 help="""lines of code to run at IPython startup."""
146 )
147 )
147 code_to_run = Unicode('', config=True,
148 code_to_run = Unicode('', config=True,
148 help="Execute the given command string."
149 help="Execute the given command string."
149 )
150 )
150 module_to_run = Unicode('', config=True,
151 module_to_run = Unicode('', config=True,
151 help="Run the module as a script."
152 help="Run the module as a script."
152 )
153 )
153 pylab_import_all = Bool(True, config=True,
154 pylab_import_all = Bool(True, config=True,
154 help="""If true, an 'import *' is done from numpy and pylab,
155 help="""If true, an 'import *' is done from numpy and pylab,
155 when using pylab"""
156 when using pylab"""
156 )
157 )
157 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
158 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
158
159
160 def init_path(self):
161 """Add current working directory, '', to sys.path"""
162 if sys.path[0] != '':
163 sys.path.insert(0, '')
164
159 def init_shell(self):
165 def init_shell(self):
160 raise NotImplementedError("Override in subclasses")
166 raise NotImplementedError("Override in subclasses")
161
167
162 def init_extensions(self):
168 def init_extensions(self):
163 """Load all IPython extensions in IPythonApp.extensions.
169 """Load all IPython extensions in IPythonApp.extensions.
164
170
165 This uses the :meth:`ExtensionManager.load_extensions` to load all
171 This uses the :meth:`ExtensionManager.load_extensions` to load all
166 the extensions listed in ``self.extensions``.
172 the extensions listed in ``self.extensions``.
167 """
173 """
168 try:
174 try:
169 self.log.debug("Loading IPython extensions...")
175 self.log.debug("Loading IPython extensions...")
170 extensions = self.default_extensions + self.extensions
176 extensions = self.default_extensions + self.extensions
171 for ext in extensions:
177 for ext in extensions:
172 try:
178 try:
173 self.log.info("Loading IPython extension: %s" % ext)
179 self.log.info("Loading IPython extension: %s" % ext)
174 self.shell.extension_manager.load_extension(ext)
180 self.shell.extension_manager.load_extension(ext)
175 except:
181 except:
176 self.log.warn("Error in loading extension: %s" % ext +
182 self.log.warn("Error in loading extension: %s" % ext +
177 "\nCheck your config files in %s" % self.profile_dir.location
183 "\nCheck your config files in %s" % self.profile_dir.location
178 )
184 )
179 self.shell.showtraceback()
185 self.shell.showtraceback()
180 except:
186 except:
181 self.log.warn("Unknown error in loading extensions:")
187 self.log.warn("Unknown error in loading extensions:")
182 self.shell.showtraceback()
188 self.shell.showtraceback()
183
189
184 def init_code(self):
190 def init_code(self):
185 """run the pre-flight code, specified via exec_lines"""
191 """run the pre-flight code, specified via exec_lines"""
186 self._run_startup_files()
192 self._run_startup_files()
187 self._run_exec_lines()
193 self._run_exec_lines()
188 self._run_exec_files()
194 self._run_exec_files()
189 self._run_cmd_line_code()
195 self._run_cmd_line_code()
190 self._run_module()
196 self._run_module()
191
197
192 # flush output, so itwon't be attached to the first cell
198 # flush output, so itwon't be attached to the first cell
193 sys.stdout.flush()
199 sys.stdout.flush()
194 sys.stderr.flush()
200 sys.stderr.flush()
195
201
196 # Hide variables defined here from %who etc.
202 # Hide variables defined here from %who etc.
197 self.shell.user_ns_hidden.update(self.shell.user_ns)
203 self.shell.user_ns_hidden.update(self.shell.user_ns)
198
204
199 def _run_exec_lines(self):
205 def _run_exec_lines(self):
200 """Run lines of code in IPythonApp.exec_lines in the user's namespace."""
206 """Run lines of code in IPythonApp.exec_lines in the user's namespace."""
201 if not self.exec_lines:
207 if not self.exec_lines:
202 return
208 return
203 try:
209 try:
204 self.log.debug("Running code from IPythonApp.exec_lines...")
210 self.log.debug("Running code from IPythonApp.exec_lines...")
205 for line in self.exec_lines:
211 for line in self.exec_lines:
206 try:
212 try:
207 self.log.info("Running code in user namespace: %s" %
213 self.log.info("Running code in user namespace: %s" %
208 line)
214 line)
209 self.shell.run_cell(line, store_history=False)
215 self.shell.run_cell(line, store_history=False)
210 except:
216 except:
211 self.log.warn("Error in executing line in user "
217 self.log.warn("Error in executing line in user "
212 "namespace: %s" % line)
218 "namespace: %s" % line)
213 self.shell.showtraceback()
219 self.shell.showtraceback()
214 except:
220 except:
215 self.log.warn("Unknown error in handling IPythonApp.exec_lines:")
221 self.log.warn("Unknown error in handling IPythonApp.exec_lines:")
216 self.shell.showtraceback()
222 self.shell.showtraceback()
217
223
218 def _exec_file(self, fname):
224 def _exec_file(self, fname):
219 try:
225 try:
220 full_filename = filefind(fname, [u'.', self.ipython_dir])
226 full_filename = filefind(fname, [u'.', self.ipython_dir])
221 except IOError as e:
227 except IOError as e:
222 self.log.warn("File not found: %r"%fname)
228 self.log.warn("File not found: %r"%fname)
223 return
229 return
224 # Make sure that the running script gets a proper sys.argv as if it
230 # Make sure that the running script gets a proper sys.argv as if it
225 # were run from a system shell.
231 # were run from a system shell.
226 save_argv = sys.argv
232 save_argv = sys.argv
227 sys.argv = [full_filename] + self.extra_args[1:]
233 sys.argv = [full_filename] + self.extra_args[1:]
228 # protect sys.argv from potential unicode strings on Python 2:
234 # protect sys.argv from potential unicode strings on Python 2:
229 if not py3compat.PY3:
235 if not py3compat.PY3:
230 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
236 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
231 try:
237 try:
232 if os.path.isfile(full_filename):
238 if os.path.isfile(full_filename):
233 if full_filename.endswith('.ipy'):
239 if full_filename.endswith('.ipy'):
234 self.log.info("Running file in user namespace: %s" %
240 self.log.info("Running file in user namespace: %s" %
235 full_filename)
241 full_filename)
236 self.shell.safe_execfile_ipy(full_filename)
242 self.shell.safe_execfile_ipy(full_filename)
237 else:
243 else:
238 # default to python, even without extension
244 # default to python, even without extension
239 self.log.info("Running file in user namespace: %s" %
245 self.log.info("Running file in user namespace: %s" %
240 full_filename)
246 full_filename)
241 # Ensure that __file__ is always defined to match Python behavior
247 # Ensure that __file__ is always defined to match Python behavior
242 self.shell.user_ns['__file__'] = fname
248 self.shell.user_ns['__file__'] = fname
243 try:
249 try:
244 self.shell.safe_execfile(full_filename, self.shell.user_ns)
250 self.shell.safe_execfile(full_filename, self.shell.user_ns)
245 finally:
251 finally:
246 del self.shell.user_ns['__file__']
252 del self.shell.user_ns['__file__']
247 finally:
253 finally:
248 sys.argv = save_argv
254 sys.argv = save_argv
249
255
250 def _run_startup_files(self):
256 def _run_startup_files(self):
251 """Run files from profile startup directory"""
257 """Run files from profile startup directory"""
252 startup_dir = self.profile_dir.startup_dir
258 startup_dir = self.profile_dir.startup_dir
253 startup_files = glob.glob(os.path.join(startup_dir, '*.py'))
259 startup_files = glob.glob(os.path.join(startup_dir, '*.py'))
254 startup_files += glob.glob(os.path.join(startup_dir, '*.ipy'))
260 startup_files += glob.glob(os.path.join(startup_dir, '*.ipy'))
255 if not startup_files:
261 if not startup_files:
256 return
262 return
257
263
258 self.log.debug("Running startup files from %s...", startup_dir)
264 self.log.debug("Running startup files from %s...", startup_dir)
259 try:
265 try:
260 for fname in sorted(startup_files):
266 for fname in sorted(startup_files):
261 self._exec_file(fname)
267 self._exec_file(fname)
262 except:
268 except:
263 self.log.warn("Unknown error in handling startup files:")
269 self.log.warn("Unknown error in handling startup files:")
264 self.shell.showtraceback()
270 self.shell.showtraceback()
265
271
266 def _run_exec_files(self):
272 def _run_exec_files(self):
267 """Run files from IPythonApp.exec_files"""
273 """Run files from IPythonApp.exec_files"""
268 if not self.exec_files:
274 if not self.exec_files:
269 return
275 return
270
276
271 self.log.debug("Running files in IPythonApp.exec_files...")
277 self.log.debug("Running files in IPythonApp.exec_files...")
272 try:
278 try:
273 for fname in self.exec_files:
279 for fname in self.exec_files:
274 self._exec_file(fname)
280 self._exec_file(fname)
275 except:
281 except:
276 self.log.warn("Unknown error in handling IPythonApp.exec_files:")
282 self.log.warn("Unknown error in handling IPythonApp.exec_files:")
277 self.shell.showtraceback()
283 self.shell.showtraceback()
278
284
279 def _run_cmd_line_code(self):
285 def _run_cmd_line_code(self):
280 """Run code or file specified at the command-line"""
286 """Run code or file specified at the command-line"""
281 if self.code_to_run:
287 if self.code_to_run:
282 line = self.code_to_run
288 line = self.code_to_run
283 try:
289 try:
284 self.log.info("Running code given at command line (c=): %s" %
290 self.log.info("Running code given at command line (c=): %s" %
285 line)
291 line)
286 self.shell.run_cell(line, store_history=False)
292 self.shell.run_cell(line, store_history=False)
287 except:
293 except:
288 self.log.warn("Error in executing line in user namespace: %s" %
294 self.log.warn("Error in executing line in user namespace: %s" %
289 line)
295 line)
290 self.shell.showtraceback()
296 self.shell.showtraceback()
291
297
292 # Like Python itself, ignore the second if the first of these is present
298 # Like Python itself, ignore the second if the first of these is present
293 elif self.file_to_run:
299 elif self.file_to_run:
294 fname = self.file_to_run
300 fname = self.file_to_run
295 try:
301 try:
296 self._exec_file(fname)
302 self._exec_file(fname)
297 except:
303 except:
298 self.log.warn("Error in executing file in user namespace: %s" %
304 self.log.warn("Error in executing file in user namespace: %s" %
299 fname)
305 fname)
300 self.shell.showtraceback()
306 self.shell.showtraceback()
301
307
302 def _run_module(self):
308 def _run_module(self):
303 """Run module specified at the command-line."""
309 """Run module specified at the command-line."""
304 if self.module_to_run:
310 if self.module_to_run:
305 # Make sure that the module gets a proper sys.argv as if it were
311 # Make sure that the module gets a proper sys.argv as if it were
306 # run using `python -m`.
312 # run using `python -m`.
307 save_argv = sys.argv
313 save_argv = sys.argv
308 sys.argv = [sys.executable] + self.extra_args
314 sys.argv = [sys.executable] + self.extra_args
309 try:
315 try:
310 self.shell.safe_run_module(self.module_to_run,
316 self.shell.safe_run_module(self.module_to_run,
311 self.shell.user_ns)
317 self.shell.user_ns)
312 finally:
318 finally:
313 sys.argv = save_argv
319 sys.argv = save_argv
@@ -1,413 +1,410 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.prompts import PromptManager
41 from IPython.core.prompts import PromptManager
42 from IPython.core.application import (
42 from IPython.core.application import (
43 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
43 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
44 )
44 )
45 from IPython.core.shellapp import (
45 from IPython.core.shellapp import (
46 InteractiveShellApp, shell_flags, shell_aliases
46 InteractiveShellApp, shell_flags, shell_aliases
47 )
47 )
48 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
48 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
49 from IPython.lib import inputhook
49 from IPython.lib import inputhook
50 from IPython.utils import warn
50 from IPython.utils import warn
51 from IPython.utils.path import get_ipython_dir, check_for_old_config
51 from IPython.utils.path import get_ipython_dir, check_for_old_config
52 from IPython.utils.traitlets import (
52 from IPython.utils.traitlets import (
53 Bool, List, Dict, CaselessStrEnum
53 Bool, List, Dict, CaselessStrEnum
54 )
54 )
55
55
56 #-----------------------------------------------------------------------------
56 #-----------------------------------------------------------------------------
57 # Globals, utilities and helpers
57 # Globals, utilities and helpers
58 #-----------------------------------------------------------------------------
58 #-----------------------------------------------------------------------------
59
59
60 #: The default config file name for this application.
60 #: The default config file name for this application.
61 default_config_file_name = u'ipython_config.py'
61 default_config_file_name = u'ipython_config.py'
62
62
63 _examples = """
63 _examples = """
64 ipython --pylab # start in pylab mode
64 ipython --pylab # start in pylab mode
65 ipython --pylab=qt # start in pylab mode with the qt4 backend
65 ipython --pylab=qt # start in pylab mode with the qt4 backend
66 ipython --log-level=DEBUG # set logging to DEBUG
66 ipython --log-level=DEBUG # set logging to DEBUG
67 ipython --profile=foo # start with profile foo
67 ipython --profile=foo # start with profile foo
68
68
69 ipython qtconsole # start the qtconsole GUI application
69 ipython qtconsole # start the qtconsole GUI application
70 ipython help qtconsole # show the help for the qtconsole subcmd
70 ipython help qtconsole # show the help for the qtconsole subcmd
71
71
72 ipython console # start the terminal-based console application
72 ipython console # start the terminal-based console application
73 ipython help console # show the help for the console subcmd
73 ipython help console # show the help for the console subcmd
74
74
75 ipython notebook # start the IPython notebook
75 ipython notebook # start the IPython notebook
76 ipython help notebook # show the help for the notebook subcmd
76 ipython help notebook # show the help for the notebook subcmd
77
77
78 ipython profile create foo # create profile foo w/ default config files
78 ipython profile create foo # create profile foo w/ default config files
79 ipython help profile # show the help for the profile subcmd
79 ipython help profile # show the help for the profile subcmd
80 """
80 """
81
81
82 #-----------------------------------------------------------------------------
82 #-----------------------------------------------------------------------------
83 # Crash handler for this application
83 # Crash handler for this application
84 #-----------------------------------------------------------------------------
84 #-----------------------------------------------------------------------------
85
85
86 class IPAppCrashHandler(CrashHandler):
86 class IPAppCrashHandler(CrashHandler):
87 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
87 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
88
88
89 def __init__(self, app):
89 def __init__(self, app):
90 contact_name = release.authors['Fernando'][0]
90 contact_name = release.authors['Fernando'][0]
91 contact_email = release.author_email
91 contact_email = release.author_email
92 bug_tracker = 'https://github.com/ipython/ipython/issues'
92 bug_tracker = 'https://github.com/ipython/ipython/issues'
93 super(IPAppCrashHandler,self).__init__(
93 super(IPAppCrashHandler,self).__init__(
94 app, contact_name, contact_email, bug_tracker
94 app, contact_name, contact_email, bug_tracker
95 )
95 )
96
96
97 def make_report(self,traceback):
97 def make_report(self,traceback):
98 """Return a string containing a crash report."""
98 """Return a string containing a crash report."""
99
99
100 sec_sep = self.section_sep
100 sec_sep = self.section_sep
101 # Start with parent report
101 # Start with parent report
102 report = [super(IPAppCrashHandler, self).make_report(traceback)]
102 report = [super(IPAppCrashHandler, self).make_report(traceback)]
103 # Add interactive-specific info we may have
103 # Add interactive-specific info we may have
104 rpt_add = report.append
104 rpt_add = report.append
105 try:
105 try:
106 rpt_add(sec_sep+"History of session input:")
106 rpt_add(sec_sep+"History of session input:")
107 for line in self.app.shell.user_ns['_ih']:
107 for line in self.app.shell.user_ns['_ih']:
108 rpt_add(line)
108 rpt_add(line)
109 rpt_add('\n*** Last line of input (may not be in above history):\n')
109 rpt_add('\n*** Last line of input (may not be in above history):\n')
110 rpt_add(self.app.shell._last_input_line+'\n')
110 rpt_add(self.app.shell._last_input_line+'\n')
111 except:
111 except:
112 pass
112 pass
113
113
114 return ''.join(report)
114 return ''.join(report)
115
115
116 #-----------------------------------------------------------------------------
116 #-----------------------------------------------------------------------------
117 # Aliases and Flags
117 # Aliases and Flags
118 #-----------------------------------------------------------------------------
118 #-----------------------------------------------------------------------------
119 flags = dict(base_flags)
119 flags = dict(base_flags)
120 flags.update(shell_flags)
120 flags.update(shell_flags)
121 frontend_flags = {}
121 frontend_flags = {}
122 addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
122 addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
123 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
123 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
124 'Turn on auto editing of files with syntax errors.',
124 'Turn on auto editing of files with syntax errors.',
125 'Turn off auto editing of files with syntax errors.'
125 'Turn off auto editing of files with syntax errors.'
126 )
126 )
127 addflag('banner', 'TerminalIPythonApp.display_banner',
127 addflag('banner', 'TerminalIPythonApp.display_banner',
128 "Display a banner upon starting IPython.",
128 "Display a banner upon starting IPython.",
129 "Don't display a banner upon starting IPython."
129 "Don't display a banner upon starting IPython."
130 )
130 )
131 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
131 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
132 """Set to confirm when you try to exit IPython with an EOF (Control-D
132 """Set to confirm when you try to exit IPython with an EOF (Control-D
133 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
133 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
134 you can force a direct exit without any confirmation.""",
134 you can force a direct exit without any confirmation.""",
135 "Don't prompt the user when exiting."
135 "Don't prompt the user when exiting."
136 )
136 )
137 addflag('term-title', 'TerminalInteractiveShell.term_title',
137 addflag('term-title', 'TerminalInteractiveShell.term_title',
138 "Enable auto setting the terminal title.",
138 "Enable auto setting the terminal title.",
139 "Disable auto setting the terminal title."
139 "Disable auto setting the terminal title."
140 )
140 )
141 classic_config = Config()
141 classic_config = Config()
142 classic_config.InteractiveShell.cache_size = 0
142 classic_config.InteractiveShell.cache_size = 0
143 classic_config.PlainTextFormatter.pprint = False
143 classic_config.PlainTextFormatter.pprint = False
144 classic_config.PromptManager.in_template = '>>> '
144 classic_config.PromptManager.in_template = '>>> '
145 classic_config.PromptManager.in2_template = '... '
145 classic_config.PromptManager.in2_template = '... '
146 classic_config.PromptManager.out_template = ''
146 classic_config.PromptManager.out_template = ''
147 classic_config.InteractiveShell.separate_in = ''
147 classic_config.InteractiveShell.separate_in = ''
148 classic_config.InteractiveShell.separate_out = ''
148 classic_config.InteractiveShell.separate_out = ''
149 classic_config.InteractiveShell.separate_out2 = ''
149 classic_config.InteractiveShell.separate_out2 = ''
150 classic_config.InteractiveShell.colors = 'NoColor'
150 classic_config.InteractiveShell.colors = 'NoColor'
151 classic_config.InteractiveShell.xmode = 'Plain'
151 classic_config.InteractiveShell.xmode = 'Plain'
152
152
153 frontend_flags['classic']=(
153 frontend_flags['classic']=(
154 classic_config,
154 classic_config,
155 "Gives IPython a similar feel to the classic Python prompt."
155 "Gives IPython a similar feel to the classic Python prompt."
156 )
156 )
157 # # log doesn't make so much sense this way anymore
157 # # log doesn't make so much sense this way anymore
158 # paa('--log','-l',
158 # paa('--log','-l',
159 # action='store_true', dest='InteractiveShell.logstart',
159 # action='store_true', dest='InteractiveShell.logstart',
160 # help="Start logging to the default log file (./ipython_log.py).")
160 # help="Start logging to the default log file (./ipython_log.py).")
161 #
161 #
162 # # quick is harder to implement
162 # # quick is harder to implement
163 frontend_flags['quick']=(
163 frontend_flags['quick']=(
164 {'TerminalIPythonApp' : {'quick' : True}},
164 {'TerminalIPythonApp' : {'quick' : True}},
165 "Enable quick startup with no config files."
165 "Enable quick startup with no config files."
166 )
166 )
167
167
168 frontend_flags['i'] = (
168 frontend_flags['i'] = (
169 {'TerminalIPythonApp' : {'force_interact' : True}},
169 {'TerminalIPythonApp' : {'force_interact' : True}},
170 """If running code from the command line, become interactive afterwards.
170 """If running code from the command line, become interactive afterwards.
171 Note: can also be given simply as '-i.'"""
171 Note: can also be given simply as '-i.'"""
172 )
172 )
173 frontend_flags['pylab'] = (
173 frontend_flags['pylab'] = (
174 {'TerminalIPythonApp' : {'pylab' : 'auto'}},
174 {'TerminalIPythonApp' : {'pylab' : 'auto'}},
175 """Pre-load matplotlib and numpy for interactive use with
175 """Pre-load matplotlib and numpy for interactive use with
176 the default matplotlib backend."""
176 the default matplotlib backend."""
177 )
177 )
178 flags.update(frontend_flags)
178 flags.update(frontend_flags)
179
179
180 aliases = dict(base_aliases)
180 aliases = dict(base_aliases)
181 aliases.update(shell_aliases)
181 aliases.update(shell_aliases)
182
182
183 # it's possible we don't want short aliases for *all* of these:
183 # it's possible we don't want short aliases for *all* of these:
184 aliases.update(dict(
184 aliases.update(dict(
185 gui='TerminalIPythonApp.gui',
185 gui='TerminalIPythonApp.gui',
186 pylab='TerminalIPythonApp.pylab',
186 pylab='TerminalIPythonApp.pylab',
187 ))
187 ))
188
188
189 #-----------------------------------------------------------------------------
189 #-----------------------------------------------------------------------------
190 # Main classes and functions
190 # Main classes and functions
191 #-----------------------------------------------------------------------------
191 #-----------------------------------------------------------------------------
192
192
193 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
193 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
194 name = u'ipython'
194 name = u'ipython'
195 description = usage.cl_usage
195 description = usage.cl_usage
196 default_config_file_name = default_config_file_name
196 default_config_file_name = default_config_file_name
197 crash_handler_class = IPAppCrashHandler
197 crash_handler_class = IPAppCrashHandler
198 examples = _examples
198 examples = _examples
199
199
200 flags = Dict(flags)
200 flags = Dict(flags)
201 aliases = Dict(aliases)
201 aliases = Dict(aliases)
202 classes = List()
202 classes = List()
203 def _classes_default(self):
203 def _classes_default(self):
204 """This has to be in a method, for TerminalIPythonApp to be available."""
204 """This has to be in a method, for TerminalIPythonApp to be available."""
205 return [
205 return [
206 InteractiveShellApp, # ShellApp comes before TerminalApp, because
206 InteractiveShellApp, # ShellApp comes before TerminalApp, because
207 self.__class__, # it will also affect subclasses (e.g. QtConsole)
207 self.__class__, # it will also affect subclasses (e.g. QtConsole)
208 TerminalInteractiveShell,
208 TerminalInteractiveShell,
209 PromptManager,
209 PromptManager,
210 ProfileDir,
210 ProfileDir,
211 PlainTextFormatter,
211 PlainTextFormatter,
212 IPCompleter,
212 IPCompleter,
213 ]
213 ]
214
214
215 subcommands = Dict(dict(
215 subcommands = Dict(dict(
216 qtconsole=('IPython.frontend.qt.console.qtconsoleapp.IPythonQtConsoleApp',
216 qtconsole=('IPython.frontend.qt.console.qtconsoleapp.IPythonQtConsoleApp',
217 """Launch the IPython Qt Console."""
217 """Launch the IPython Qt Console."""
218 ),
218 ),
219 notebook=('IPython.frontend.html.notebook.notebookapp.NotebookApp',
219 notebook=('IPython.frontend.html.notebook.notebookapp.NotebookApp',
220 """Launch the IPython HTML Notebook Server."""
220 """Launch the IPython HTML Notebook Server."""
221 ),
221 ),
222 profile = ("IPython.core.profileapp.ProfileApp",
222 profile = ("IPython.core.profileapp.ProfileApp",
223 "Create and manage IPython profiles."
223 "Create and manage IPython profiles."
224 ),
224 ),
225 kernel = ("IPython.zmq.ipkernel.IPKernelApp",
225 kernel = ("IPython.zmq.ipkernel.IPKernelApp",
226 "Start a kernel without an attached frontend."
226 "Start a kernel without an attached frontend."
227 ),
227 ),
228 console=('IPython.frontend.terminal.console.app.ZMQTerminalIPythonApp',
228 console=('IPython.frontend.terminal.console.app.ZMQTerminalIPythonApp',
229 """Launch the IPython terminal-based Console."""
229 """Launch the IPython terminal-based Console."""
230 ),
230 ),
231 ))
231 ))
232
232
233 # *do* autocreate requested profile, but don't create the config file.
233 # *do* autocreate requested profile, but don't create the config file.
234 auto_create=Bool(True)
234 auto_create=Bool(True)
235 # configurables
235 # configurables
236 ignore_old_config=Bool(False, config=True,
236 ignore_old_config=Bool(False, config=True,
237 help="Suppress warning messages about legacy config files"
237 help="Suppress warning messages about legacy config files"
238 )
238 )
239 quick = Bool(False, config=True,
239 quick = Bool(False, config=True,
240 help="""Start IPython quickly by skipping the loading of config files."""
240 help="""Start IPython quickly by skipping the loading of config files."""
241 )
241 )
242 def _quick_changed(self, name, old, new):
242 def _quick_changed(self, name, old, new):
243 if new:
243 if new:
244 self.load_config_file = lambda *a, **kw: None
244 self.load_config_file = lambda *a, **kw: None
245 self.ignore_old_config=True
245 self.ignore_old_config=True
246
246
247 gui = CaselessStrEnum(('qt', 'wx', 'gtk', 'glut', 'pyglet'), config=True,
247 gui = CaselessStrEnum(('qt', 'wx', 'gtk', 'glut', 'pyglet'), config=True,
248 help="Enable GUI event loop integration ('qt', 'wx', 'gtk', 'glut', 'pyglet')."
248 help="Enable GUI event loop integration ('qt', 'wx', 'gtk', 'glut', 'pyglet')."
249 )
249 )
250 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'auto'],
250 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'auto'],
251 config=True,
251 config=True,
252 help="""Pre-load matplotlib and numpy for interactive use,
252 help="""Pre-load matplotlib and numpy for interactive use,
253 selecting a particular matplotlib backend and loop integration.
253 selecting a particular matplotlib backend and loop integration.
254 """
254 """
255 )
255 )
256 display_banner = Bool(True, config=True,
256 display_banner = Bool(True, config=True,
257 help="Whether to display a banner upon starting IPython."
257 help="Whether to display a banner upon starting IPython."
258 )
258 )
259
259
260 # if there is code of files to run from the cmd line, don't interact
260 # if there is code of files to run from the cmd line, don't interact
261 # unless the --i flag (App.force_interact) is true.
261 # unless the --i flag (App.force_interact) is true.
262 force_interact = Bool(False, config=True,
262 force_interact = Bool(False, config=True,
263 help="""If a command or file is given via the command-line,
263 help="""If a command or file is given via the command-line,
264 e.g. 'ipython foo.py"""
264 e.g. 'ipython foo.py"""
265 )
265 )
266 def _force_interact_changed(self, name, old, new):
266 def _force_interact_changed(self, name, old, new):
267 if new:
267 if new:
268 self.interact = True
268 self.interact = True
269
269
270 def _file_to_run_changed(self, name, old, new):
270 def _file_to_run_changed(self, name, old, new):
271 if new:
271 if new:
272 self.something_to_run = True
272 self.something_to_run = True
273 if new and not self.force_interact:
273 if new and not self.force_interact:
274 self.interact = False
274 self.interact = False
275 _code_to_run_changed = _file_to_run_changed
275 _code_to_run_changed = _file_to_run_changed
276 _module_to_run_changed = _file_to_run_changed
276 _module_to_run_changed = _file_to_run_changed
277
277
278 # internal, not-configurable
278 # internal, not-configurable
279 interact=Bool(True)
279 interact=Bool(True)
280 something_to_run=Bool(False)
280 something_to_run=Bool(False)
281
281
282 def parse_command_line(self, argv=None):
282 def parse_command_line(self, argv=None):
283 """override to allow old '-pylab' flag with deprecation warning"""
283 """override to allow old '-pylab' flag with deprecation warning"""
284
284
285 argv = sys.argv[1:] if argv is None else argv
285 argv = sys.argv[1:] if argv is None else argv
286
286
287 if '-pylab' in argv:
287 if '-pylab' in argv:
288 # deprecated `-pylab` given,
288 # deprecated `-pylab` given,
289 # warn and transform into current syntax
289 # warn and transform into current syntax
290 argv = argv[:] # copy, don't clobber
290 argv = argv[:] # copy, don't clobber
291 idx = argv.index('-pylab')
291 idx = argv.index('-pylab')
292 warn.warn("`-pylab` flag has been deprecated.\n"
292 warn.warn("`-pylab` flag has been deprecated.\n"
293 " Use `--pylab` instead, or `--pylab=foo` to specify a backend.")
293 " Use `--pylab` instead, or `--pylab=foo` to specify a backend.")
294 sub = '--pylab'
294 sub = '--pylab'
295 if len(argv) > idx+1:
295 if len(argv) > idx+1:
296 # check for gui arg, as in '-pylab qt'
296 # check for gui arg, as in '-pylab qt'
297 gui = argv[idx+1]
297 gui = argv[idx+1]
298 if gui in ('wx', 'qt', 'qt4', 'gtk', 'auto'):
298 if gui in ('wx', 'qt', 'qt4', 'gtk', 'auto'):
299 sub = '--pylab='+gui
299 sub = '--pylab='+gui
300 argv.pop(idx+1)
300 argv.pop(idx+1)
301 argv[idx] = sub
301 argv[idx] = sub
302
302
303 return super(TerminalIPythonApp, self).parse_command_line(argv)
303 return super(TerminalIPythonApp, self).parse_command_line(argv)
304
304
305 @catch_config_error
305 @catch_config_error
306 def initialize(self, argv=None):
306 def initialize(self, argv=None):
307 """Do actions after construct, but before starting the app."""
307 """Do actions after construct, but before starting the app."""
308 super(TerminalIPythonApp, self).initialize(argv)
308 super(TerminalIPythonApp, self).initialize(argv)
309 if self.subapp is not None:
309 if self.subapp is not None:
310 # don't bother initializing further, starting subapp
310 # don't bother initializing further, starting subapp
311 return
311 return
312 if not self.ignore_old_config:
312 if not self.ignore_old_config:
313 check_for_old_config(self.ipython_dir)
313 check_for_old_config(self.ipython_dir)
314 # print self.extra_args
314 # print self.extra_args
315 if self.extra_args and not self.something_to_run:
315 if self.extra_args and not self.something_to_run:
316 self.file_to_run = self.extra_args[0]
316 self.file_to_run = self.extra_args[0]
317 self.init_path()
317 # create the shell
318 # create the shell
318 self.init_shell()
319 self.init_shell()
319 # and draw the banner
320 # and draw the banner
320 self.init_banner()
321 self.init_banner()
321 # Now a variety of things that happen after the banner is printed.
322 # Now a variety of things that happen after the banner is printed.
322 self.init_gui_pylab()
323 self.init_gui_pylab()
323 self.init_extensions()
324 self.init_extensions()
324 self.init_code()
325 self.init_code()
325
326
326 def init_shell(self):
327 def init_shell(self):
327 """initialize the InteractiveShell instance"""
328 """initialize the InteractiveShell instance"""
328 # I am a little hesitant to put these into InteractiveShell itself.
329 # But that might be the place for them
330 sys.path.insert(0, '')
331
332 # Create an InteractiveShell instance.
329 # Create an InteractiveShell instance.
333 # shell.display_banner should always be False for the terminal
330 # shell.display_banner should always be False for the terminal
334 # based app, because we call shell.show_banner() by hand below
331 # based app, because we call shell.show_banner() by hand below
335 # so the banner shows *before* all extension loading stuff.
332 # so the banner shows *before* all extension loading stuff.
336 self.shell = TerminalInteractiveShell.instance(config=self.config,
333 self.shell = TerminalInteractiveShell.instance(config=self.config,
337 display_banner=False, profile_dir=self.profile_dir,
334 display_banner=False, profile_dir=self.profile_dir,
338 ipython_dir=self.ipython_dir)
335 ipython_dir=self.ipython_dir)
339 self.shell.configurables.append(self)
336 self.shell.configurables.append(self)
340
337
341 def init_banner(self):
338 def init_banner(self):
342 """optionally display the banner"""
339 """optionally display the banner"""
343 if self.display_banner and self.interact:
340 if self.display_banner and self.interact:
344 self.shell.show_banner()
341 self.shell.show_banner()
345 # Make sure there is a space below the banner.
342 # Make sure there is a space below the banner.
346 if self.log_level <= logging.INFO: print
343 if self.log_level <= logging.INFO: print
347
344
348
345
349 def init_gui_pylab(self):
346 def init_gui_pylab(self):
350 """Enable GUI event loop integration, taking pylab into account."""
347 """Enable GUI event loop integration, taking pylab into account."""
351 gui = self.gui
348 gui = self.gui
352
349
353 # Using `pylab` will also require gui activation, though which toolkit
350 # Using `pylab` will also require gui activation, though which toolkit
354 # to use may be chosen automatically based on mpl configuration.
351 # to use may be chosen automatically based on mpl configuration.
355 if self.pylab:
352 if self.pylab:
356 activate = self.shell.enable_pylab
353 activate = self.shell.enable_pylab
357 if self.pylab == 'auto':
354 if self.pylab == 'auto':
358 gui = None
355 gui = None
359 else:
356 else:
360 gui = self.pylab
357 gui = self.pylab
361 else:
358 else:
362 # Enable only GUI integration, no pylab
359 # Enable only GUI integration, no pylab
363 activate = inputhook.enable_gui
360 activate = inputhook.enable_gui
364
361
365 if gui or self.pylab:
362 if gui or self.pylab:
366 try:
363 try:
367 self.log.info("Enabling GUI event loop integration, "
364 self.log.info("Enabling GUI event loop integration, "
368 "toolkit=%s, pylab=%s" % (gui, self.pylab) )
365 "toolkit=%s, pylab=%s" % (gui, self.pylab) )
369 if self.pylab:
366 if self.pylab:
370 activate(gui, import_all=self.pylab_import_all)
367 activate(gui, import_all=self.pylab_import_all)
371 else:
368 else:
372 activate(gui)
369 activate(gui)
373 except:
370 except:
374 self.log.warn("Error in enabling GUI event loop integration:")
371 self.log.warn("Error in enabling GUI event loop integration:")
375 self.shell.showtraceback()
372 self.shell.showtraceback()
376
373
377 def start(self):
374 def start(self):
378 if self.subapp is not None:
375 if self.subapp is not None:
379 return self.subapp.start()
376 return self.subapp.start()
380 # perform any prexec steps:
377 # perform any prexec steps:
381 if self.interact:
378 if self.interact:
382 self.log.debug("Starting IPython's mainloop...")
379 self.log.debug("Starting IPython's mainloop...")
383 self.shell.mainloop()
380 self.shell.mainloop()
384 else:
381 else:
385 self.log.debug("IPython not interactive...")
382 self.log.debug("IPython not interactive...")
386
383
387
384
388 def load_default_config(ipython_dir=None):
385 def load_default_config(ipython_dir=None):
389 """Load the default config file from the default ipython_dir.
386 """Load the default config file from the default ipython_dir.
390
387
391 This is useful for embedded shells.
388 This is useful for embedded shells.
392 """
389 """
393 if ipython_dir is None:
390 if ipython_dir is None:
394 ipython_dir = get_ipython_dir()
391 ipython_dir = get_ipython_dir()
395 profile_dir = os.path.join(ipython_dir, 'profile_default')
392 profile_dir = os.path.join(ipython_dir, 'profile_default')
396 cl = PyFileConfigLoader(default_config_file_name, profile_dir)
393 cl = PyFileConfigLoader(default_config_file_name, profile_dir)
397 try:
394 try:
398 config = cl.load_config()
395 config = cl.load_config()
399 except ConfigFileNotFound:
396 except ConfigFileNotFound:
400 # no config found
397 # no config found
401 config = Config()
398 config = Config()
402 return config
399 return config
403
400
404
401
405 def launch_new_instance():
402 def launch_new_instance():
406 """Create and run a full blown IPython instance"""
403 """Create and run a full blown IPython instance"""
407 app = TerminalIPythonApp.instance()
404 app = TerminalIPythonApp.instance()
408 app.initialize()
405 app.initialize()
409 app.start()
406 app.start()
410
407
411
408
412 if __name__ == '__main__':
409 if __name__ == '__main__':
413 launch_new_instance()
410 launch_new_instance()
@@ -1,713 +1,710 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 """A simple interactive kernel that talks to a frontend over 0MQ.
2 """A simple interactive kernel that talks to a frontend over 0MQ.
3
3
4 Things to do:
4 Things to do:
5
5
6 * Implement `set_parent` logic. Right before doing exec, the Kernel should
6 * Implement `set_parent` logic. Right before doing exec, the Kernel should
7 call set_parent on all the PUB objects with the message about to be executed.
7 call set_parent on all the PUB objects with the message about to be executed.
8 * Implement random port and security key logic.
8 * Implement random port and security key logic.
9 * Implement control messages.
9 * Implement control messages.
10 * Implement event loop and poll version.
10 * Implement event loop and poll version.
11 """
11 """
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from __future__ import print_function
16 from __future__ import print_function
17
17
18 # Standard library imports.
18 # Standard library imports.
19 import __builtin__
19 import __builtin__
20 import atexit
20 import atexit
21 import sys
21 import sys
22 import time
22 import time
23 import traceback
23 import traceback
24 import logging
24 import logging
25 from signal import (
25 from signal import (
26 signal, default_int_handler, SIGINT, SIG_IGN
26 signal, default_int_handler, SIGINT, SIG_IGN
27 )
27 )
28 # System library imports.
28 # System library imports.
29 import zmq
29 import zmq
30
30
31 # Local imports.
31 # Local imports.
32 from IPython.core import pylabtools
32 from IPython.core import pylabtools
33 from IPython.config.configurable import Configurable
33 from IPython.config.configurable import Configurable
34 from IPython.config.application import boolean_flag, catch_config_error
34 from IPython.config.application import boolean_flag, catch_config_error
35 from IPython.core.application import ProfileDir
35 from IPython.core.application import ProfileDir
36 from IPython.core.error import StdinNotImplementedError
36 from IPython.core.error import StdinNotImplementedError
37 from IPython.core.shellapp import (
37 from IPython.core.shellapp import (
38 InteractiveShellApp, shell_flags, shell_aliases
38 InteractiveShellApp, shell_flags, shell_aliases
39 )
39 )
40 from IPython.utils import io
40 from IPython.utils import io
41 from IPython.utils import py3compat
41 from IPython.utils import py3compat
42 from IPython.utils.frame import extract_module_locals
42 from IPython.utils.frame import extract_module_locals
43 from IPython.utils.jsonutil import json_clean
43 from IPython.utils.jsonutil import json_clean
44 from IPython.utils.traitlets import (
44 from IPython.utils.traitlets import (
45 Any, Instance, Float, Dict, CaselessStrEnum
45 Any, Instance, Float, Dict, CaselessStrEnum
46 )
46 )
47
47
48 from entry_point import base_launch_kernel
48 from entry_point import base_launch_kernel
49 from kernelapp import KernelApp, kernel_flags, kernel_aliases
49 from kernelapp import KernelApp, kernel_flags, kernel_aliases
50 from session import Session, Message
50 from session import Session, Message
51 from zmqshell import ZMQInteractiveShell
51 from zmqshell import ZMQInteractiveShell
52
52
53
53
54 #-----------------------------------------------------------------------------
54 #-----------------------------------------------------------------------------
55 # Main kernel class
55 # Main kernel class
56 #-----------------------------------------------------------------------------
56 #-----------------------------------------------------------------------------
57
57
58 class Kernel(Configurable):
58 class Kernel(Configurable):
59
59
60 #---------------------------------------------------------------------------
60 #---------------------------------------------------------------------------
61 # Kernel interface
61 # Kernel interface
62 #---------------------------------------------------------------------------
62 #---------------------------------------------------------------------------
63
63
64 # attribute to override with a GUI
64 # attribute to override with a GUI
65 eventloop = Any(None)
65 eventloop = Any(None)
66
66
67 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
67 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
68 session = Instance(Session)
68 session = Instance(Session)
69 profile_dir = Instance('IPython.core.profiledir.ProfileDir')
69 profile_dir = Instance('IPython.core.profiledir.ProfileDir')
70 shell_socket = Instance('zmq.Socket')
70 shell_socket = Instance('zmq.Socket')
71 iopub_socket = Instance('zmq.Socket')
71 iopub_socket = Instance('zmq.Socket')
72 stdin_socket = Instance('zmq.Socket')
72 stdin_socket = Instance('zmq.Socket')
73 log = Instance(logging.Logger)
73 log = Instance(logging.Logger)
74
74
75 user_module = Instance('types.ModuleType')
75 user_module = Instance('types.ModuleType')
76 def _user_module_changed(self, name, old, new):
76 def _user_module_changed(self, name, old, new):
77 if self.shell is not None:
77 if self.shell is not None:
78 self.shell.user_module = new
78 self.shell.user_module = new
79
79
80 user_ns = Dict(default_value=None)
80 user_ns = Dict(default_value=None)
81 def _user_ns_changed(self, name, old, new):
81 def _user_ns_changed(self, name, old, new):
82 if self.shell is not None:
82 if self.shell is not None:
83 self.shell.user_ns = new
83 self.shell.user_ns = new
84 self.shell.init_user_ns()
84 self.shell.init_user_ns()
85
85
86 # Private interface
86 # Private interface
87
87
88 # Time to sleep after flushing the stdout/err buffers in each execute
88 # Time to sleep after flushing the stdout/err buffers in each execute
89 # cycle. While this introduces a hard limit on the minimal latency of the
89 # cycle. While this introduces a hard limit on the minimal latency of the
90 # execute cycle, it helps prevent output synchronization problems for
90 # execute cycle, it helps prevent output synchronization problems for
91 # clients.
91 # clients.
92 # Units are in seconds. The minimum zmq latency on local host is probably
92 # Units are in seconds. The minimum zmq latency on local host is probably
93 # ~150 microseconds, set this to 500us for now. We may need to increase it
93 # ~150 microseconds, set this to 500us for now. We may need to increase it
94 # a little if it's not enough after more interactive testing.
94 # a little if it's not enough after more interactive testing.
95 _execute_sleep = Float(0.0005, config=True)
95 _execute_sleep = Float(0.0005, config=True)
96
96
97 # Frequency of the kernel's event loop.
97 # Frequency of the kernel's event loop.
98 # Units are in seconds, kernel subclasses for GUI toolkits may need to
98 # Units are in seconds, kernel subclasses for GUI toolkits may need to
99 # adapt to milliseconds.
99 # adapt to milliseconds.
100 _poll_interval = Float(0.05, config=True)
100 _poll_interval = Float(0.05, config=True)
101
101
102 # If the shutdown was requested over the network, we leave here the
102 # If the shutdown was requested over the network, we leave here the
103 # necessary reply message so it can be sent by our registered atexit
103 # necessary reply message so it can be sent by our registered atexit
104 # handler. This ensures that the reply is only sent to clients truly at
104 # handler. This ensures that the reply is only sent to clients truly at
105 # the end of our shutdown process (which happens after the underlying
105 # the end of our shutdown process (which happens after the underlying
106 # IPython shell's own shutdown).
106 # IPython shell's own shutdown).
107 _shutdown_message = None
107 _shutdown_message = None
108
108
109 # This is a dict of port number that the kernel is listening on. It is set
109 # This is a dict of port number that the kernel is listening on. It is set
110 # by record_ports and used by connect_request.
110 # by record_ports and used by connect_request.
111 _recorded_ports = Dict()
111 _recorded_ports = Dict()
112
112
113
113
114
114
115 def __init__(self, **kwargs):
115 def __init__(self, **kwargs):
116 super(Kernel, self).__init__(**kwargs)
116 super(Kernel, self).__init__(**kwargs)
117
117
118 # Before we even start up the shell, register *first* our exit handlers
118 # Before we even start up the shell, register *first* our exit handlers
119 # so they come before the shell's
119 # so they come before the shell's
120 atexit.register(self._at_shutdown)
120 atexit.register(self._at_shutdown)
121
121
122 # Initialize the InteractiveShell subclass
122 # Initialize the InteractiveShell subclass
123 self.shell = ZMQInteractiveShell.instance(config=self.config,
123 self.shell = ZMQInteractiveShell.instance(config=self.config,
124 profile_dir = self.profile_dir,
124 profile_dir = self.profile_dir,
125 user_module = self.user_module,
125 user_module = self.user_module,
126 user_ns = self.user_ns,
126 user_ns = self.user_ns,
127 )
127 )
128 self.shell.displayhook.session = self.session
128 self.shell.displayhook.session = self.session
129 self.shell.displayhook.pub_socket = self.iopub_socket
129 self.shell.displayhook.pub_socket = self.iopub_socket
130 self.shell.display_pub.session = self.session
130 self.shell.display_pub.session = self.session
131 self.shell.display_pub.pub_socket = self.iopub_socket
131 self.shell.display_pub.pub_socket = self.iopub_socket
132
132
133 # TMP - hack while developing
133 # TMP - hack while developing
134 self.shell._reply_content = None
134 self.shell._reply_content = None
135
135
136 # Build dict of handlers for message types
136 # Build dict of handlers for message types
137 msg_types = [ 'execute_request', 'complete_request',
137 msg_types = [ 'execute_request', 'complete_request',
138 'object_info_request', 'history_request',
138 'object_info_request', 'history_request',
139 'connect_request', 'shutdown_request']
139 'connect_request', 'shutdown_request']
140 self.handlers = {}
140 self.handlers = {}
141 for msg_type in msg_types:
141 for msg_type in msg_types:
142 self.handlers[msg_type] = getattr(self, msg_type)
142 self.handlers[msg_type] = getattr(self, msg_type)
143
143
144 def do_one_iteration(self):
144 def do_one_iteration(self):
145 """Do one iteration of the kernel's evaluation loop.
145 """Do one iteration of the kernel's evaluation loop.
146 """
146 """
147 try:
147 try:
148 ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
148 ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
149 except Exception:
149 except Exception:
150 self.log.warn("Invalid Message:", exc_info=True)
150 self.log.warn("Invalid Message:", exc_info=True)
151 return
151 return
152 if msg is None:
152 if msg is None:
153 return
153 return
154
154
155 msg_type = msg['header']['msg_type']
155 msg_type = msg['header']['msg_type']
156
156
157 # This assert will raise in versions of zeromq 2.0.7 and lesser.
157 # This assert will raise in versions of zeromq 2.0.7 and lesser.
158 # We now require 2.0.8 or above, so we can uncomment for safety.
158 # We now require 2.0.8 or above, so we can uncomment for safety.
159 # print(ident,msg, file=sys.__stdout__)
159 # print(ident,msg, file=sys.__stdout__)
160 assert ident is not None, "Missing message part."
160 assert ident is not None, "Missing message part."
161
161
162 # Print some info about this message and leave a '--->' marker, so it's
162 # Print some info about this message and leave a '--->' marker, so it's
163 # easier to trace visually the message chain when debugging. Each
163 # easier to trace visually the message chain when debugging. Each
164 # handler prints its message at the end.
164 # handler prints its message at the end.
165 self.log.debug('\n*** MESSAGE TYPE:'+str(msg_type)+'***')
165 self.log.debug('\n*** MESSAGE TYPE:'+str(msg_type)+'***')
166 self.log.debug(' Content: '+str(msg['content'])+'\n --->\n ')
166 self.log.debug(' Content: '+str(msg['content'])+'\n --->\n ')
167
167
168 # Find and call actual handler for message
168 # Find and call actual handler for message
169 handler = self.handlers.get(msg_type, None)
169 handler = self.handlers.get(msg_type, None)
170 if handler is None:
170 if handler is None:
171 self.log.error("UNKNOWN MESSAGE TYPE:" +str(msg))
171 self.log.error("UNKNOWN MESSAGE TYPE:" +str(msg))
172 else:
172 else:
173 handler(ident, msg)
173 handler(ident, msg)
174
174
175 # Check whether we should exit, in case the incoming message set the
175 # Check whether we should exit, in case the incoming message set the
176 # exit flag on
176 # exit flag on
177 if self.shell.exit_now:
177 if self.shell.exit_now:
178 self.log.debug('\nExiting IPython kernel...')
178 self.log.debug('\nExiting IPython kernel...')
179 # We do a normal, clean exit, which allows any actions registered
179 # We do a normal, clean exit, which allows any actions registered
180 # via atexit (such as history saving) to take place.
180 # via atexit (such as history saving) to take place.
181 sys.exit(0)
181 sys.exit(0)
182
182
183
183
184 def start(self):
184 def start(self):
185 """ Start the kernel main loop.
185 """ Start the kernel main loop.
186 """
186 """
187 # a KeyboardInterrupt (SIGINT) can occur on any python statement, so
187 # a KeyboardInterrupt (SIGINT) can occur on any python statement, so
188 # let's ignore (SIG_IGN) them until we're in a place to handle them properly
188 # let's ignore (SIG_IGN) them until we're in a place to handle them properly
189 signal(SIGINT,SIG_IGN)
189 signal(SIGINT,SIG_IGN)
190 poller = zmq.Poller()
190 poller = zmq.Poller()
191 poller.register(self.shell_socket, zmq.POLLIN)
191 poller.register(self.shell_socket, zmq.POLLIN)
192 # loop while self.eventloop has not been overridden
192 # loop while self.eventloop has not been overridden
193 while self.eventloop is None:
193 while self.eventloop is None:
194 try:
194 try:
195 # scale by extra factor of 10, because there is no
195 # scale by extra factor of 10, because there is no
196 # reason for this to be anything less than ~ 0.1s
196 # reason for this to be anything less than ~ 0.1s
197 # since it is a real poller and will respond
197 # since it is a real poller and will respond
198 # to events immediately
198 # to events immediately
199
199
200 # double nested try/except, to properly catch KeyboardInterrupt
200 # double nested try/except, to properly catch KeyboardInterrupt
201 # due to pyzmq Issue #130
201 # due to pyzmq Issue #130
202 try:
202 try:
203 poller.poll(10*1000*self._poll_interval)
203 poller.poll(10*1000*self._poll_interval)
204 # restore raising of KeyboardInterrupt
204 # restore raising of KeyboardInterrupt
205 signal(SIGINT, default_int_handler)
205 signal(SIGINT, default_int_handler)
206 self.do_one_iteration()
206 self.do_one_iteration()
207 except:
207 except:
208 raise
208 raise
209 finally:
209 finally:
210 # prevent raising of KeyboardInterrupt
210 # prevent raising of KeyboardInterrupt
211 signal(SIGINT,SIG_IGN)
211 signal(SIGINT,SIG_IGN)
212 except KeyboardInterrupt:
212 except KeyboardInterrupt:
213 # Ctrl-C shouldn't crash the kernel
213 # Ctrl-C shouldn't crash the kernel
214 io.raw_print("KeyboardInterrupt caught in kernel")
214 io.raw_print("KeyboardInterrupt caught in kernel")
215 # stop ignoring sigint, now that we are out of our own loop,
215 # stop ignoring sigint, now that we are out of our own loop,
216 # we don't want to prevent future code from handling it
216 # we don't want to prevent future code from handling it
217 signal(SIGINT, default_int_handler)
217 signal(SIGINT, default_int_handler)
218 while self.eventloop is not None:
218 while self.eventloop is not None:
219 try:
219 try:
220 self.eventloop(self)
220 self.eventloop(self)
221 except KeyboardInterrupt:
221 except KeyboardInterrupt:
222 # Ctrl-C shouldn't crash the kernel
222 # Ctrl-C shouldn't crash the kernel
223 io.raw_print("KeyboardInterrupt caught in kernel")
223 io.raw_print("KeyboardInterrupt caught in kernel")
224 continue
224 continue
225 else:
225 else:
226 # eventloop exited cleanly, this means we should stop (right?)
226 # eventloop exited cleanly, this means we should stop (right?)
227 self.eventloop = None
227 self.eventloop = None
228 break
228 break
229
229
230
230
231 def record_ports(self, ports):
231 def record_ports(self, ports):
232 """Record the ports that this kernel is using.
232 """Record the ports that this kernel is using.
233
233
234 The creator of the Kernel instance must call this methods if they
234 The creator of the Kernel instance must call this methods if they
235 want the :meth:`connect_request` method to return the port numbers.
235 want the :meth:`connect_request` method to return the port numbers.
236 """
236 """
237 self._recorded_ports = ports
237 self._recorded_ports = ports
238
238
239 #---------------------------------------------------------------------------
239 #---------------------------------------------------------------------------
240 # Kernel request handlers
240 # Kernel request handlers
241 #---------------------------------------------------------------------------
241 #---------------------------------------------------------------------------
242
242
243 def _publish_pyin(self, code, parent, execution_count):
243 def _publish_pyin(self, code, parent, execution_count):
244 """Publish the code request on the pyin stream."""
244 """Publish the code request on the pyin stream."""
245
245
246 self.session.send(self.iopub_socket, u'pyin', {u'code':code,
246 self.session.send(self.iopub_socket, u'pyin', {u'code':code,
247 u'execution_count': execution_count}, parent=parent)
247 u'execution_count': execution_count}, parent=parent)
248
248
249 def execute_request(self, ident, parent):
249 def execute_request(self, ident, parent):
250
250
251 self.session.send(self.iopub_socket,
251 self.session.send(self.iopub_socket,
252 u'status',
252 u'status',
253 {u'execution_state':u'busy'},
253 {u'execution_state':u'busy'},
254 parent=parent )
254 parent=parent )
255
255
256 try:
256 try:
257 content = parent[u'content']
257 content = parent[u'content']
258 code = content[u'code']
258 code = content[u'code']
259 silent = content[u'silent']
259 silent = content[u'silent']
260 except:
260 except:
261 self.log.error("Got bad msg: ")
261 self.log.error("Got bad msg: ")
262 self.log.error(str(Message(parent)))
262 self.log.error(str(Message(parent)))
263 return
263 return
264
264
265 shell = self.shell # we'll need this a lot here
265 shell = self.shell # we'll need this a lot here
266
266
267 # Replace raw_input. Note that is not sufficient to replace
267 # Replace raw_input. Note that is not sufficient to replace
268 # raw_input in the user namespace.
268 # raw_input in the user namespace.
269 if content.get('allow_stdin', False):
269 if content.get('allow_stdin', False):
270 raw_input = lambda prompt='': self._raw_input(prompt, ident, parent)
270 raw_input = lambda prompt='': self._raw_input(prompt, ident, parent)
271 else:
271 else:
272 raw_input = lambda prompt='' : self._no_raw_input()
272 raw_input = lambda prompt='' : self._no_raw_input()
273
273
274 if py3compat.PY3:
274 if py3compat.PY3:
275 __builtin__.input = raw_input
275 __builtin__.input = raw_input
276 else:
276 else:
277 __builtin__.raw_input = raw_input
277 __builtin__.raw_input = raw_input
278
278
279 # Set the parent message of the display hook and out streams.
279 # Set the parent message of the display hook and out streams.
280 shell.displayhook.set_parent(parent)
280 shell.displayhook.set_parent(parent)
281 shell.display_pub.set_parent(parent)
281 shell.display_pub.set_parent(parent)
282 sys.stdout.set_parent(parent)
282 sys.stdout.set_parent(parent)
283 sys.stderr.set_parent(parent)
283 sys.stderr.set_parent(parent)
284
284
285 # Re-broadcast our input for the benefit of listening clients, and
285 # Re-broadcast our input for the benefit of listening clients, and
286 # start computing output
286 # start computing output
287 if not silent:
287 if not silent:
288 self._publish_pyin(code, parent, shell.execution_count)
288 self._publish_pyin(code, parent, shell.execution_count)
289
289
290 reply_content = {}
290 reply_content = {}
291 try:
291 try:
292 if silent:
292 if silent:
293 # run_code uses 'exec' mode, so no displayhook will fire, and it
293 # run_code uses 'exec' mode, so no displayhook will fire, and it
294 # doesn't call logging or history manipulations. Print
294 # doesn't call logging or history manipulations. Print
295 # statements in that code will obviously still execute.
295 # statements in that code will obviously still execute.
296 shell.run_code(code)
296 shell.run_code(code)
297 else:
297 else:
298 # FIXME: the shell calls the exception handler itself.
298 # FIXME: the shell calls the exception handler itself.
299 shell.run_cell(code, store_history=True)
299 shell.run_cell(code, store_history=True)
300 except:
300 except:
301 status = u'error'
301 status = u'error'
302 # FIXME: this code right now isn't being used yet by default,
302 # FIXME: this code right now isn't being used yet by default,
303 # because the run_cell() call above directly fires off exception
303 # because the run_cell() call above directly fires off exception
304 # reporting. This code, therefore, is only active in the scenario
304 # reporting. This code, therefore, is only active in the scenario
305 # where runlines itself has an unhandled exception. We need to
305 # where runlines itself has an unhandled exception. We need to
306 # uniformize this, for all exception construction to come from a
306 # uniformize this, for all exception construction to come from a
307 # single location in the codbase.
307 # single location in the codbase.
308 etype, evalue, tb = sys.exc_info()
308 etype, evalue, tb = sys.exc_info()
309 tb_list = traceback.format_exception(etype, evalue, tb)
309 tb_list = traceback.format_exception(etype, evalue, tb)
310 reply_content.update(shell._showtraceback(etype, evalue, tb_list))
310 reply_content.update(shell._showtraceback(etype, evalue, tb_list))
311 else:
311 else:
312 status = u'ok'
312 status = u'ok'
313
313
314 reply_content[u'status'] = status
314 reply_content[u'status'] = status
315
315
316 # Return the execution counter so clients can display prompts
316 # Return the execution counter so clients can display prompts
317 reply_content['execution_count'] = shell.execution_count -1
317 reply_content['execution_count'] = shell.execution_count -1
318
318
319 # FIXME - fish exception info out of shell, possibly left there by
319 # FIXME - fish exception info out of shell, possibly left there by
320 # runlines. We'll need to clean up this logic later.
320 # runlines. We'll need to clean up this logic later.
321 if shell._reply_content is not None:
321 if shell._reply_content is not None:
322 reply_content.update(shell._reply_content)
322 reply_content.update(shell._reply_content)
323 # reset after use
323 # reset after use
324 shell._reply_content = None
324 shell._reply_content = None
325
325
326 # At this point, we can tell whether the main code execution succeeded
326 # At this point, we can tell whether the main code execution succeeded
327 # or not. If it did, we proceed to evaluate user_variables/expressions
327 # or not. If it did, we proceed to evaluate user_variables/expressions
328 if reply_content['status'] == 'ok':
328 if reply_content['status'] == 'ok':
329 reply_content[u'user_variables'] = \
329 reply_content[u'user_variables'] = \
330 shell.user_variables(content[u'user_variables'])
330 shell.user_variables(content[u'user_variables'])
331 reply_content[u'user_expressions'] = \
331 reply_content[u'user_expressions'] = \
332 shell.user_expressions(content[u'user_expressions'])
332 shell.user_expressions(content[u'user_expressions'])
333 else:
333 else:
334 # If there was an error, don't even try to compute variables or
334 # If there was an error, don't even try to compute variables or
335 # expressions
335 # expressions
336 reply_content[u'user_variables'] = {}
336 reply_content[u'user_variables'] = {}
337 reply_content[u'user_expressions'] = {}
337 reply_content[u'user_expressions'] = {}
338
338
339 # Payloads should be retrieved regardless of outcome, so we can both
339 # Payloads should be retrieved regardless of outcome, so we can both
340 # recover partial output (that could have been generated early in a
340 # recover partial output (that could have been generated early in a
341 # block, before an error) and clear the payload system always.
341 # block, before an error) and clear the payload system always.
342 reply_content[u'payload'] = shell.payload_manager.read_payload()
342 reply_content[u'payload'] = shell.payload_manager.read_payload()
343 # Be agressive about clearing the payload because we don't want
343 # Be agressive about clearing the payload because we don't want
344 # it to sit in memory until the next execute_request comes in.
344 # it to sit in memory until the next execute_request comes in.
345 shell.payload_manager.clear_payload()
345 shell.payload_manager.clear_payload()
346
346
347 # Flush output before sending the reply.
347 # Flush output before sending the reply.
348 sys.stdout.flush()
348 sys.stdout.flush()
349 sys.stderr.flush()
349 sys.stderr.flush()
350 # FIXME: on rare occasions, the flush doesn't seem to make it to the
350 # FIXME: on rare occasions, the flush doesn't seem to make it to the
351 # clients... This seems to mitigate the problem, but we definitely need
351 # clients... This seems to mitigate the problem, but we definitely need
352 # to better understand what's going on.
352 # to better understand what's going on.
353 if self._execute_sleep:
353 if self._execute_sleep:
354 time.sleep(self._execute_sleep)
354 time.sleep(self._execute_sleep)
355
355
356 # Send the reply.
356 # Send the reply.
357 reply_content = json_clean(reply_content)
357 reply_content = json_clean(reply_content)
358 reply_msg = self.session.send(self.shell_socket, u'execute_reply',
358 reply_msg = self.session.send(self.shell_socket, u'execute_reply',
359 reply_content, parent, ident=ident)
359 reply_content, parent, ident=ident)
360 self.log.debug(str(reply_msg))
360 self.log.debug(str(reply_msg))
361
361
362 if reply_msg['content']['status'] == u'error':
362 if reply_msg['content']['status'] == u'error':
363 self._abort_queue()
363 self._abort_queue()
364
364
365 self.session.send(self.iopub_socket,
365 self.session.send(self.iopub_socket,
366 u'status',
366 u'status',
367 {u'execution_state':u'idle'},
367 {u'execution_state':u'idle'},
368 parent=parent )
368 parent=parent )
369
369
370 def complete_request(self, ident, parent):
370 def complete_request(self, ident, parent):
371 txt, matches = self._complete(parent)
371 txt, matches = self._complete(parent)
372 matches = {'matches' : matches,
372 matches = {'matches' : matches,
373 'matched_text' : txt,
373 'matched_text' : txt,
374 'status' : 'ok'}
374 'status' : 'ok'}
375 matches = json_clean(matches)
375 matches = json_clean(matches)
376 completion_msg = self.session.send(self.shell_socket, 'complete_reply',
376 completion_msg = self.session.send(self.shell_socket, 'complete_reply',
377 matches, parent, ident)
377 matches, parent, ident)
378 self.log.debug(str(completion_msg))
378 self.log.debug(str(completion_msg))
379
379
380 def object_info_request(self, ident, parent):
380 def object_info_request(self, ident, parent):
381 content = parent['content']
381 content = parent['content']
382 object_info = self.shell.object_inspect(content['oname'],
382 object_info = self.shell.object_inspect(content['oname'],
383 detail_level = content.get('detail_level', 0)
383 detail_level = content.get('detail_level', 0)
384 )
384 )
385 # Before we send this object over, we scrub it for JSON usage
385 # Before we send this object over, we scrub it for JSON usage
386 oinfo = json_clean(object_info)
386 oinfo = json_clean(object_info)
387 msg = self.session.send(self.shell_socket, 'object_info_reply',
387 msg = self.session.send(self.shell_socket, 'object_info_reply',
388 oinfo, parent, ident)
388 oinfo, parent, ident)
389 self.log.debug(msg)
389 self.log.debug(msg)
390
390
391 def history_request(self, ident, parent):
391 def history_request(self, ident, parent):
392 # We need to pull these out, as passing **kwargs doesn't work with
392 # We need to pull these out, as passing **kwargs doesn't work with
393 # unicode keys before Python 2.6.5.
393 # unicode keys before Python 2.6.5.
394 hist_access_type = parent['content']['hist_access_type']
394 hist_access_type = parent['content']['hist_access_type']
395 raw = parent['content']['raw']
395 raw = parent['content']['raw']
396 output = parent['content']['output']
396 output = parent['content']['output']
397 if hist_access_type == 'tail':
397 if hist_access_type == 'tail':
398 n = parent['content']['n']
398 n = parent['content']['n']
399 hist = self.shell.history_manager.get_tail(n, raw=raw, output=output,
399 hist = self.shell.history_manager.get_tail(n, raw=raw, output=output,
400 include_latest=True)
400 include_latest=True)
401
401
402 elif hist_access_type == 'range':
402 elif hist_access_type == 'range':
403 session = parent['content']['session']
403 session = parent['content']['session']
404 start = parent['content']['start']
404 start = parent['content']['start']
405 stop = parent['content']['stop']
405 stop = parent['content']['stop']
406 hist = self.shell.history_manager.get_range(session, start, stop,
406 hist = self.shell.history_manager.get_range(session, start, stop,
407 raw=raw, output=output)
407 raw=raw, output=output)
408
408
409 elif hist_access_type == 'search':
409 elif hist_access_type == 'search':
410 pattern = parent['content']['pattern']
410 pattern = parent['content']['pattern']
411 hist = self.shell.history_manager.search(pattern, raw=raw,
411 hist = self.shell.history_manager.search(pattern, raw=raw,
412 output=output)
412 output=output)
413
413
414 else:
414 else:
415 hist = []
415 hist = []
416 hist = list(hist)
416 hist = list(hist)
417 content = {'history' : hist}
417 content = {'history' : hist}
418 content = json_clean(content)
418 content = json_clean(content)
419 msg = self.session.send(self.shell_socket, 'history_reply',
419 msg = self.session.send(self.shell_socket, 'history_reply',
420 content, parent, ident)
420 content, parent, ident)
421 self.log.debug("Sending history reply with %i entries", len(hist))
421 self.log.debug("Sending history reply with %i entries", len(hist))
422
422
423 def connect_request(self, ident, parent):
423 def connect_request(self, ident, parent):
424 if self._recorded_ports is not None:
424 if self._recorded_ports is not None:
425 content = self._recorded_ports.copy()
425 content = self._recorded_ports.copy()
426 else:
426 else:
427 content = {}
427 content = {}
428 msg = self.session.send(self.shell_socket, 'connect_reply',
428 msg = self.session.send(self.shell_socket, 'connect_reply',
429 content, parent, ident)
429 content, parent, ident)
430 self.log.debug(msg)
430 self.log.debug(msg)
431
431
432 def shutdown_request(self, ident, parent):
432 def shutdown_request(self, ident, parent):
433 self.shell.exit_now = True
433 self.shell.exit_now = True
434 self._shutdown_message = self.session.msg(u'shutdown_reply',
434 self._shutdown_message = self.session.msg(u'shutdown_reply',
435 parent['content'], parent)
435 parent['content'], parent)
436 sys.exit(0)
436 sys.exit(0)
437
437
438 #---------------------------------------------------------------------------
438 #---------------------------------------------------------------------------
439 # Protected interface
439 # Protected interface
440 #---------------------------------------------------------------------------
440 #---------------------------------------------------------------------------
441
441
442 def _abort_queue(self):
442 def _abort_queue(self):
443 while True:
443 while True:
444 try:
444 try:
445 ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
445 ident,msg = self.session.recv(self.shell_socket, zmq.NOBLOCK)
446 except Exception:
446 except Exception:
447 self.log.warn("Invalid Message:", exc_info=True)
447 self.log.warn("Invalid Message:", exc_info=True)
448 continue
448 continue
449 if msg is None:
449 if msg is None:
450 break
450 break
451 else:
451 else:
452 assert ident is not None, \
452 assert ident is not None, \
453 "Unexpected missing message part."
453 "Unexpected missing message part."
454
454
455 self.log.debug("Aborting:\n"+str(Message(msg)))
455 self.log.debug("Aborting:\n"+str(Message(msg)))
456 msg_type = msg['header']['msg_type']
456 msg_type = msg['header']['msg_type']
457 reply_type = msg_type.split('_')[0] + '_reply'
457 reply_type = msg_type.split('_')[0] + '_reply'
458 reply_msg = self.session.send(self.shell_socket, reply_type,
458 reply_msg = self.session.send(self.shell_socket, reply_type,
459 {'status' : 'aborted'}, msg, ident=ident)
459 {'status' : 'aborted'}, msg, ident=ident)
460 self.log.debug(reply_msg)
460 self.log.debug(reply_msg)
461 # We need to wait a bit for requests to come in. This can probably
461 # We need to wait a bit for requests to come in. This can probably
462 # be set shorter for true asynchronous clients.
462 # be set shorter for true asynchronous clients.
463 time.sleep(0.1)
463 time.sleep(0.1)
464
464
465 def _no_raw_input(self):
465 def _no_raw_input(self):
466 """Raise StdinNotImplentedError if active frontend doesn't support
466 """Raise StdinNotImplentedError if active frontend doesn't support
467 stdin."""
467 stdin."""
468 raise StdinNotImplementedError("raw_input was called, but this "
468 raise StdinNotImplementedError("raw_input was called, but this "
469 "frontend does not support stdin.")
469 "frontend does not support stdin.")
470
470
471 def _raw_input(self, prompt, ident, parent):
471 def _raw_input(self, prompt, ident, parent):
472 # Flush output before making the request.
472 # Flush output before making the request.
473 sys.stderr.flush()
473 sys.stderr.flush()
474 sys.stdout.flush()
474 sys.stdout.flush()
475
475
476 # Send the input request.
476 # Send the input request.
477 content = json_clean(dict(prompt=prompt))
477 content = json_clean(dict(prompt=prompt))
478 self.session.send(self.stdin_socket, u'input_request', content, parent,
478 self.session.send(self.stdin_socket, u'input_request', content, parent,
479 ident=ident)
479 ident=ident)
480
480
481 # Await a response.
481 # Await a response.
482 while True:
482 while True:
483 try:
483 try:
484 ident, reply = self.session.recv(self.stdin_socket, 0)
484 ident, reply = self.session.recv(self.stdin_socket, 0)
485 except Exception:
485 except Exception:
486 self.log.warn("Invalid Message:", exc_info=True)
486 self.log.warn("Invalid Message:", exc_info=True)
487 else:
487 else:
488 break
488 break
489 try:
489 try:
490 value = reply['content']['value']
490 value = reply['content']['value']
491 except:
491 except:
492 self.log.error("Got bad raw_input reply: ")
492 self.log.error("Got bad raw_input reply: ")
493 self.log.error(str(Message(parent)))
493 self.log.error(str(Message(parent)))
494 value = ''
494 value = ''
495 if value == '\x04':
495 if value == '\x04':
496 # EOF
496 # EOF
497 raise EOFError
497 raise EOFError
498 return value
498 return value
499
499
500 def _complete(self, msg):
500 def _complete(self, msg):
501 c = msg['content']
501 c = msg['content']
502 try:
502 try:
503 cpos = int(c['cursor_pos'])
503 cpos = int(c['cursor_pos'])
504 except:
504 except:
505 # If we don't get something that we can convert to an integer, at
505 # If we don't get something that we can convert to an integer, at
506 # least attempt the completion guessing the cursor is at the end of
506 # least attempt the completion guessing the cursor is at the end of
507 # the text, if there's any, and otherwise of the line
507 # the text, if there's any, and otherwise of the line
508 cpos = len(c['text'])
508 cpos = len(c['text'])
509 if cpos==0:
509 if cpos==0:
510 cpos = len(c['line'])
510 cpos = len(c['line'])
511 return self.shell.complete(c['text'], c['line'], cpos)
511 return self.shell.complete(c['text'], c['line'], cpos)
512
512
513 def _object_info(self, context):
513 def _object_info(self, context):
514 symbol, leftover = self._symbol_from_context(context)
514 symbol, leftover = self._symbol_from_context(context)
515 if symbol is not None and not leftover:
515 if symbol is not None and not leftover:
516 doc = getattr(symbol, '__doc__', '')
516 doc = getattr(symbol, '__doc__', '')
517 else:
517 else:
518 doc = ''
518 doc = ''
519 object_info = dict(docstring = doc)
519 object_info = dict(docstring = doc)
520 return object_info
520 return object_info
521
521
522 def _symbol_from_context(self, context):
522 def _symbol_from_context(self, context):
523 if not context:
523 if not context:
524 return None, context
524 return None, context
525
525
526 base_symbol_string = context[0]
526 base_symbol_string = context[0]
527 symbol = self.shell.user_ns.get(base_symbol_string, None)
527 symbol = self.shell.user_ns.get(base_symbol_string, None)
528 if symbol is None:
528 if symbol is None:
529 symbol = __builtin__.__dict__.get(base_symbol_string, None)
529 symbol = __builtin__.__dict__.get(base_symbol_string, None)
530 if symbol is None:
530 if symbol is None:
531 return None, context
531 return None, context
532
532
533 context = context[1:]
533 context = context[1:]
534 for i, name in enumerate(context):
534 for i, name in enumerate(context):
535 new_symbol = getattr(symbol, name, None)
535 new_symbol = getattr(symbol, name, None)
536 if new_symbol is None:
536 if new_symbol is None:
537 return symbol, context[i:]
537 return symbol, context[i:]
538 else:
538 else:
539 symbol = new_symbol
539 symbol = new_symbol
540
540
541 return symbol, []
541 return symbol, []
542
542
543 def _at_shutdown(self):
543 def _at_shutdown(self):
544 """Actions taken at shutdown by the kernel, called by python's atexit.
544 """Actions taken at shutdown by the kernel, called by python's atexit.
545 """
545 """
546 # io.rprint("Kernel at_shutdown") # dbg
546 # io.rprint("Kernel at_shutdown") # dbg
547 if self._shutdown_message is not None:
547 if self._shutdown_message is not None:
548 self.session.send(self.shell_socket, self._shutdown_message)
548 self.session.send(self.shell_socket, self._shutdown_message)
549 self.session.send(self.iopub_socket, self._shutdown_message)
549 self.session.send(self.iopub_socket, self._shutdown_message)
550 self.log.debug(str(self._shutdown_message))
550 self.log.debug(str(self._shutdown_message))
551 # A very short sleep to give zmq time to flush its message buffers
551 # A very short sleep to give zmq time to flush its message buffers
552 # before Python truly shuts down.
552 # before Python truly shuts down.
553 time.sleep(0.01)
553 time.sleep(0.01)
554
554
555 #-----------------------------------------------------------------------------
555 #-----------------------------------------------------------------------------
556 # Aliases and Flags for the IPKernelApp
556 # Aliases and Flags for the IPKernelApp
557 #-----------------------------------------------------------------------------
557 #-----------------------------------------------------------------------------
558
558
559 flags = dict(kernel_flags)
559 flags = dict(kernel_flags)
560 flags.update(shell_flags)
560 flags.update(shell_flags)
561
561
562 addflag = lambda *args: flags.update(boolean_flag(*args))
562 addflag = lambda *args: flags.update(boolean_flag(*args))
563
563
564 flags['pylab'] = (
564 flags['pylab'] = (
565 {'IPKernelApp' : {'pylab' : 'auto'}},
565 {'IPKernelApp' : {'pylab' : 'auto'}},
566 """Pre-load matplotlib and numpy for interactive use with
566 """Pre-load matplotlib and numpy for interactive use with
567 the default matplotlib backend."""
567 the default matplotlib backend."""
568 )
568 )
569
569
570 aliases = dict(kernel_aliases)
570 aliases = dict(kernel_aliases)
571 aliases.update(shell_aliases)
571 aliases.update(shell_aliases)
572
572
573 # it's possible we don't want short aliases for *all* of these:
573 # it's possible we don't want short aliases for *all* of these:
574 aliases.update(dict(
574 aliases.update(dict(
575 pylab='IPKernelApp.pylab',
575 pylab='IPKernelApp.pylab',
576 ))
576 ))
577
577
578 #-----------------------------------------------------------------------------
578 #-----------------------------------------------------------------------------
579 # The IPKernelApp class
579 # The IPKernelApp class
580 #-----------------------------------------------------------------------------
580 #-----------------------------------------------------------------------------
581
581
582 class IPKernelApp(KernelApp, InteractiveShellApp):
582 class IPKernelApp(KernelApp, InteractiveShellApp):
583 name = 'ipkernel'
583 name = 'ipkernel'
584
584
585 aliases = Dict(aliases)
585 aliases = Dict(aliases)
586 flags = Dict(flags)
586 flags = Dict(flags)
587 classes = [Kernel, ZMQInteractiveShell, ProfileDir, Session]
587 classes = [Kernel, ZMQInteractiveShell, ProfileDir, Session]
588
588
589 # configurables
589 # configurables
590 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'inline', 'auto'],
590 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'inline', 'auto'],
591 config=True,
591 config=True,
592 help="""Pre-load matplotlib and numpy for interactive use,
592 help="""Pre-load matplotlib and numpy for interactive use,
593 selecting a particular matplotlib backend and loop integration.
593 selecting a particular matplotlib backend and loop integration.
594 """
594 """
595 )
595 )
596
596
597 @catch_config_error
597 @catch_config_error
598 def initialize(self, argv=None):
598 def initialize(self, argv=None):
599 super(IPKernelApp, self).initialize(argv)
599 super(IPKernelApp, self).initialize(argv)
600 self.init_path()
600 self.init_shell()
601 self.init_shell()
601 self.init_extensions()
602 self.init_extensions()
602 self.init_code()
603 self.init_code()
603
604
604 def init_kernel(self):
605 def init_kernel(self):
605
606
606 kernel = Kernel(config=self.config, session=self.session,
607 kernel = Kernel(config=self.config, session=self.session,
607 shell_socket=self.shell_socket,
608 shell_socket=self.shell_socket,
608 iopub_socket=self.iopub_socket,
609 iopub_socket=self.iopub_socket,
609 stdin_socket=self.stdin_socket,
610 stdin_socket=self.stdin_socket,
610 log=self.log,
611 log=self.log,
611 profile_dir=self.profile_dir,
612 profile_dir=self.profile_dir,
612 )
613 )
613 self.kernel = kernel
614 self.kernel = kernel
614 kernel.record_ports(self.ports)
615 kernel.record_ports(self.ports)
615 shell = kernel.shell
616 shell = kernel.shell
616 if self.pylab:
617 if self.pylab:
617 try:
618 try:
618 gui, backend = pylabtools.find_gui_and_backend(self.pylab)
619 gui, backend = pylabtools.find_gui_and_backend(self.pylab)
619 shell.enable_pylab(gui, import_all=self.pylab_import_all)
620 shell.enable_pylab(gui, import_all=self.pylab_import_all)
620 except Exception:
621 except Exception:
621 self.log.error("Pylab initialization failed", exc_info=True)
622 self.log.error("Pylab initialization failed", exc_info=True)
622 # print exception straight to stdout, because normally
623 # print exception straight to stdout, because normally
623 # _showtraceback associates the reply with an execution,
624 # _showtraceback associates the reply with an execution,
624 # which means frontends will never draw it, as this exception
625 # which means frontends will never draw it, as this exception
625 # is not associated with any execute request.
626 # is not associated with any execute request.
626
627
627 # replace pyerr-sending traceback with stdout
628 # replace pyerr-sending traceback with stdout
628 _showtraceback = shell._showtraceback
629 _showtraceback = shell._showtraceback
629 def print_tb(etype, evalue, stb):
630 def print_tb(etype, evalue, stb):
630 print ("Error initializing pylab, pylab mode will not "
631 print ("Error initializing pylab, pylab mode will not "
631 "be active", file=io.stderr)
632 "be active", file=io.stderr)
632 print (shell.InteractiveTB.stb2text(stb), file=io.stdout)
633 print (shell.InteractiveTB.stb2text(stb), file=io.stdout)
633 shell._showtraceback = print_tb
634 shell._showtraceback = print_tb
634
635
635 # send the traceback over stdout
636 # send the traceback over stdout
636 shell.showtraceback(tb_offset=0)
637 shell.showtraceback(tb_offset=0)
637
638
638 # restore proper _showtraceback method
639 # restore proper _showtraceback method
639 shell._showtraceback = _showtraceback
640 shell._showtraceback = _showtraceback
640
641
641
642
642 def init_shell(self):
643 def init_shell(self):
643 # I am a little hesitant to put these into InteractiveShell itself.
644 # But that might be the place for them
645 sys.path.insert(0, '')
646
647 self.shell = self.kernel.shell
644 self.shell = self.kernel.shell
648 self.shell.configurables.append(self)
645 self.shell.configurables.append(self)
649
646
650
647
651 #-----------------------------------------------------------------------------
648 #-----------------------------------------------------------------------------
652 # Kernel main and launch functions
649 # Kernel main and launch functions
653 #-----------------------------------------------------------------------------
650 #-----------------------------------------------------------------------------
654
651
655 def launch_kernel(*args, **kwargs):
652 def launch_kernel(*args, **kwargs):
656 """Launches a localhost IPython kernel, binding to the specified ports.
653 """Launches a localhost IPython kernel, binding to the specified ports.
657
654
658 This function simply calls entry_point.base_launch_kernel with the right
655 This function simply calls entry_point.base_launch_kernel with the right
659 first command to start an ipkernel. See base_launch_kernel for arguments.
656 first command to start an ipkernel. See base_launch_kernel for arguments.
660
657
661 Returns
658 Returns
662 -------
659 -------
663 A tuple of form:
660 A tuple of form:
664 (kernel_process, shell_port, iopub_port, stdin_port, hb_port)
661 (kernel_process, shell_port, iopub_port, stdin_port, hb_port)
665 where kernel_process is a Popen object and the ports are integers.
662 where kernel_process is a Popen object and the ports are integers.
666 """
663 """
667 return base_launch_kernel('from IPython.zmq.ipkernel import main; main()',
664 return base_launch_kernel('from IPython.zmq.ipkernel import main; main()',
668 *args, **kwargs)
665 *args, **kwargs)
669
666
670
667
671 def embed_kernel(module=None, local_ns=None, **kwargs):
668 def embed_kernel(module=None, local_ns=None, **kwargs):
672 """Embed and start an IPython kernel in a given scope.
669 """Embed and start an IPython kernel in a given scope.
673
670
674 Parameters
671 Parameters
675 ----------
672 ----------
676 module : ModuleType, optional
673 module : ModuleType, optional
677 The module to load into IPython globals (default: caller)
674 The module to load into IPython globals (default: caller)
678 local_ns : dict, optional
675 local_ns : dict, optional
679 The namespace to load into IPython user namespace (default: caller)
676 The namespace to load into IPython user namespace (default: caller)
680
677
681 kwargs : various, optional
678 kwargs : various, optional
682 Further keyword args are relayed to the KernelApp constructor,
679 Further keyword args are relayed to the KernelApp constructor,
683 allowing configuration of the Kernel. Will only have an effect
680 allowing configuration of the Kernel. Will only have an effect
684 on the first embed_kernel call for a given process.
681 on the first embed_kernel call for a given process.
685
682
686 """
683 """
687 # get the app if it exists, or set it up if it doesn't
684 # get the app if it exists, or set it up if it doesn't
688 if IPKernelApp.initialized():
685 if IPKernelApp.initialized():
689 app = IPKernelApp.instance()
686 app = IPKernelApp.instance()
690 else:
687 else:
691 app = IPKernelApp.instance(**kwargs)
688 app = IPKernelApp.instance(**kwargs)
692 app.initialize([])
689 app.initialize([])
693
690
694 # load the calling scope if not given
691 # load the calling scope if not given
695 (caller_module, caller_locals) = extract_module_locals(1)
692 (caller_module, caller_locals) = extract_module_locals(1)
696 if module is None:
693 if module is None:
697 module = caller_module
694 module = caller_module
698 if local_ns is None:
695 if local_ns is None:
699 local_ns = caller_locals
696 local_ns = caller_locals
700
697
701 app.kernel.user_module = module
698 app.kernel.user_module = module
702 app.kernel.user_ns = local_ns
699 app.kernel.user_ns = local_ns
703 app.start()
700 app.start()
704
701
705 def main():
702 def main():
706 """Run an IPKernel as an application"""
703 """Run an IPKernel as an application"""
707 app = IPKernelApp.instance()
704 app = IPKernelApp.instance()
708 app.initialize()
705 app.initialize()
709 app.start()
706 app.start()
710
707
711
708
712 if __name__ == '__main__':
709 if __name__ == '__main__':
713 main()
710 main()
General Comments 0
You need to be logged in to leave comments. Login now