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