##// END OF EJS Templates
explicit allow_none
Sylvain Corlay -
Show More
@@ -1,437 +1,437
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 from __future__ import print_function
24 from __future__ import print_function
25
25
26 import glob
26 import glob
27 import os
27 import os
28 import sys
28 import sys
29
29
30 from IPython.config.application import boolean_flag
30 from IPython.config.application import boolean_flag
31 from IPython.config.configurable import Configurable
31 from IPython.config.configurable import Configurable
32 from IPython.config.loader import Config
32 from IPython.config.loader import Config
33 from IPython.core import pylabtools
33 from IPython.core import pylabtools
34 from IPython.utils import py3compat
34 from IPython.utils import py3compat
35 from IPython.utils.contexts import preserve_keys
35 from IPython.utils.contexts import preserve_keys
36 from IPython.utils.path import filefind
36 from IPython.utils.path import filefind
37 from IPython.utils.traitlets import (
37 from IPython.utils.traitlets import (
38 Unicode, Instance, List, Bool, CaselessStrEnum
38 Unicode, Instance, List, Bool, CaselessStrEnum
39 )
39 )
40 from IPython.lib.inputhook import guis
40 from IPython.lib.inputhook import guis
41
41
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43 # Aliases and Flags
43 # Aliases and Flags
44 #-----------------------------------------------------------------------------
44 #-----------------------------------------------------------------------------
45
45
46 gui_keys = tuple(sorted([ key for key in guis if key is not None ]))
46 gui_keys = tuple(sorted([ key for key in guis if key is not None ]))
47
47
48 backend_keys = sorted(pylabtools.backends.keys())
48 backend_keys = sorted(pylabtools.backends.keys())
49 backend_keys.insert(0, 'auto')
49 backend_keys.insert(0, 'auto')
50
50
51 shell_flags = {}
51 shell_flags = {}
52
52
53 addflag = lambda *args: shell_flags.update(boolean_flag(*args))
53 addflag = lambda *args: shell_flags.update(boolean_flag(*args))
54 addflag('autoindent', 'InteractiveShell.autoindent',
54 addflag('autoindent', 'InteractiveShell.autoindent',
55 'Turn on autoindenting.', 'Turn off autoindenting.'
55 'Turn on autoindenting.', 'Turn off autoindenting.'
56 )
56 )
57 addflag('automagic', 'InteractiveShell.automagic',
57 addflag('automagic', 'InteractiveShell.automagic',
58 """Turn on the auto calling of magic commands. Type %%magic at the
58 """Turn on the auto calling of magic commands. Type %%magic at the
59 IPython prompt for more information.""",
59 IPython prompt for more information.""",
60 'Turn off the auto calling of magic commands.'
60 'Turn off the auto calling of magic commands.'
61 )
61 )
62 addflag('pdb', 'InteractiveShell.pdb',
62 addflag('pdb', 'InteractiveShell.pdb',
63 "Enable auto calling the pdb debugger after every exception.",
63 "Enable auto calling the pdb debugger after every exception.",
64 "Disable auto calling the pdb debugger after every exception."
64 "Disable auto calling the pdb debugger after every exception."
65 )
65 )
66 # pydb flag doesn't do any config, as core.debugger switches on import,
66 # pydb flag doesn't do any config, as core.debugger switches on import,
67 # which is before parsing. This just allows the flag to be passed.
67 # which is before parsing. This just allows the flag to be passed.
68 shell_flags.update(dict(
68 shell_flags.update(dict(
69 pydb = ({},
69 pydb = ({},
70 """Use the third party 'pydb' package as debugger, instead of pdb.
70 """Use the third party 'pydb' package as debugger, instead of pdb.
71 Requires that pydb is installed."""
71 Requires that pydb is installed."""
72 )
72 )
73 ))
73 ))
74 addflag('pprint', 'PlainTextFormatter.pprint',
74 addflag('pprint', 'PlainTextFormatter.pprint',
75 "Enable auto pretty printing of results.",
75 "Enable auto pretty printing of results.",
76 "Disable auto pretty printing of results."
76 "Disable auto pretty printing of results."
77 )
77 )
78 addflag('color-info', 'InteractiveShell.color_info',
78 addflag('color-info', 'InteractiveShell.color_info',
79 """IPython can display information about objects via a set of functions,
79 """IPython can display information about objects via a set of functions,
80 and optionally can use colors for this, syntax highlighting
80 and optionally can use colors for this, syntax highlighting
81 source code and various other elements. This is on by default, but can cause
81 source code and various other elements. This is on by default, but can cause
82 problems with some pagers. If you see such problems, you can disable the
82 problems with some pagers. If you see such problems, you can disable the
83 colours.""",
83 colours.""",
84 "Disable using colors for info related things."
84 "Disable using colors for info related things."
85 )
85 )
86 addflag('deep-reload', 'InteractiveShell.deep_reload',
86 addflag('deep-reload', 'InteractiveShell.deep_reload',
87 """Enable deep (recursive) reloading by default. IPython can use the
87 """Enable deep (recursive) reloading by default. IPython can use the
88 deep_reload module which reloads changes in modules recursively (it
88 deep_reload module which reloads changes in modules recursively (it
89 replaces the reload() function, so you don't need to change anything to
89 replaces the reload() function, so you don't need to change anything to
90 use it). deep_reload() forces a full reload of modules whose code may
90 use it). deep_reload() forces a full reload of modules whose code may
91 have changed, which the default reload() function does not. When
91 have changed, which the default reload() function does not. When
92 deep_reload is off, IPython will use the normal reload(), but
92 deep_reload is off, IPython will use the normal reload(), but
93 deep_reload will still be available as dreload(). This feature is off
93 deep_reload will still be available as dreload(). This feature is off
94 by default [which means that you have both normal reload() and
94 by default [which means that you have both normal reload() and
95 dreload()].""",
95 dreload()].""",
96 "Disable deep (recursive) reloading by default."
96 "Disable deep (recursive) reloading by default."
97 )
97 )
98 nosep_config = Config()
98 nosep_config = Config()
99 nosep_config.InteractiveShell.separate_in = ''
99 nosep_config.InteractiveShell.separate_in = ''
100 nosep_config.InteractiveShell.separate_out = ''
100 nosep_config.InteractiveShell.separate_out = ''
101 nosep_config.InteractiveShell.separate_out2 = ''
101 nosep_config.InteractiveShell.separate_out2 = ''
102
102
103 shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
103 shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
104 shell_flags['pylab'] = (
104 shell_flags['pylab'] = (
105 {'InteractiveShellApp' : {'pylab' : 'auto'}},
105 {'InteractiveShellApp' : {'pylab' : 'auto'}},
106 """Pre-load matplotlib and numpy for interactive use with
106 """Pre-load matplotlib and numpy for interactive use with
107 the default matplotlib backend."""
107 the default matplotlib backend."""
108 )
108 )
109 shell_flags['matplotlib'] = (
109 shell_flags['matplotlib'] = (
110 {'InteractiveShellApp' : {'matplotlib' : 'auto'}},
110 {'InteractiveShellApp' : {'matplotlib' : 'auto'}},
111 """Configure matplotlib for interactive use with
111 """Configure matplotlib for interactive use with
112 the default matplotlib backend."""
112 the default matplotlib backend."""
113 )
113 )
114
114
115 # it's possible we don't want short aliases for *all* of these:
115 # it's possible we don't want short aliases for *all* of these:
116 shell_aliases = dict(
116 shell_aliases = dict(
117 autocall='InteractiveShell.autocall',
117 autocall='InteractiveShell.autocall',
118 colors='InteractiveShell.colors',
118 colors='InteractiveShell.colors',
119 logfile='InteractiveShell.logfile',
119 logfile='InteractiveShell.logfile',
120 logappend='InteractiveShell.logappend',
120 logappend='InteractiveShell.logappend',
121 c='InteractiveShellApp.code_to_run',
121 c='InteractiveShellApp.code_to_run',
122 m='InteractiveShellApp.module_to_run',
122 m='InteractiveShellApp.module_to_run',
123 ext='InteractiveShellApp.extra_extension',
123 ext='InteractiveShellApp.extra_extension',
124 gui='InteractiveShellApp.gui',
124 gui='InteractiveShellApp.gui',
125 pylab='InteractiveShellApp.pylab',
125 pylab='InteractiveShellApp.pylab',
126 matplotlib='InteractiveShellApp.matplotlib',
126 matplotlib='InteractiveShellApp.matplotlib',
127 )
127 )
128 shell_aliases['cache-size'] = 'InteractiveShell.cache_size'
128 shell_aliases['cache-size'] = 'InteractiveShell.cache_size'
129
129
130 #-----------------------------------------------------------------------------
130 #-----------------------------------------------------------------------------
131 # Main classes and functions
131 # Main classes and functions
132 #-----------------------------------------------------------------------------
132 #-----------------------------------------------------------------------------
133
133
134 class InteractiveShellApp(Configurable):
134 class InteractiveShellApp(Configurable):
135 """A Mixin for applications that start InteractiveShell instances.
135 """A Mixin for applications that start InteractiveShell instances.
136
136
137 Provides configurables for loading extensions and executing files
137 Provides configurables for loading extensions and executing files
138 as part of configuring a Shell environment.
138 as part of configuring a Shell environment.
139
139
140 The following methods should be called by the :meth:`initialize` method
140 The following methods should be called by the :meth:`initialize` method
141 of the subclass:
141 of the subclass:
142
142
143 - :meth:`init_path`
143 - :meth:`init_path`
144 - :meth:`init_shell` (to be implemented by the subclass)
144 - :meth:`init_shell` (to be implemented by the subclass)
145 - :meth:`init_gui_pylab`
145 - :meth:`init_gui_pylab`
146 - :meth:`init_extensions`
146 - :meth:`init_extensions`
147 - :meth:`init_code`
147 - :meth:`init_code`
148 """
148 """
149 extensions = List(Unicode, config=True,
149 extensions = List(Unicode, config=True,
150 help="A list of dotted module names of IPython extensions to load."
150 help="A list of dotted module names of IPython extensions to load."
151 )
151 )
152 extra_extension = Unicode('', config=True,
152 extra_extension = Unicode('', config=True,
153 help="dotted module name of an IPython extension to load."
153 help="dotted module name of an IPython extension to load."
154 )
154 )
155 def _extra_extension_changed(self, name, old, new):
155 def _extra_extension_changed(self, name, old, new):
156 if new:
156 if new:
157 # add to self.extensions
157 # add to self.extensions
158 self.extensions.append(new)
158 self.extensions.append(new)
159
159
160 # Extensions that are always loaded (not configurable)
160 # Extensions that are always loaded (not configurable)
161 default_extensions = List(Unicode, [u'storemagic'], config=False)
161 default_extensions = List(Unicode, [u'storemagic'], config=False)
162
162
163 hide_initial_ns = Bool(True, config=True,
163 hide_initial_ns = Bool(True, config=True,
164 help="""Should variables loaded at startup (by startup files, exec_lines, etc.)
164 help="""Should variables loaded at startup (by startup files, exec_lines, etc.)
165 be hidden from tools like %who?"""
165 be hidden from tools like %who?"""
166 )
166 )
167
167
168 exec_files = List(Unicode, config=True,
168 exec_files = List(Unicode, config=True,
169 help="""List of files to run at IPython startup."""
169 help="""List of files to run at IPython startup."""
170 )
170 )
171 exec_PYTHONSTARTUP = Bool(True, config=True,
171 exec_PYTHONSTARTUP = Bool(True, config=True,
172 help="""Run the file referenced by the PYTHONSTARTUP environment
172 help="""Run the file referenced by the PYTHONSTARTUP environment
173 variable at IPython startup."""
173 variable at IPython startup."""
174 )
174 )
175 file_to_run = Unicode('', config=True,
175 file_to_run = Unicode('', config=True,
176 help="""A file to be run""")
176 help="""A file to be run""")
177
177
178 exec_lines = List(Unicode, config=True,
178 exec_lines = List(Unicode, config=True,
179 help="""lines of code to run at IPython startup."""
179 help="""lines of code to run at IPython startup."""
180 )
180 )
181 code_to_run = Unicode('', config=True,
181 code_to_run = Unicode('', config=True,
182 help="Execute the given command string."
182 help="Execute the given command string."
183 )
183 )
184 module_to_run = Unicode('', config=True,
184 module_to_run = Unicode('', config=True,
185 help="Run the module as a script."
185 help="Run the module as a script."
186 )
186 )
187 gui = CaselessStrEnum(gui_keys, config=True,
187 gui = CaselessStrEnum(gui_keys, config=True, allow_none=True,
188 help="Enable GUI event loop integration with any of {0}.".format(gui_keys)
188 help="Enable GUI event loop integration with any of {0}.".format(gui_keys)
189 )
189 )
190 matplotlib = CaselessStrEnum(backend_keys,
190 matplotlib = CaselessStrEnum(backend_keys, allow_none=True,
191 config=True,
191 config=True,
192 help="""Configure matplotlib for interactive use with
192 help="""Configure matplotlib for interactive use with
193 the default matplotlib backend."""
193 the default matplotlib backend."""
194 )
194 )
195 pylab = CaselessStrEnum(backend_keys,
195 pylab = CaselessStrEnum(backend_keys, allow_none=True,
196 config=True,
196 config=True,
197 help="""Pre-load matplotlib and numpy for interactive use,
197 help="""Pre-load matplotlib and numpy for interactive use,
198 selecting a particular matplotlib backend and loop integration.
198 selecting a particular matplotlib backend and loop integration.
199 """
199 """
200 )
200 )
201 pylab_import_all = Bool(True, config=True,
201 pylab_import_all = Bool(True, config=True,
202 help="""If true, IPython will populate the user namespace with numpy, pylab, etc.
202 help="""If true, IPython will populate the user namespace with numpy, pylab, etc.
203 and an ``import *`` is done from numpy and pylab, when using pylab mode.
203 and an ``import *`` is done from numpy and pylab, when using pylab mode.
204
204
205 When False, pylab mode should not import any names into the user namespace.
205 When False, pylab mode should not import any names into the user namespace.
206 """
206 """
207 )
207 )
208 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
208 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
209
209
210 user_ns = Instance(dict, args=None, allow_none=True)
210 user_ns = Instance(dict, args=None, allow_none=True)
211 def _user_ns_changed(self, name, old, new):
211 def _user_ns_changed(self, name, old, new):
212 if self.shell is not None:
212 if self.shell is not None:
213 self.shell.user_ns = new
213 self.shell.user_ns = new
214 self.shell.init_user_ns()
214 self.shell.init_user_ns()
215
215
216 def init_path(self):
216 def init_path(self):
217 """Add current working directory, '', to sys.path"""
217 """Add current working directory, '', to sys.path"""
218 if sys.path[0] != '':
218 if sys.path[0] != '':
219 sys.path.insert(0, '')
219 sys.path.insert(0, '')
220
220
221 def init_shell(self):
221 def init_shell(self):
222 raise NotImplementedError("Override in subclasses")
222 raise NotImplementedError("Override in subclasses")
223
223
224 def init_gui_pylab(self):
224 def init_gui_pylab(self):
225 """Enable GUI event loop integration, taking pylab into account."""
225 """Enable GUI event loop integration, taking pylab into account."""
226 enable = False
226 enable = False
227 shell = self.shell
227 shell = self.shell
228 if self.pylab:
228 if self.pylab:
229 enable = lambda key: shell.enable_pylab(key, import_all=self.pylab_import_all)
229 enable = lambda key: shell.enable_pylab(key, import_all=self.pylab_import_all)
230 key = self.pylab
230 key = self.pylab
231 elif self.matplotlib:
231 elif self.matplotlib:
232 enable = shell.enable_matplotlib
232 enable = shell.enable_matplotlib
233 key = self.matplotlib
233 key = self.matplotlib
234 elif self.gui:
234 elif self.gui:
235 enable = shell.enable_gui
235 enable = shell.enable_gui
236 key = self.gui
236 key = self.gui
237
237
238 if not enable:
238 if not enable:
239 return
239 return
240
240
241 try:
241 try:
242 r = enable(key)
242 r = enable(key)
243 except ImportError:
243 except ImportError:
244 self.log.warn("Eventloop or matplotlib integration failed. Is matplotlib installed?")
244 self.log.warn("Eventloop or matplotlib integration failed. Is matplotlib installed?")
245 self.shell.showtraceback()
245 self.shell.showtraceback()
246 return
246 return
247 except Exception:
247 except Exception:
248 self.log.warn("GUI event loop or pylab initialization failed")
248 self.log.warn("GUI event loop or pylab initialization failed")
249 self.shell.showtraceback()
249 self.shell.showtraceback()
250 return
250 return
251
251
252 if isinstance(r, tuple):
252 if isinstance(r, tuple):
253 gui, backend = r[:2]
253 gui, backend = r[:2]
254 self.log.info("Enabling GUI event loop integration, "
254 self.log.info("Enabling GUI event loop integration, "
255 "eventloop=%s, matplotlib=%s", gui, backend)
255 "eventloop=%s, matplotlib=%s", gui, backend)
256 if key == "auto":
256 if key == "auto":
257 print("Using matplotlib backend: %s" % backend)
257 print("Using matplotlib backend: %s" % backend)
258 else:
258 else:
259 gui = r
259 gui = r
260 self.log.info("Enabling GUI event loop integration, "
260 self.log.info("Enabling GUI event loop integration, "
261 "eventloop=%s", gui)
261 "eventloop=%s", gui)
262
262
263 def init_extensions(self):
263 def init_extensions(self):
264 """Load all IPython extensions in IPythonApp.extensions.
264 """Load all IPython extensions in IPythonApp.extensions.
265
265
266 This uses the :meth:`ExtensionManager.load_extensions` to load all
266 This uses the :meth:`ExtensionManager.load_extensions` to load all
267 the extensions listed in ``self.extensions``.
267 the extensions listed in ``self.extensions``.
268 """
268 """
269 try:
269 try:
270 self.log.debug("Loading IPython extensions...")
270 self.log.debug("Loading IPython extensions...")
271 extensions = self.default_extensions + self.extensions
271 extensions = self.default_extensions + self.extensions
272 for ext in extensions:
272 for ext in extensions:
273 try:
273 try:
274 self.log.info("Loading IPython extension: %s" % ext)
274 self.log.info("Loading IPython extension: %s" % ext)
275 self.shell.extension_manager.load_extension(ext)
275 self.shell.extension_manager.load_extension(ext)
276 except:
276 except:
277 msg = ("Error in loading extension: {ext}\n"
277 msg = ("Error in loading extension: {ext}\n"
278 "Check your config files in {location}".format(
278 "Check your config files in {location}".format(
279 ext=ext,
279 ext=ext,
280 location=self.profile_dir.location
280 location=self.profile_dir.location
281 ))
281 ))
282 self.log.warn(msg, exc_info=True)
282 self.log.warn(msg, exc_info=True)
283 except:
283 except:
284 self.log.warn("Unknown error in loading extensions:", exc_info=True)
284 self.log.warn("Unknown error in loading extensions:", exc_info=True)
285
285
286 def init_code(self):
286 def init_code(self):
287 """run the pre-flight code, specified via exec_lines"""
287 """run the pre-flight code, specified via exec_lines"""
288 self._run_startup_files()
288 self._run_startup_files()
289 self._run_exec_lines()
289 self._run_exec_lines()
290 self._run_exec_files()
290 self._run_exec_files()
291
291
292 # Hide variables defined here from %who etc.
292 # Hide variables defined here from %who etc.
293 if self.hide_initial_ns:
293 if self.hide_initial_ns:
294 self.shell.user_ns_hidden.update(self.shell.user_ns)
294 self.shell.user_ns_hidden.update(self.shell.user_ns)
295
295
296 # command-line execution (ipython -i script.py, ipython -m module)
296 # command-line execution (ipython -i script.py, ipython -m module)
297 # should *not* be excluded from %whos
297 # should *not* be excluded from %whos
298 self._run_cmd_line_code()
298 self._run_cmd_line_code()
299 self._run_module()
299 self._run_module()
300
300
301 # flush output, so itwon't be attached to the first cell
301 # flush output, so itwon't be attached to the first cell
302 sys.stdout.flush()
302 sys.stdout.flush()
303 sys.stderr.flush()
303 sys.stderr.flush()
304
304
305 def _run_exec_lines(self):
305 def _run_exec_lines(self):
306 """Run lines of code in IPythonApp.exec_lines in the user's namespace."""
306 """Run lines of code in IPythonApp.exec_lines in the user's namespace."""
307 if not self.exec_lines:
307 if not self.exec_lines:
308 return
308 return
309 try:
309 try:
310 self.log.debug("Running code from IPythonApp.exec_lines...")
310 self.log.debug("Running code from IPythonApp.exec_lines...")
311 for line in self.exec_lines:
311 for line in self.exec_lines:
312 try:
312 try:
313 self.log.info("Running code in user namespace: %s" %
313 self.log.info("Running code in user namespace: %s" %
314 line)
314 line)
315 self.shell.run_cell(line, store_history=False)
315 self.shell.run_cell(line, store_history=False)
316 except:
316 except:
317 self.log.warn("Error in executing line in user "
317 self.log.warn("Error in executing line in user "
318 "namespace: %s" % line)
318 "namespace: %s" % line)
319 self.shell.showtraceback()
319 self.shell.showtraceback()
320 except:
320 except:
321 self.log.warn("Unknown error in handling IPythonApp.exec_lines:")
321 self.log.warn("Unknown error in handling IPythonApp.exec_lines:")
322 self.shell.showtraceback()
322 self.shell.showtraceback()
323
323
324 def _exec_file(self, fname, shell_futures=False):
324 def _exec_file(self, fname, shell_futures=False):
325 try:
325 try:
326 full_filename = filefind(fname, [u'.', self.ipython_dir])
326 full_filename = filefind(fname, [u'.', self.ipython_dir])
327 except IOError as e:
327 except IOError as e:
328 self.log.warn("File not found: %r"%fname)
328 self.log.warn("File not found: %r"%fname)
329 return
329 return
330 # Make sure that the running script gets a proper sys.argv as if it
330 # Make sure that the running script gets a proper sys.argv as if it
331 # were run from a system shell.
331 # were run from a system shell.
332 save_argv = sys.argv
332 save_argv = sys.argv
333 sys.argv = [full_filename] + self.extra_args[1:]
333 sys.argv = [full_filename] + self.extra_args[1:]
334 # protect sys.argv from potential unicode strings on Python 2:
334 # protect sys.argv from potential unicode strings on Python 2:
335 if not py3compat.PY3:
335 if not py3compat.PY3:
336 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
336 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
337 try:
337 try:
338 if os.path.isfile(full_filename):
338 if os.path.isfile(full_filename):
339 self.log.info("Running file in user namespace: %s" %
339 self.log.info("Running file in user namespace: %s" %
340 full_filename)
340 full_filename)
341 # Ensure that __file__ is always defined to match Python
341 # Ensure that __file__ is always defined to match Python
342 # behavior.
342 # behavior.
343 with preserve_keys(self.shell.user_ns, '__file__'):
343 with preserve_keys(self.shell.user_ns, '__file__'):
344 self.shell.user_ns['__file__'] = fname
344 self.shell.user_ns['__file__'] = fname
345 if full_filename.endswith('.ipy'):
345 if full_filename.endswith('.ipy'):
346 self.shell.safe_execfile_ipy(full_filename,
346 self.shell.safe_execfile_ipy(full_filename,
347 shell_futures=shell_futures)
347 shell_futures=shell_futures)
348 else:
348 else:
349 # default to python, even without extension
349 # default to python, even without extension
350 self.shell.safe_execfile(full_filename,
350 self.shell.safe_execfile(full_filename,
351 self.shell.user_ns,
351 self.shell.user_ns,
352 shell_futures=shell_futures)
352 shell_futures=shell_futures)
353 finally:
353 finally:
354 sys.argv = save_argv
354 sys.argv = save_argv
355
355
356 def _run_startup_files(self):
356 def _run_startup_files(self):
357 """Run files from profile startup directory"""
357 """Run files from profile startup directory"""
358 startup_dir = self.profile_dir.startup_dir
358 startup_dir = self.profile_dir.startup_dir
359 startup_files = []
359 startup_files = []
360
360
361 if self.exec_PYTHONSTARTUP and os.environ.get('PYTHONSTARTUP', False) and \
361 if self.exec_PYTHONSTARTUP and os.environ.get('PYTHONSTARTUP', False) and \
362 not (self.file_to_run or self.code_to_run or self.module_to_run):
362 not (self.file_to_run or self.code_to_run or self.module_to_run):
363 python_startup = os.environ['PYTHONSTARTUP']
363 python_startup = os.environ['PYTHONSTARTUP']
364 self.log.debug("Running PYTHONSTARTUP file %s...", python_startup)
364 self.log.debug("Running PYTHONSTARTUP file %s...", python_startup)
365 try:
365 try:
366 self._exec_file(python_startup)
366 self._exec_file(python_startup)
367 except:
367 except:
368 self.log.warn("Unknown error in handling PYTHONSTARTUP file %s:", python_startup)
368 self.log.warn("Unknown error in handling PYTHONSTARTUP file %s:", python_startup)
369 self.shell.showtraceback()
369 self.shell.showtraceback()
370 finally:
370 finally:
371 # Many PYTHONSTARTUP files set up the readline completions,
371 # Many PYTHONSTARTUP files set up the readline completions,
372 # but this is often at odds with IPython's own completions.
372 # but this is often at odds with IPython's own completions.
373 # Do not allow PYTHONSTARTUP to set up readline.
373 # Do not allow PYTHONSTARTUP to set up readline.
374 if self.shell.has_readline:
374 if self.shell.has_readline:
375 self.shell.set_readline_completer()
375 self.shell.set_readline_completer()
376
376
377 startup_files += glob.glob(os.path.join(startup_dir, '*.py'))
377 startup_files += glob.glob(os.path.join(startup_dir, '*.py'))
378 startup_files += glob.glob(os.path.join(startup_dir, '*.ipy'))
378 startup_files += glob.glob(os.path.join(startup_dir, '*.ipy'))
379 if not startup_files:
379 if not startup_files:
380 return
380 return
381
381
382 self.log.debug("Running startup files from %s...", startup_dir)
382 self.log.debug("Running startup files from %s...", startup_dir)
383 try:
383 try:
384 for fname in sorted(startup_files):
384 for fname in sorted(startup_files):
385 self._exec_file(fname)
385 self._exec_file(fname)
386 except:
386 except:
387 self.log.warn("Unknown error in handling startup files:")
387 self.log.warn("Unknown error in handling startup files:")
388 self.shell.showtraceback()
388 self.shell.showtraceback()
389
389
390 def _run_exec_files(self):
390 def _run_exec_files(self):
391 """Run files from IPythonApp.exec_files"""
391 """Run files from IPythonApp.exec_files"""
392 if not self.exec_files:
392 if not self.exec_files:
393 return
393 return
394
394
395 self.log.debug("Running files in IPythonApp.exec_files...")
395 self.log.debug("Running files in IPythonApp.exec_files...")
396 try:
396 try:
397 for fname in self.exec_files:
397 for fname in self.exec_files:
398 self._exec_file(fname)
398 self._exec_file(fname)
399 except:
399 except:
400 self.log.warn("Unknown error in handling IPythonApp.exec_files:")
400 self.log.warn("Unknown error in handling IPythonApp.exec_files:")
401 self.shell.showtraceback()
401 self.shell.showtraceback()
402
402
403 def _run_cmd_line_code(self):
403 def _run_cmd_line_code(self):
404 """Run code or file specified at the command-line"""
404 """Run code or file specified at the command-line"""
405 if self.code_to_run:
405 if self.code_to_run:
406 line = self.code_to_run
406 line = self.code_to_run
407 try:
407 try:
408 self.log.info("Running code given at command line (c=): %s" %
408 self.log.info("Running code given at command line (c=): %s" %
409 line)
409 line)
410 self.shell.run_cell(line, store_history=False)
410 self.shell.run_cell(line, store_history=False)
411 except:
411 except:
412 self.log.warn("Error in executing line in user namespace: %s" %
412 self.log.warn("Error in executing line in user namespace: %s" %
413 line)
413 line)
414 self.shell.showtraceback()
414 self.shell.showtraceback()
415
415
416 # Like Python itself, ignore the second if the first of these is present
416 # Like Python itself, ignore the second if the first of these is present
417 elif self.file_to_run:
417 elif self.file_to_run:
418 fname = self.file_to_run
418 fname = self.file_to_run
419 try:
419 try:
420 self._exec_file(fname, shell_futures=True)
420 self._exec_file(fname, shell_futures=True)
421 except:
421 except:
422 self.log.warn("Error in executing file in user namespace: %s" %
422 self.log.warn("Error in executing file in user namespace: %s" %
423 fname)
423 fname)
424 self.shell.showtraceback()
424 self.shell.showtraceback()
425
425
426 def _run_module(self):
426 def _run_module(self):
427 """Run module specified at the command-line."""
427 """Run module specified at the command-line."""
428 if self.module_to_run:
428 if self.module_to_run:
429 # Make sure that the module gets a proper sys.argv as if it were
429 # Make sure that the module gets a proper sys.argv as if it were
430 # run using `python -m`.
430 # run using `python -m`.
431 save_argv = sys.argv
431 save_argv = sys.argv
432 sys.argv = [sys.executable] + self.extra_args
432 sys.argv = [sys.executable] + self.extra_args
433 try:
433 try:
434 self.shell.safe_run_module(self.module_to_run,
434 self.shell.safe_run_module(self.module_to_run,
435 self.shell.user_ns)
435 self.shell.user_ns)
436 finally:
436 finally:
437 sys.argv = save_argv
437 sys.argv = save_argv
@@ -1,496 +1,496
1 """Test suite for our zeromq-based message specification."""
1 """Test suite for our zeromq-based message specification."""
2
2
3 # Copyright (c) IPython Development Team.
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
4 # Distributed under the terms of the Modified BSD License.
5
5
6 import re
6 import re
7 import sys
7 import sys
8 from distutils.version import LooseVersion as V
8 from distutils.version import LooseVersion as V
9 try:
9 try:
10 from queue import Empty # Py 3
10 from queue import Empty # Py 3
11 except ImportError:
11 except ImportError:
12 from Queue import Empty # Py 2
12 from Queue import Empty # Py 2
13
13
14 import nose.tools as nt
14 import nose.tools as nt
15
15
16 from IPython.utils.traitlets import (
16 from IPython.utils.traitlets import (
17 HasTraits, TraitError, Bool, Unicode, Dict, Integer, List, Enum,
17 HasTraits, TraitError, Bool, Unicode, Dict, Integer, List, Enum,
18 )
18 )
19 from IPython.utils.py3compat import string_types, iteritems
19 from IPython.utils.py3compat import string_types, iteritems
20
20
21 from .utils import TIMEOUT, start_global_kernel, flush_channels, execute
21 from .utils import TIMEOUT, start_global_kernel, flush_channels, execute
22
22
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24 # Globals
24 # Globals
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26 KC = None
26 KC = None
27
27
28 def setup():
28 def setup():
29 global KC
29 global KC
30 KC = start_global_kernel()
30 KC = start_global_kernel()
31
31
32 #-----------------------------------------------------------------------------
32 #-----------------------------------------------------------------------------
33 # Message Spec References
33 # Message Spec References
34 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
35
35
36 class Reference(HasTraits):
36 class Reference(HasTraits):
37
37
38 """
38 """
39 Base class for message spec specification testing.
39 Base class for message spec specification testing.
40
40
41 This class is the core of the message specification test. The
41 This class is the core of the message specification test. The
42 idea is that child classes implement trait attributes for each
42 idea is that child classes implement trait attributes for each
43 message keys, so that message keys can be tested against these
43 message keys, so that message keys can be tested against these
44 traits using :meth:`check` method.
44 traits using :meth:`check` method.
45
45
46 """
46 """
47
47
48 def check(self, d):
48 def check(self, d):
49 """validate a dict against our traits"""
49 """validate a dict against our traits"""
50 for key in self.trait_names():
50 for key in self.trait_names():
51 nt.assert_in(key, d)
51 nt.assert_in(key, d)
52 # FIXME: always allow None, probably not a good idea
52 # FIXME: always allow None, probably not a good idea
53 if d[key] is None:
53 if d[key] is None:
54 continue
54 continue
55 try:
55 try:
56 setattr(self, key, d[key])
56 setattr(self, key, d[key])
57 except TraitError as e:
57 except TraitError as e:
58 assert False, str(e)
58 assert False, str(e)
59
59
60
60
61 class Version(Unicode):
61 class Version(Unicode):
62 def __init__(self, *args, **kwargs):
62 def __init__(self, *args, **kwargs):
63 self.min = kwargs.pop('min', None)
63 self.min = kwargs.pop('min', None)
64 self.max = kwargs.pop('max', None)
64 self.max = kwargs.pop('max', None)
65 kwargs['default_value'] = self.min
65 kwargs['default_value'] = self.min
66 super(Version, self).__init__(*args, **kwargs)
66 super(Version, self).__init__(*args, **kwargs)
67
67
68 def validate(self, obj, value):
68 def validate(self, obj, value):
69 if self.min and V(value) < V(self.min):
69 if self.min and V(value) < V(self.min):
70 raise TraitError("bad version: %s < %s" % (value, self.min))
70 raise TraitError("bad version: %s < %s" % (value, self.min))
71 if self.max and (V(value) > V(self.max)):
71 if self.max and (V(value) > V(self.max)):
72 raise TraitError("bad version: %s > %s" % (value, self.max))
72 raise TraitError("bad version: %s > %s" % (value, self.max))
73
73
74
74
75 class RMessage(Reference):
75 class RMessage(Reference):
76 msg_id = Unicode()
76 msg_id = Unicode()
77 msg_type = Unicode()
77 msg_type = Unicode()
78 header = Dict()
78 header = Dict()
79 parent_header = Dict()
79 parent_header = Dict()
80 content = Dict()
80 content = Dict()
81
81
82 def check(self, d):
82 def check(self, d):
83 super(RMessage, self).check(d)
83 super(RMessage, self).check(d)
84 RHeader().check(self.header)
84 RHeader().check(self.header)
85 if self.parent_header:
85 if self.parent_header:
86 RHeader().check(self.parent_header)
86 RHeader().check(self.parent_header)
87
87
88 class RHeader(Reference):
88 class RHeader(Reference):
89 msg_id = Unicode()
89 msg_id = Unicode()
90 msg_type = Unicode()
90 msg_type = Unicode()
91 session = Unicode()
91 session = Unicode()
92 username = Unicode()
92 username = Unicode()
93 version = Version(min='5.0')
93 version = Version(min='5.0')
94
94
95 mime_pat = re.compile(r'^[\w\-\+\.]+/[\w\-\+\.]+$')
95 mime_pat = re.compile(r'^[\w\-\+\.]+/[\w\-\+\.]+$')
96
96
97 class MimeBundle(Reference):
97 class MimeBundle(Reference):
98 metadata = Dict()
98 metadata = Dict()
99 data = Dict()
99 data = Dict()
100 def _data_changed(self, name, old, new):
100 def _data_changed(self, name, old, new):
101 for k,v in iteritems(new):
101 for k,v in iteritems(new):
102 assert mime_pat.match(k)
102 assert mime_pat.match(k)
103 nt.assert_is_instance(v, string_types)
103 nt.assert_is_instance(v, string_types)
104
104
105 # shell replies
105 # shell replies
106
106
107 class ExecuteReply(Reference):
107 class ExecuteReply(Reference):
108 execution_count = Integer()
108 execution_count = Integer()
109 status = Enum((u'ok', u'error'))
109 status = Enum((u'ok', u'error'), allow_none=True)
110
110
111 def check(self, d):
111 def check(self, d):
112 Reference.check(self, d)
112 Reference.check(self, d)
113 if d['status'] == 'ok':
113 if d['status'] == 'ok':
114 ExecuteReplyOkay().check(d)
114 ExecuteReplyOkay().check(d)
115 elif d['status'] == 'error':
115 elif d['status'] == 'error':
116 ExecuteReplyError().check(d)
116 ExecuteReplyError().check(d)
117
117
118
118
119 class ExecuteReplyOkay(Reference):
119 class ExecuteReplyOkay(Reference):
120 payload = List(Dict)
120 payload = List(Dict)
121 user_expressions = Dict()
121 user_expressions = Dict()
122
122
123
123
124 class ExecuteReplyError(Reference):
124 class ExecuteReplyError(Reference):
125 ename = Unicode()
125 ename = Unicode()
126 evalue = Unicode()
126 evalue = Unicode()
127 traceback = List(Unicode)
127 traceback = List(Unicode)
128
128
129
129
130 class InspectReply(MimeBundle):
130 class InspectReply(MimeBundle):
131 found = Bool()
131 found = Bool()
132
132
133
133
134 class ArgSpec(Reference):
134 class ArgSpec(Reference):
135 args = List(Unicode)
135 args = List(Unicode)
136 varargs = Unicode()
136 varargs = Unicode()
137 varkw = Unicode()
137 varkw = Unicode()
138 defaults = List()
138 defaults = List()
139
139
140
140
141 class Status(Reference):
141 class Status(Reference):
142 execution_state = Enum((u'busy', u'idle', u'starting'))
142 execution_state = Enum((u'busy', u'idle', u'starting'), allow_none=True)
143
143
144
144
145 class CompleteReply(Reference):
145 class CompleteReply(Reference):
146 matches = List(Unicode)
146 matches = List(Unicode)
147 cursor_start = Integer()
147 cursor_start = Integer()
148 cursor_end = Integer()
148 cursor_end = Integer()
149 status = Unicode()
149 status = Unicode()
150
150
151 class LanguageInfo(Reference):
151 class LanguageInfo(Reference):
152 name = Unicode('python')
152 name = Unicode('python')
153 version = Unicode(sys.version.split()[0])
153 version = Unicode(sys.version.split()[0])
154
154
155 class KernelInfoReply(Reference):
155 class KernelInfoReply(Reference):
156 protocol_version = Version(min='5.0')
156 protocol_version = Version(min='5.0')
157 implementation = Unicode('ipython')
157 implementation = Unicode('ipython')
158 implementation_version = Version(min='2.1')
158 implementation_version = Version(min='2.1')
159 language_info = Dict()
159 language_info = Dict()
160 banner = Unicode()
160 banner = Unicode()
161
161
162 def check(self, d):
162 def check(self, d):
163 Reference.check(self, d)
163 Reference.check(self, d)
164 LanguageInfo().check(d['language_info'])
164 LanguageInfo().check(d['language_info'])
165
165
166
166
167 class IsCompleteReply(Reference):
167 class IsCompleteReply(Reference):
168 status = Enum((u'complete', u'incomplete', u'invalid', u'unknown'))
168 status = Enum((u'complete', u'incomplete', u'invalid', u'unknown'), allow_none=True)
169
169
170 def check(self, d):
170 def check(self, d):
171 Reference.check(self, d)
171 Reference.check(self, d)
172 if d['status'] == 'incomplete':
172 if d['status'] == 'incomplete':
173 IsCompleteReplyIncomplete().check(d)
173 IsCompleteReplyIncomplete().check(d)
174
174
175 class IsCompleteReplyIncomplete(Reference):
175 class IsCompleteReplyIncomplete(Reference):
176 indent = Unicode()
176 indent = Unicode()
177
177
178
178
179 # IOPub messages
179 # IOPub messages
180
180
181 class ExecuteInput(Reference):
181 class ExecuteInput(Reference):
182 code = Unicode()
182 code = Unicode()
183 execution_count = Integer()
183 execution_count = Integer()
184
184
185
185
186 Error = ExecuteReplyError
186 Error = ExecuteReplyError
187
187
188
188
189 class Stream(Reference):
189 class Stream(Reference):
190 name = Enum((u'stdout', u'stderr'))
190 name = Enum((u'stdout', u'stderr'), allow_none=True)
191 text = Unicode()
191 text = Unicode()
192
192
193
193
194 class DisplayData(MimeBundle):
194 class DisplayData(MimeBundle):
195 pass
195 pass
196
196
197
197
198 class ExecuteResult(MimeBundle):
198 class ExecuteResult(MimeBundle):
199 execution_count = Integer()
199 execution_count = Integer()
200
200
201 class HistoryReply(Reference):
201 class HistoryReply(Reference):
202 history = List(List())
202 history = List(List())
203
203
204
204
205 references = {
205 references = {
206 'execute_reply' : ExecuteReply(),
206 'execute_reply' : ExecuteReply(),
207 'inspect_reply' : InspectReply(),
207 'inspect_reply' : InspectReply(),
208 'status' : Status(),
208 'status' : Status(),
209 'complete_reply' : CompleteReply(),
209 'complete_reply' : CompleteReply(),
210 'kernel_info_reply': KernelInfoReply(),
210 'kernel_info_reply': KernelInfoReply(),
211 'is_complete_reply': IsCompleteReply(),
211 'is_complete_reply': IsCompleteReply(),
212 'execute_input' : ExecuteInput(),
212 'execute_input' : ExecuteInput(),
213 'execute_result' : ExecuteResult(),
213 'execute_result' : ExecuteResult(),
214 'history_reply' : HistoryReply(),
214 'history_reply' : HistoryReply(),
215 'error' : Error(),
215 'error' : Error(),
216 'stream' : Stream(),
216 'stream' : Stream(),
217 'display_data' : DisplayData(),
217 'display_data' : DisplayData(),
218 'header' : RHeader(),
218 'header' : RHeader(),
219 }
219 }
220 """
220 """
221 Specifications of `content` part of the reply messages.
221 Specifications of `content` part of the reply messages.
222 """
222 """
223
223
224
224
225 def validate_message(msg, msg_type=None, parent=None):
225 def validate_message(msg, msg_type=None, parent=None):
226 """validate a message
226 """validate a message
227
227
228 This is a generator, and must be iterated through to actually
228 This is a generator, and must be iterated through to actually
229 trigger each test.
229 trigger each test.
230
230
231 If msg_type and/or parent are given, the msg_type and/or parent msg_id
231 If msg_type and/or parent are given, the msg_type and/or parent msg_id
232 are compared with the given values.
232 are compared with the given values.
233 """
233 """
234 RMessage().check(msg)
234 RMessage().check(msg)
235 if msg_type:
235 if msg_type:
236 nt.assert_equal(msg['msg_type'], msg_type)
236 nt.assert_equal(msg['msg_type'], msg_type)
237 if parent:
237 if parent:
238 nt.assert_equal(msg['parent_header']['msg_id'], parent)
238 nt.assert_equal(msg['parent_header']['msg_id'], parent)
239 content = msg['content']
239 content = msg['content']
240 ref = references[msg['msg_type']]
240 ref = references[msg['msg_type']]
241 ref.check(content)
241 ref.check(content)
242
242
243
243
244 #-----------------------------------------------------------------------------
244 #-----------------------------------------------------------------------------
245 # Tests
245 # Tests
246 #-----------------------------------------------------------------------------
246 #-----------------------------------------------------------------------------
247
247
248 # Shell channel
248 # Shell channel
249
249
250 def test_execute():
250 def test_execute():
251 flush_channels()
251 flush_channels()
252
252
253 msg_id = KC.execute(code='x=1')
253 msg_id = KC.execute(code='x=1')
254 reply = KC.get_shell_msg(timeout=TIMEOUT)
254 reply = KC.get_shell_msg(timeout=TIMEOUT)
255 validate_message(reply, 'execute_reply', msg_id)
255 validate_message(reply, 'execute_reply', msg_id)
256
256
257
257
258 def test_execute_silent():
258 def test_execute_silent():
259 flush_channels()
259 flush_channels()
260 msg_id, reply = execute(code='x=1', silent=True)
260 msg_id, reply = execute(code='x=1', silent=True)
261
261
262 # flush status=idle
262 # flush status=idle
263 status = KC.iopub_channel.get_msg(timeout=TIMEOUT)
263 status = KC.iopub_channel.get_msg(timeout=TIMEOUT)
264 validate_message(status, 'status', msg_id)
264 validate_message(status, 'status', msg_id)
265 nt.assert_equal(status['content']['execution_state'], 'idle')
265 nt.assert_equal(status['content']['execution_state'], 'idle')
266
266
267 nt.assert_raises(Empty, KC.iopub_channel.get_msg, timeout=0.1)
267 nt.assert_raises(Empty, KC.iopub_channel.get_msg, timeout=0.1)
268 count = reply['execution_count']
268 count = reply['execution_count']
269
269
270 msg_id, reply = execute(code='x=2', silent=True)
270 msg_id, reply = execute(code='x=2', silent=True)
271
271
272 # flush status=idle
272 # flush status=idle
273 status = KC.iopub_channel.get_msg(timeout=TIMEOUT)
273 status = KC.iopub_channel.get_msg(timeout=TIMEOUT)
274 validate_message(status, 'status', msg_id)
274 validate_message(status, 'status', msg_id)
275 nt.assert_equal(status['content']['execution_state'], 'idle')
275 nt.assert_equal(status['content']['execution_state'], 'idle')
276
276
277 nt.assert_raises(Empty, KC.iopub_channel.get_msg, timeout=0.1)
277 nt.assert_raises(Empty, KC.iopub_channel.get_msg, timeout=0.1)
278 count_2 = reply['execution_count']
278 count_2 = reply['execution_count']
279 nt.assert_equal(count_2, count)
279 nt.assert_equal(count_2, count)
280
280
281
281
282 def test_execute_error():
282 def test_execute_error():
283 flush_channels()
283 flush_channels()
284
284
285 msg_id, reply = execute(code='1/0')
285 msg_id, reply = execute(code='1/0')
286 nt.assert_equal(reply['status'], 'error')
286 nt.assert_equal(reply['status'], 'error')
287 nt.assert_equal(reply['ename'], 'ZeroDivisionError')
287 nt.assert_equal(reply['ename'], 'ZeroDivisionError')
288
288
289 error = KC.iopub_channel.get_msg(timeout=TIMEOUT)
289 error = KC.iopub_channel.get_msg(timeout=TIMEOUT)
290 validate_message(error, 'error', msg_id)
290 validate_message(error, 'error', msg_id)
291
291
292
292
293 def test_execute_inc():
293 def test_execute_inc():
294 """execute request should increment execution_count"""
294 """execute request should increment execution_count"""
295 flush_channels()
295 flush_channels()
296
296
297 msg_id, reply = execute(code='x=1')
297 msg_id, reply = execute(code='x=1')
298 count = reply['execution_count']
298 count = reply['execution_count']
299
299
300 flush_channels()
300 flush_channels()
301
301
302 msg_id, reply = execute(code='x=2')
302 msg_id, reply = execute(code='x=2')
303 count_2 = reply['execution_count']
303 count_2 = reply['execution_count']
304 nt.assert_equal(count_2, count+1)
304 nt.assert_equal(count_2, count+1)
305
305
306 def test_execute_stop_on_error():
306 def test_execute_stop_on_error():
307 """execute request should not abort execution queue with stop_on_error False"""
307 """execute request should not abort execution queue with stop_on_error False"""
308 flush_channels()
308 flush_channels()
309
309
310 fail = '\n'.join([
310 fail = '\n'.join([
311 # sleep to ensure subsequent message is waiting in the queue to be aborted
311 # sleep to ensure subsequent message is waiting in the queue to be aborted
312 'import time',
312 'import time',
313 'time.sleep(0.5)',
313 'time.sleep(0.5)',
314 'raise ValueError',
314 'raise ValueError',
315 ])
315 ])
316 KC.execute(code=fail)
316 KC.execute(code=fail)
317 msg_id = KC.execute(code='print("Hello")')
317 msg_id = KC.execute(code='print("Hello")')
318 KC.get_shell_msg(timeout=TIMEOUT)
318 KC.get_shell_msg(timeout=TIMEOUT)
319 reply = KC.get_shell_msg(timeout=TIMEOUT)
319 reply = KC.get_shell_msg(timeout=TIMEOUT)
320 nt.assert_equal(reply['content']['status'], 'aborted')
320 nt.assert_equal(reply['content']['status'], 'aborted')
321
321
322 flush_channels()
322 flush_channels()
323
323
324 KC.execute(code=fail, stop_on_error=False)
324 KC.execute(code=fail, stop_on_error=False)
325 msg_id = KC.execute(code='print("Hello")')
325 msg_id = KC.execute(code='print("Hello")')
326 KC.get_shell_msg(timeout=TIMEOUT)
326 KC.get_shell_msg(timeout=TIMEOUT)
327 reply = KC.get_shell_msg(timeout=TIMEOUT)
327 reply = KC.get_shell_msg(timeout=TIMEOUT)
328 nt.assert_equal(reply['content']['status'], 'ok')
328 nt.assert_equal(reply['content']['status'], 'ok')
329
329
330
330
331 def test_user_expressions():
331 def test_user_expressions():
332 flush_channels()
332 flush_channels()
333
333
334 msg_id, reply = execute(code='x=1', user_expressions=dict(foo='x+1'))
334 msg_id, reply = execute(code='x=1', user_expressions=dict(foo='x+1'))
335 user_expressions = reply['user_expressions']
335 user_expressions = reply['user_expressions']
336 nt.assert_equal(user_expressions, {u'foo': {
336 nt.assert_equal(user_expressions, {u'foo': {
337 u'status': u'ok',
337 u'status': u'ok',
338 u'data': {u'text/plain': u'2'},
338 u'data': {u'text/plain': u'2'},
339 u'metadata': {},
339 u'metadata': {},
340 }})
340 }})
341
341
342
342
343 def test_user_expressions_fail():
343 def test_user_expressions_fail():
344 flush_channels()
344 flush_channels()
345
345
346 msg_id, reply = execute(code='x=0', user_expressions=dict(foo='nosuchname'))
346 msg_id, reply = execute(code='x=0', user_expressions=dict(foo='nosuchname'))
347 user_expressions = reply['user_expressions']
347 user_expressions = reply['user_expressions']
348 foo = user_expressions['foo']
348 foo = user_expressions['foo']
349 nt.assert_equal(foo['status'], 'error')
349 nt.assert_equal(foo['status'], 'error')
350 nt.assert_equal(foo['ename'], 'NameError')
350 nt.assert_equal(foo['ename'], 'NameError')
351
351
352
352
353 def test_oinfo():
353 def test_oinfo():
354 flush_channels()
354 flush_channels()
355
355
356 msg_id = KC.inspect('a')
356 msg_id = KC.inspect('a')
357 reply = KC.get_shell_msg(timeout=TIMEOUT)
357 reply = KC.get_shell_msg(timeout=TIMEOUT)
358 validate_message(reply, 'inspect_reply', msg_id)
358 validate_message(reply, 'inspect_reply', msg_id)
359
359
360
360
361 def test_oinfo_found():
361 def test_oinfo_found():
362 flush_channels()
362 flush_channels()
363
363
364 msg_id, reply = execute(code='a=5')
364 msg_id, reply = execute(code='a=5')
365
365
366 msg_id = KC.inspect('a')
366 msg_id = KC.inspect('a')
367 reply = KC.get_shell_msg(timeout=TIMEOUT)
367 reply = KC.get_shell_msg(timeout=TIMEOUT)
368 validate_message(reply, 'inspect_reply', msg_id)
368 validate_message(reply, 'inspect_reply', msg_id)
369 content = reply['content']
369 content = reply['content']
370 assert content['found']
370 assert content['found']
371 text = content['data']['text/plain']
371 text = content['data']['text/plain']
372 nt.assert_in('Type:', text)
372 nt.assert_in('Type:', text)
373 nt.assert_in('Docstring:', text)
373 nt.assert_in('Docstring:', text)
374
374
375
375
376 def test_oinfo_detail():
376 def test_oinfo_detail():
377 flush_channels()
377 flush_channels()
378
378
379 msg_id, reply = execute(code='ip=get_ipython()')
379 msg_id, reply = execute(code='ip=get_ipython()')
380
380
381 msg_id = KC.inspect('ip.object_inspect', cursor_pos=10, detail_level=1)
381 msg_id = KC.inspect('ip.object_inspect', cursor_pos=10, detail_level=1)
382 reply = KC.get_shell_msg(timeout=TIMEOUT)
382 reply = KC.get_shell_msg(timeout=TIMEOUT)
383 validate_message(reply, 'inspect_reply', msg_id)
383 validate_message(reply, 'inspect_reply', msg_id)
384 content = reply['content']
384 content = reply['content']
385 assert content['found']
385 assert content['found']
386 text = content['data']['text/plain']
386 text = content['data']['text/plain']
387 nt.assert_in('Definition:', text)
387 nt.assert_in('Definition:', text)
388 nt.assert_in('Source:', text)
388 nt.assert_in('Source:', text)
389
389
390
390
391 def test_oinfo_not_found():
391 def test_oinfo_not_found():
392 flush_channels()
392 flush_channels()
393
393
394 msg_id = KC.inspect('dne')
394 msg_id = KC.inspect('dne')
395 reply = KC.get_shell_msg(timeout=TIMEOUT)
395 reply = KC.get_shell_msg(timeout=TIMEOUT)
396 validate_message(reply, 'inspect_reply', msg_id)
396 validate_message(reply, 'inspect_reply', msg_id)
397 content = reply['content']
397 content = reply['content']
398 nt.assert_false(content['found'])
398 nt.assert_false(content['found'])
399
399
400
400
401 def test_complete():
401 def test_complete():
402 flush_channels()
402 flush_channels()
403
403
404 msg_id, reply = execute(code="alpha = albert = 5")
404 msg_id, reply = execute(code="alpha = albert = 5")
405
405
406 msg_id = KC.complete('al', 2)
406 msg_id = KC.complete('al', 2)
407 reply = KC.get_shell_msg(timeout=TIMEOUT)
407 reply = KC.get_shell_msg(timeout=TIMEOUT)
408 validate_message(reply, 'complete_reply', msg_id)
408 validate_message(reply, 'complete_reply', msg_id)
409 matches = reply['content']['matches']
409 matches = reply['content']['matches']
410 for name in ('alpha', 'albert'):
410 for name in ('alpha', 'albert'):
411 nt.assert_in(name, matches)
411 nt.assert_in(name, matches)
412
412
413
413
414 def test_kernel_info_request():
414 def test_kernel_info_request():
415 flush_channels()
415 flush_channels()
416
416
417 msg_id = KC.kernel_info()
417 msg_id = KC.kernel_info()
418 reply = KC.get_shell_msg(timeout=TIMEOUT)
418 reply = KC.get_shell_msg(timeout=TIMEOUT)
419 validate_message(reply, 'kernel_info_reply', msg_id)
419 validate_message(reply, 'kernel_info_reply', msg_id)
420
420
421
421
422 def test_single_payload():
422 def test_single_payload():
423 flush_channels()
423 flush_channels()
424 msg_id, reply = execute(code="for i in range(3):\n"+
424 msg_id, reply = execute(code="for i in range(3):\n"+
425 " x=range?\n")
425 " x=range?\n")
426 payload = reply['payload']
426 payload = reply['payload']
427 next_input_pls = [pl for pl in payload if pl["source"] == "set_next_input"]
427 next_input_pls = [pl for pl in payload if pl["source"] == "set_next_input"]
428 nt.assert_equal(len(next_input_pls), 1)
428 nt.assert_equal(len(next_input_pls), 1)
429
429
430 def test_is_complete():
430 def test_is_complete():
431 flush_channels()
431 flush_channels()
432
432
433 msg_id = KC.is_complete("a = 1")
433 msg_id = KC.is_complete("a = 1")
434 reply = KC.get_shell_msg(timeout=TIMEOUT)
434 reply = KC.get_shell_msg(timeout=TIMEOUT)
435 validate_message(reply, 'is_complete_reply', msg_id)
435 validate_message(reply, 'is_complete_reply', msg_id)
436
436
437 def test_history_range():
437 def test_history_range():
438 flush_channels()
438 flush_channels()
439
439
440 msg_id_exec = KC.execute(code='x=1', store_history = True)
440 msg_id_exec = KC.execute(code='x=1', store_history = True)
441 reply_exec = KC.get_shell_msg(timeout=TIMEOUT)
441 reply_exec = KC.get_shell_msg(timeout=TIMEOUT)
442
442
443 msg_id = KC.history(hist_access_type = 'range', raw = True, output = True, start = 1, stop = 2, session = 0)
443 msg_id = KC.history(hist_access_type = 'range', raw = True, output = True, start = 1, stop = 2, session = 0)
444 reply = KC.get_shell_msg(timeout=TIMEOUT)
444 reply = KC.get_shell_msg(timeout=TIMEOUT)
445 validate_message(reply, 'history_reply', msg_id)
445 validate_message(reply, 'history_reply', msg_id)
446 content = reply['content']
446 content = reply['content']
447 nt.assert_equal(len(content['history']), 1)
447 nt.assert_equal(len(content['history']), 1)
448
448
449 def test_history_tail():
449 def test_history_tail():
450 flush_channels()
450 flush_channels()
451
451
452 msg_id_exec = KC.execute(code='x=1', store_history = True)
452 msg_id_exec = KC.execute(code='x=1', store_history = True)
453 reply_exec = KC.get_shell_msg(timeout=TIMEOUT)
453 reply_exec = KC.get_shell_msg(timeout=TIMEOUT)
454
454
455 msg_id = KC.history(hist_access_type = 'tail', raw = True, output = True, n = 1, session = 0)
455 msg_id = KC.history(hist_access_type = 'tail', raw = True, output = True, n = 1, session = 0)
456 reply = KC.get_shell_msg(timeout=TIMEOUT)
456 reply = KC.get_shell_msg(timeout=TIMEOUT)
457 validate_message(reply, 'history_reply', msg_id)
457 validate_message(reply, 'history_reply', msg_id)
458 content = reply['content']
458 content = reply['content']
459 nt.assert_equal(len(content['history']), 1)
459 nt.assert_equal(len(content['history']), 1)
460
460
461 def test_history_search():
461 def test_history_search():
462 flush_channels()
462 flush_channels()
463
463
464 msg_id_exec = KC.execute(code='x=1', store_history = True)
464 msg_id_exec = KC.execute(code='x=1', store_history = True)
465 reply_exec = KC.get_shell_msg(timeout=TIMEOUT)
465 reply_exec = KC.get_shell_msg(timeout=TIMEOUT)
466
466
467 msg_id = KC.history(hist_access_type = 'search', raw = True, output = True, n = 1, pattern = '*', session = 0)
467 msg_id = KC.history(hist_access_type = 'search', raw = True, output = True, n = 1, pattern = '*', session = 0)
468 reply = KC.get_shell_msg(timeout=TIMEOUT)
468 reply = KC.get_shell_msg(timeout=TIMEOUT)
469 validate_message(reply, 'history_reply', msg_id)
469 validate_message(reply, 'history_reply', msg_id)
470 content = reply['content']
470 content = reply['content']
471 nt.assert_equal(len(content['history']), 1)
471 nt.assert_equal(len(content['history']), 1)
472
472
473 # IOPub channel
473 # IOPub channel
474
474
475
475
476 def test_stream():
476 def test_stream():
477 flush_channels()
477 flush_channels()
478
478
479 msg_id, reply = execute("print('hi')")
479 msg_id, reply = execute("print('hi')")
480
480
481 stdout = KC.iopub_channel.get_msg(timeout=TIMEOUT)
481 stdout = KC.iopub_channel.get_msg(timeout=TIMEOUT)
482 validate_message(stdout, 'stream', msg_id)
482 validate_message(stdout, 'stream', msg_id)
483 content = stdout['content']
483 content = stdout['content']
484 nt.assert_equal(content['text'], u'hi\n')
484 nt.assert_equal(content['text'], u'hi\n')
485
485
486
486
487 def test_display_data():
487 def test_display_data():
488 flush_channels()
488 flush_channels()
489
489
490 msg_id, reply = execute("from IPython.core.display import display; display(1)")
490 msg_id, reply = execute("from IPython.core.display import display; display(1)")
491
491
492 display = KC.iopub_channel.get_msg(timeout=TIMEOUT)
492 display = KC.iopub_channel.get_msg(timeout=TIMEOUT)
493 validate_message(display, 'display_data', parent=msg_id)
493 validate_message(display, 'display_data', parent=msg_id)
494 data = display['content']['data']
494 data = display['content']['data']
495 nt.assert_equal(data['text/plain'], u'1')
495 nt.assert_equal(data['text/plain'], u'1')
496
496
@@ -1,578 +1,578
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """terminal client to the IPython kernel"""
2 """terminal client to the IPython kernel"""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7 from __future__ import print_function
7 from __future__ import print_function
8
8
9 import base64
9 import base64
10 import bdb
10 import bdb
11 import signal
11 import signal
12 import os
12 import os
13 import sys
13 import sys
14 import time
14 import time
15 import subprocess
15 import subprocess
16 from getpass import getpass
16 from getpass import getpass
17 from io import BytesIO
17 from io import BytesIO
18
18
19 try:
19 try:
20 from queue import Empty # Py 3
20 from queue import Empty # Py 3
21 except ImportError:
21 except ImportError:
22 from Queue import Empty # Py 2
22 from Queue import Empty # Py 2
23
23
24 from IPython.core import page
24 from IPython.core import page
25 from IPython.core import release
25 from IPython.core import release
26 from IPython.terminal.console.zmqhistory import ZMQHistoryManager
26 from IPython.terminal.console.zmqhistory import ZMQHistoryManager
27 from IPython.utils.warn import warn, error
27 from IPython.utils.warn import warn, error
28 from IPython.utils import io
28 from IPython.utils import io
29 from IPython.utils.py3compat import string_types, input
29 from IPython.utils.py3compat import string_types, input
30 from IPython.utils.traitlets import List, Enum, Any, Instance, Unicode, Float, Bool
30 from IPython.utils.traitlets import List, Enum, Any, Instance, Unicode, Float, Bool
31 from IPython.utils.tempdir import NamedFileInTemporaryDirectory
31 from IPython.utils.tempdir import NamedFileInTemporaryDirectory
32
32
33 from IPython.terminal.interactiveshell import TerminalInteractiveShell
33 from IPython.terminal.interactiveshell import TerminalInteractiveShell
34 from IPython.terminal.console.completer import ZMQCompleter
34 from IPython.terminal.console.completer import ZMQCompleter
35
35
36 class ZMQTerminalInteractiveShell(TerminalInteractiveShell):
36 class ZMQTerminalInteractiveShell(TerminalInteractiveShell):
37 """A subclass of TerminalInteractiveShell that uses the 0MQ kernel"""
37 """A subclass of TerminalInteractiveShell that uses the 0MQ kernel"""
38 _executing = False
38 _executing = False
39 _execution_state = Unicode('')
39 _execution_state = Unicode('')
40 _pending_clearoutput = False
40 _pending_clearoutput = False
41 kernel_banner = Unicode('')
41 kernel_banner = Unicode('')
42 kernel_timeout = Float(60, config=True,
42 kernel_timeout = Float(60, config=True,
43 help="""Timeout for giving up on a kernel (in seconds).
43 help="""Timeout for giving up on a kernel (in seconds).
44
44
45 On first connect and restart, the console tests whether the
45 On first connect and restart, the console tests whether the
46 kernel is running and responsive by sending kernel_info_requests.
46 kernel is running and responsive by sending kernel_info_requests.
47 This sets the timeout in seconds for how long the kernel can take
47 This sets the timeout in seconds for how long the kernel can take
48 before being presumed dead.
48 before being presumed dead.
49 """
49 """
50 )
50 )
51
51
52 image_handler = Enum(('PIL', 'stream', 'tempfile', 'callable'),
52 image_handler = Enum(('PIL', 'stream', 'tempfile', 'callable'),
53 config=True, help=
53 config=True, allow_none=True, help=
54 """
54 """
55 Handler for image type output. This is useful, for example,
55 Handler for image type output. This is useful, for example,
56 when connecting to the kernel in which pylab inline backend is
56 when connecting to the kernel in which pylab inline backend is
57 activated. There are four handlers defined. 'PIL': Use
57 activated. There are four handlers defined. 'PIL': Use
58 Python Imaging Library to popup image; 'stream': Use an
58 Python Imaging Library to popup image; 'stream': Use an
59 external program to show the image. Image will be fed into
59 external program to show the image. Image will be fed into
60 the STDIN of the program. You will need to configure
60 the STDIN of the program. You will need to configure
61 `stream_image_handler`; 'tempfile': Use an external program to
61 `stream_image_handler`; 'tempfile': Use an external program to
62 show the image. Image will be saved in a temporally file and
62 show the image. Image will be saved in a temporally file and
63 the program is called with the temporally file. You will need
63 the program is called with the temporally file. You will need
64 to configure `tempfile_image_handler`; 'callable': You can set
64 to configure `tempfile_image_handler`; 'callable': You can set
65 any Python callable which is called with the image data. You
65 any Python callable which is called with the image data. You
66 will need to configure `callable_image_handler`.
66 will need to configure `callable_image_handler`.
67 """
67 """
68 )
68 )
69
69
70 stream_image_handler = List(config=True, help=
70 stream_image_handler = List(config=True, help=
71 """
71 """
72 Command to invoke an image viewer program when you are using
72 Command to invoke an image viewer program when you are using
73 'stream' image handler. This option is a list of string where
73 'stream' image handler. This option is a list of string where
74 the first element is the command itself and reminders are the
74 the first element is the command itself and reminders are the
75 options for the command. Raw image data is given as STDIN to
75 options for the command. Raw image data is given as STDIN to
76 the program.
76 the program.
77 """
77 """
78 )
78 )
79
79
80 tempfile_image_handler = List(config=True, help=
80 tempfile_image_handler = List(config=True, help=
81 """
81 """
82 Command to invoke an image viewer program when you are using
82 Command to invoke an image viewer program when you are using
83 'tempfile' image handler. This option is a list of string
83 'tempfile' image handler. This option is a list of string
84 where the first element is the command itself and reminders
84 where the first element is the command itself and reminders
85 are the options for the command. You can use {file} and
85 are the options for the command. You can use {file} and
86 {format} in the string to represent the location of the
86 {format} in the string to represent the location of the
87 generated image file and image format.
87 generated image file and image format.
88 """
88 """
89 )
89 )
90
90
91 callable_image_handler = Any(config=True, help=
91 callable_image_handler = Any(config=True, help=
92 """
92 """
93 Callable object called via 'callable' image handler with one
93 Callable object called via 'callable' image handler with one
94 argument, `data`, which is `msg["content"]["data"]` where
94 argument, `data`, which is `msg["content"]["data"]` where
95 `msg` is the message from iopub channel. For exmaple, you can
95 `msg` is the message from iopub channel. For exmaple, you can
96 find base64 encoded PNG data as `data['image/png']`.
96 find base64 encoded PNG data as `data['image/png']`.
97 """
97 """
98 )
98 )
99
99
100 mime_preference = List(
100 mime_preference = List(
101 default_value=['image/png', 'image/jpeg', 'image/svg+xml'],
101 default_value=['image/png', 'image/jpeg', 'image/svg+xml'],
102 config=True, allow_none=False, help=
102 config=True, allow_none=False, help=
103 """
103 """
104 Preferred object representation MIME type in order. First
104 Preferred object representation MIME type in order. First
105 matched MIME type will be used.
105 matched MIME type will be used.
106 """
106 """
107 )
107 )
108
108
109 manager = Instance('IPython.kernel.KernelManager')
109 manager = Instance('IPython.kernel.KernelManager')
110 client = Instance('IPython.kernel.KernelClient')
110 client = Instance('IPython.kernel.KernelClient')
111 def _client_changed(self, name, old, new):
111 def _client_changed(self, name, old, new):
112 self.session_id = new.session.session
112 self.session_id = new.session.session
113 session_id = Unicode()
113 session_id = Unicode()
114
114
115 def init_completer(self):
115 def init_completer(self):
116 """Initialize the completion machinery.
116 """Initialize the completion machinery.
117
117
118 This creates completion machinery that can be used by client code,
118 This creates completion machinery that can be used by client code,
119 either interactively in-process (typically triggered by the readline
119 either interactively in-process (typically triggered by the readline
120 library), programmatically (such as in test suites) or out-of-process
120 library), programmatically (such as in test suites) or out-of-process
121 (typically over the network by remote frontends).
121 (typically over the network by remote frontends).
122 """
122 """
123 from IPython.core.completerlib import (module_completer,
123 from IPython.core.completerlib import (module_completer,
124 magic_run_completer, cd_completer)
124 magic_run_completer, cd_completer)
125
125
126 self.Completer = ZMQCompleter(self, self.client, config=self.config)
126 self.Completer = ZMQCompleter(self, self.client, config=self.config)
127
127
128
128
129 self.set_hook('complete_command', module_completer, str_key = 'import')
129 self.set_hook('complete_command', module_completer, str_key = 'import')
130 self.set_hook('complete_command', module_completer, str_key = 'from')
130 self.set_hook('complete_command', module_completer, str_key = 'from')
131 self.set_hook('complete_command', magic_run_completer, str_key = '%run')
131 self.set_hook('complete_command', magic_run_completer, str_key = '%run')
132 self.set_hook('complete_command', cd_completer, str_key = '%cd')
132 self.set_hook('complete_command', cd_completer, str_key = '%cd')
133
133
134 # Only configure readline if we truly are using readline. IPython can
134 # Only configure readline if we truly are using readline. IPython can
135 # do tab-completion over the network, in GUIs, etc, where readline
135 # do tab-completion over the network, in GUIs, etc, where readline
136 # itself may be absent
136 # itself may be absent
137 if self.has_readline:
137 if self.has_readline:
138 self.set_readline_completer()
138 self.set_readline_completer()
139
139
140 def run_cell(self, cell, store_history=True):
140 def run_cell(self, cell, store_history=True):
141 """Run a complete IPython cell.
141 """Run a complete IPython cell.
142
142
143 Parameters
143 Parameters
144 ----------
144 ----------
145 cell : str
145 cell : str
146 The code (including IPython code such as %magic functions) to run.
146 The code (including IPython code such as %magic functions) to run.
147 store_history : bool
147 store_history : bool
148 If True, the raw and translated cell will be stored in IPython's
148 If True, the raw and translated cell will be stored in IPython's
149 history. For user code calling back into IPython's machinery, this
149 history. For user code calling back into IPython's machinery, this
150 should be set to False.
150 should be set to False.
151 """
151 """
152 if (not cell) or cell.isspace():
152 if (not cell) or cell.isspace():
153 # pressing enter flushes any pending display
153 # pressing enter flushes any pending display
154 self.handle_iopub()
154 self.handle_iopub()
155 return
155 return
156
156
157 # flush stale replies, which could have been ignored, due to missed heartbeats
157 # flush stale replies, which could have been ignored, due to missed heartbeats
158 while self.client.shell_channel.msg_ready():
158 while self.client.shell_channel.msg_ready():
159 self.client.shell_channel.get_msg()
159 self.client.shell_channel.get_msg()
160 # execute takes 'hidden', which is the inverse of store_hist
160 # execute takes 'hidden', which is the inverse of store_hist
161 msg_id = self.client.execute(cell, not store_history)
161 msg_id = self.client.execute(cell, not store_history)
162
162
163 # first thing is wait for any side effects (output, stdin, etc.)
163 # first thing is wait for any side effects (output, stdin, etc.)
164 self._executing = True
164 self._executing = True
165 self._execution_state = "busy"
165 self._execution_state = "busy"
166 while self._execution_state != 'idle' and self.client.is_alive():
166 while self._execution_state != 'idle' and self.client.is_alive():
167 try:
167 try:
168 self.handle_input_request(msg_id, timeout=0.05)
168 self.handle_input_request(msg_id, timeout=0.05)
169 except Empty:
169 except Empty:
170 # display intermediate print statements, etc.
170 # display intermediate print statements, etc.
171 self.handle_iopub(msg_id)
171 self.handle_iopub(msg_id)
172
172
173 # after all of that is done, wait for the execute reply
173 # after all of that is done, wait for the execute reply
174 while self.client.is_alive():
174 while self.client.is_alive():
175 try:
175 try:
176 self.handle_execute_reply(msg_id, timeout=0.05)
176 self.handle_execute_reply(msg_id, timeout=0.05)
177 except Empty:
177 except Empty:
178 pass
178 pass
179 else:
179 else:
180 break
180 break
181 self._executing = False
181 self._executing = False
182
182
183 #-----------------
183 #-----------------
184 # message handlers
184 # message handlers
185 #-----------------
185 #-----------------
186
186
187 def handle_execute_reply(self, msg_id, timeout=None):
187 def handle_execute_reply(self, msg_id, timeout=None):
188 msg = self.client.shell_channel.get_msg(block=False, timeout=timeout)
188 msg = self.client.shell_channel.get_msg(block=False, timeout=timeout)
189 if msg["parent_header"].get("msg_id", None) == msg_id:
189 if msg["parent_header"].get("msg_id", None) == msg_id:
190
190
191 self.handle_iopub(msg_id)
191 self.handle_iopub(msg_id)
192
192
193 content = msg["content"]
193 content = msg["content"]
194 status = content['status']
194 status = content['status']
195
195
196 if status == 'aborted':
196 if status == 'aborted':
197 self.write('Aborted\n')
197 self.write('Aborted\n')
198 return
198 return
199 elif status == 'ok':
199 elif status == 'ok':
200 # handle payloads
200 # handle payloads
201 for item in content["payload"]:
201 for item in content["payload"]:
202 source = item['source']
202 source = item['source']
203 if source == 'page':
203 if source == 'page':
204 page.page(item['data']['text/plain'])
204 page.page(item['data']['text/plain'])
205 elif source == 'set_next_input':
205 elif source == 'set_next_input':
206 self.set_next_input(item['text'])
206 self.set_next_input(item['text'])
207 elif source == 'ask_exit':
207 elif source == 'ask_exit':
208 self.ask_exit()
208 self.ask_exit()
209
209
210 elif status == 'error':
210 elif status == 'error':
211 for frame in content["traceback"]:
211 for frame in content["traceback"]:
212 print(frame, file=io.stderr)
212 print(frame, file=io.stderr)
213
213
214 self.execution_count = int(content["execution_count"] + 1)
214 self.execution_count = int(content["execution_count"] + 1)
215
215
216 include_other_output = Bool(False, config=True,
216 include_other_output = Bool(False, config=True,
217 help="""Whether to include output from clients
217 help="""Whether to include output from clients
218 other than this one sharing the same kernel.
218 other than this one sharing the same kernel.
219
219
220 Outputs are not displayed until enter is pressed.
220 Outputs are not displayed until enter is pressed.
221 """
221 """
222 )
222 )
223 other_output_prefix = Unicode("[remote] ", config=True,
223 other_output_prefix = Unicode("[remote] ", config=True,
224 help="""Prefix to add to outputs coming from clients other than this one.
224 help="""Prefix to add to outputs coming from clients other than this one.
225
225
226 Only relevant if include_other_output is True.
226 Only relevant if include_other_output is True.
227 """
227 """
228 )
228 )
229
229
230 def from_here(self, msg):
230 def from_here(self, msg):
231 """Return whether a message is from this session"""
231 """Return whether a message is from this session"""
232 return msg['parent_header'].get("session", self.session_id) == self.session_id
232 return msg['parent_header'].get("session", self.session_id) == self.session_id
233
233
234 def include_output(self, msg):
234 def include_output(self, msg):
235 """Return whether we should include a given output message"""
235 """Return whether we should include a given output message"""
236 from_here = self.from_here(msg)
236 from_here = self.from_here(msg)
237 if msg['msg_type'] == 'execute_input':
237 if msg['msg_type'] == 'execute_input':
238 # only echo inputs not from here
238 # only echo inputs not from here
239 return self.include_other_output and not from_here
239 return self.include_other_output and not from_here
240
240
241 if self.include_other_output:
241 if self.include_other_output:
242 return True
242 return True
243 else:
243 else:
244 return from_here
244 return from_here
245
245
246 def handle_iopub(self, msg_id=''):
246 def handle_iopub(self, msg_id=''):
247 """Process messages on the IOPub channel
247 """Process messages on the IOPub channel
248
248
249 This method consumes and processes messages on the IOPub channel,
249 This method consumes and processes messages on the IOPub channel,
250 such as stdout, stderr, execute_result and status.
250 such as stdout, stderr, execute_result and status.
251
251
252 It only displays output that is caused by this session.
252 It only displays output that is caused by this session.
253 """
253 """
254 while self.client.iopub_channel.msg_ready():
254 while self.client.iopub_channel.msg_ready():
255 sub_msg = self.client.iopub_channel.get_msg()
255 sub_msg = self.client.iopub_channel.get_msg()
256 msg_type = sub_msg['header']['msg_type']
256 msg_type = sub_msg['header']['msg_type']
257 parent = sub_msg["parent_header"]
257 parent = sub_msg["parent_header"]
258
258
259 if self.include_output(sub_msg):
259 if self.include_output(sub_msg):
260 if msg_type == 'status':
260 if msg_type == 'status':
261 self._execution_state = sub_msg["content"]["execution_state"]
261 self._execution_state = sub_msg["content"]["execution_state"]
262 elif msg_type == 'stream':
262 elif msg_type == 'stream':
263 if sub_msg["content"]["name"] == "stdout":
263 if sub_msg["content"]["name"] == "stdout":
264 if self._pending_clearoutput:
264 if self._pending_clearoutput:
265 print("\r", file=io.stdout, end="")
265 print("\r", file=io.stdout, end="")
266 self._pending_clearoutput = False
266 self._pending_clearoutput = False
267 print(sub_msg["content"]["text"], file=io.stdout, end="")
267 print(sub_msg["content"]["text"], file=io.stdout, end="")
268 io.stdout.flush()
268 io.stdout.flush()
269 elif sub_msg["content"]["name"] == "stderr":
269 elif sub_msg["content"]["name"] == "stderr":
270 if self._pending_clearoutput:
270 if self._pending_clearoutput:
271 print("\r", file=io.stderr, end="")
271 print("\r", file=io.stderr, end="")
272 self._pending_clearoutput = False
272 self._pending_clearoutput = False
273 print(sub_msg["content"]["text"], file=io.stderr, end="")
273 print(sub_msg["content"]["text"], file=io.stderr, end="")
274 io.stderr.flush()
274 io.stderr.flush()
275
275
276 elif msg_type == 'execute_result':
276 elif msg_type == 'execute_result':
277 if self._pending_clearoutput:
277 if self._pending_clearoutput:
278 print("\r", file=io.stdout, end="")
278 print("\r", file=io.stdout, end="")
279 self._pending_clearoutput = False
279 self._pending_clearoutput = False
280 self.execution_count = int(sub_msg["content"]["execution_count"])
280 self.execution_count = int(sub_msg["content"]["execution_count"])
281 if not self.from_here(sub_msg):
281 if not self.from_here(sub_msg):
282 sys.stdout.write(self.other_output_prefix)
282 sys.stdout.write(self.other_output_prefix)
283 format_dict = sub_msg["content"]["data"]
283 format_dict = sub_msg["content"]["data"]
284 self.handle_rich_data(format_dict)
284 self.handle_rich_data(format_dict)
285
285
286 # taken from DisplayHook.__call__:
286 # taken from DisplayHook.__call__:
287 hook = self.displayhook
287 hook = self.displayhook
288 hook.start_displayhook()
288 hook.start_displayhook()
289 hook.write_output_prompt()
289 hook.write_output_prompt()
290 hook.write_format_data(format_dict)
290 hook.write_format_data(format_dict)
291 hook.log_output(format_dict)
291 hook.log_output(format_dict)
292 hook.finish_displayhook()
292 hook.finish_displayhook()
293
293
294 elif msg_type == 'display_data':
294 elif msg_type == 'display_data':
295 data = sub_msg["content"]["data"]
295 data = sub_msg["content"]["data"]
296 handled = self.handle_rich_data(data)
296 handled = self.handle_rich_data(data)
297 if not handled:
297 if not handled:
298 if not self.from_here(sub_msg):
298 if not self.from_here(sub_msg):
299 sys.stdout.write(self.other_output_prefix)
299 sys.stdout.write(self.other_output_prefix)
300 # if it was an image, we handled it by now
300 # if it was an image, we handled it by now
301 if 'text/plain' in data:
301 if 'text/plain' in data:
302 print(data['text/plain'])
302 print(data['text/plain'])
303
303
304 elif msg_type == 'execute_input':
304 elif msg_type == 'execute_input':
305 content = sub_msg['content']
305 content = sub_msg['content']
306 self.execution_count = content['execution_count']
306 self.execution_count = content['execution_count']
307 if not self.from_here(sub_msg):
307 if not self.from_here(sub_msg):
308 sys.stdout.write(self.other_output_prefix)
308 sys.stdout.write(self.other_output_prefix)
309 sys.stdout.write(self.prompt_manager.render('in'))
309 sys.stdout.write(self.prompt_manager.render('in'))
310 sys.stdout.write(content['code'])
310 sys.stdout.write(content['code'])
311
311
312 elif msg_type == 'clear_output':
312 elif msg_type == 'clear_output':
313 if sub_msg["content"]["wait"]:
313 if sub_msg["content"]["wait"]:
314 self._pending_clearoutput = True
314 self._pending_clearoutput = True
315 else:
315 else:
316 print("\r", file=io.stdout, end="")
316 print("\r", file=io.stdout, end="")
317
317
318 _imagemime = {
318 _imagemime = {
319 'image/png': 'png',
319 'image/png': 'png',
320 'image/jpeg': 'jpeg',
320 'image/jpeg': 'jpeg',
321 'image/svg+xml': 'svg',
321 'image/svg+xml': 'svg',
322 }
322 }
323
323
324 def handle_rich_data(self, data):
324 def handle_rich_data(self, data):
325 for mime in self.mime_preference:
325 for mime in self.mime_preference:
326 if mime in data and mime in self._imagemime:
326 if mime in data and mime in self._imagemime:
327 self.handle_image(data, mime)
327 self.handle_image(data, mime)
328 return True
328 return True
329
329
330 def handle_image(self, data, mime):
330 def handle_image(self, data, mime):
331 handler = getattr(
331 handler = getattr(
332 self, 'handle_image_{0}'.format(self.image_handler), None)
332 self, 'handle_image_{0}'.format(self.image_handler), None)
333 if handler:
333 if handler:
334 handler(data, mime)
334 handler(data, mime)
335
335
336 def handle_image_PIL(self, data, mime):
336 def handle_image_PIL(self, data, mime):
337 if mime not in ('image/png', 'image/jpeg'):
337 if mime not in ('image/png', 'image/jpeg'):
338 return
338 return
339 import PIL.Image
339 import PIL.Image
340 raw = base64.decodestring(data[mime].encode('ascii'))
340 raw = base64.decodestring(data[mime].encode('ascii'))
341 img = PIL.Image.open(BytesIO(raw))
341 img = PIL.Image.open(BytesIO(raw))
342 img.show()
342 img.show()
343
343
344 def handle_image_stream(self, data, mime):
344 def handle_image_stream(self, data, mime):
345 raw = base64.decodestring(data[mime].encode('ascii'))
345 raw = base64.decodestring(data[mime].encode('ascii'))
346 imageformat = self._imagemime[mime]
346 imageformat = self._imagemime[mime]
347 fmt = dict(format=imageformat)
347 fmt = dict(format=imageformat)
348 args = [s.format(**fmt) for s in self.stream_image_handler]
348 args = [s.format(**fmt) for s in self.stream_image_handler]
349 with open(os.devnull, 'w') as devnull:
349 with open(os.devnull, 'w') as devnull:
350 proc = subprocess.Popen(
350 proc = subprocess.Popen(
351 args, stdin=subprocess.PIPE,
351 args, stdin=subprocess.PIPE,
352 stdout=devnull, stderr=devnull)
352 stdout=devnull, stderr=devnull)
353 proc.communicate(raw)
353 proc.communicate(raw)
354
354
355 def handle_image_tempfile(self, data, mime):
355 def handle_image_tempfile(self, data, mime):
356 raw = base64.decodestring(data[mime].encode('ascii'))
356 raw = base64.decodestring(data[mime].encode('ascii'))
357 imageformat = self._imagemime[mime]
357 imageformat = self._imagemime[mime]
358 filename = 'tmp.{0}'.format(imageformat)
358 filename = 'tmp.{0}'.format(imageformat)
359 with NamedFileInTemporaryDirectory(filename) as f, \
359 with NamedFileInTemporaryDirectory(filename) as f, \
360 open(os.devnull, 'w') as devnull:
360 open(os.devnull, 'w') as devnull:
361 f.write(raw)
361 f.write(raw)
362 f.flush()
362 f.flush()
363 fmt = dict(file=f.name, format=imageformat)
363 fmt = dict(file=f.name, format=imageformat)
364 args = [s.format(**fmt) for s in self.tempfile_image_handler]
364 args = [s.format(**fmt) for s in self.tempfile_image_handler]
365 subprocess.call(args, stdout=devnull, stderr=devnull)
365 subprocess.call(args, stdout=devnull, stderr=devnull)
366
366
367 def handle_image_callable(self, data, mime):
367 def handle_image_callable(self, data, mime):
368 self.callable_image_handler(data)
368 self.callable_image_handler(data)
369
369
370 def handle_input_request(self, msg_id, timeout=0.1):
370 def handle_input_request(self, msg_id, timeout=0.1):
371 """ Method to capture raw_input
371 """ Method to capture raw_input
372 """
372 """
373 req = self.client.stdin_channel.get_msg(timeout=timeout)
373 req = self.client.stdin_channel.get_msg(timeout=timeout)
374 # in case any iopub came while we were waiting:
374 # in case any iopub came while we were waiting:
375 self.handle_iopub(msg_id)
375 self.handle_iopub(msg_id)
376 if msg_id == req["parent_header"].get("msg_id"):
376 if msg_id == req["parent_header"].get("msg_id"):
377 # wrap SIGINT handler
377 # wrap SIGINT handler
378 real_handler = signal.getsignal(signal.SIGINT)
378 real_handler = signal.getsignal(signal.SIGINT)
379 def double_int(sig,frame):
379 def double_int(sig,frame):
380 # call real handler (forwards sigint to kernel),
380 # call real handler (forwards sigint to kernel),
381 # then raise local interrupt, stopping local raw_input
381 # then raise local interrupt, stopping local raw_input
382 real_handler(sig,frame)
382 real_handler(sig,frame)
383 raise KeyboardInterrupt
383 raise KeyboardInterrupt
384 signal.signal(signal.SIGINT, double_int)
384 signal.signal(signal.SIGINT, double_int)
385 content = req['content']
385 content = req['content']
386 read = getpass if content.get('password', False) else input
386 read = getpass if content.get('password', False) else input
387 try:
387 try:
388 raw_data = read(content["prompt"])
388 raw_data = read(content["prompt"])
389 except EOFError:
389 except EOFError:
390 # turn EOFError into EOF character
390 # turn EOFError into EOF character
391 raw_data = '\x04'
391 raw_data = '\x04'
392 except KeyboardInterrupt:
392 except KeyboardInterrupt:
393 sys.stdout.write('\n')
393 sys.stdout.write('\n')
394 return
394 return
395 finally:
395 finally:
396 # restore SIGINT handler
396 # restore SIGINT handler
397 signal.signal(signal.SIGINT, real_handler)
397 signal.signal(signal.SIGINT, real_handler)
398
398
399 # only send stdin reply if there *was not* another request
399 # only send stdin reply if there *was not* another request
400 # or execution finished while we were reading.
400 # or execution finished while we were reading.
401 if not (self.client.stdin_channel.msg_ready() or self.client.shell_channel.msg_ready()):
401 if not (self.client.stdin_channel.msg_ready() or self.client.shell_channel.msg_ready()):
402 self.client.input(raw_data)
402 self.client.input(raw_data)
403
403
404 def mainloop(self, display_banner=False):
404 def mainloop(self, display_banner=False):
405 while True:
405 while True:
406 try:
406 try:
407 self.interact(display_banner=display_banner)
407 self.interact(display_banner=display_banner)
408 #self.interact_with_readline()
408 #self.interact_with_readline()
409 # XXX for testing of a readline-decoupled repl loop, call
409 # XXX for testing of a readline-decoupled repl loop, call
410 # interact_with_readline above
410 # interact_with_readline above
411 break
411 break
412 except KeyboardInterrupt:
412 except KeyboardInterrupt:
413 # this should not be necessary, but KeyboardInterrupt
413 # this should not be necessary, but KeyboardInterrupt
414 # handling seems rather unpredictable...
414 # handling seems rather unpredictable...
415 self.write("\nKeyboardInterrupt in interact()\n")
415 self.write("\nKeyboardInterrupt in interact()\n")
416
416
417 self.client.shutdown()
417 self.client.shutdown()
418
418
419 def _banner1_default(self):
419 def _banner1_default(self):
420 return "IPython Console {version}\n".format(version=release.version)
420 return "IPython Console {version}\n".format(version=release.version)
421
421
422 def compute_banner(self):
422 def compute_banner(self):
423 super(ZMQTerminalInteractiveShell, self).compute_banner()
423 super(ZMQTerminalInteractiveShell, self).compute_banner()
424 if self.client and not self.kernel_banner:
424 if self.client and not self.kernel_banner:
425 msg_id = self.client.kernel_info()
425 msg_id = self.client.kernel_info()
426 while True:
426 while True:
427 try:
427 try:
428 reply = self.client.get_shell_msg(timeout=1)
428 reply = self.client.get_shell_msg(timeout=1)
429 except Empty:
429 except Empty:
430 break
430 break
431 else:
431 else:
432 if reply['parent_header'].get('msg_id') == msg_id:
432 if reply['parent_header'].get('msg_id') == msg_id:
433 self.kernel_banner = reply['content'].get('banner', '')
433 self.kernel_banner = reply['content'].get('banner', '')
434 break
434 break
435 self.banner += self.kernel_banner
435 self.banner += self.kernel_banner
436
436
437 def wait_for_kernel(self, timeout=None):
437 def wait_for_kernel(self, timeout=None):
438 """method to wait for a kernel to be ready"""
438 """method to wait for a kernel to be ready"""
439 tic = time.time()
439 tic = time.time()
440 self.client.hb_channel.unpause()
440 self.client.hb_channel.unpause()
441 while True:
441 while True:
442 msg_id = self.client.kernel_info()
442 msg_id = self.client.kernel_info()
443 reply = None
443 reply = None
444 while True:
444 while True:
445 try:
445 try:
446 reply = self.client.get_shell_msg(timeout=1)
446 reply = self.client.get_shell_msg(timeout=1)
447 except Empty:
447 except Empty:
448 break
448 break
449 else:
449 else:
450 if reply['parent_header'].get('msg_id') == msg_id:
450 if reply['parent_header'].get('msg_id') == msg_id:
451 return True
451 return True
452 if timeout is not None \
452 if timeout is not None \
453 and (time.time() - tic) > timeout \
453 and (time.time() - tic) > timeout \
454 and not self.client.hb_channel.is_beating():
454 and not self.client.hb_channel.is_beating():
455 # heart failed
455 # heart failed
456 return False
456 return False
457 return True
457 return True
458
458
459 def interact(self, display_banner=None):
459 def interact(self, display_banner=None):
460 """Closely emulate the interactive Python console."""
460 """Closely emulate the interactive Python console."""
461
461
462 # batch run -> do not interact
462 # batch run -> do not interact
463 if self.exit_now:
463 if self.exit_now:
464 return
464 return
465
465
466 if display_banner is None:
466 if display_banner is None:
467 display_banner = self.display_banner
467 display_banner = self.display_banner
468
468
469 if isinstance(display_banner, string_types):
469 if isinstance(display_banner, string_types):
470 self.show_banner(display_banner)
470 self.show_banner(display_banner)
471 elif display_banner:
471 elif display_banner:
472 self.show_banner()
472 self.show_banner()
473
473
474 more = False
474 more = False
475
475
476 # run a non-empty no-op, so that we don't get a prompt until
476 # run a non-empty no-op, so that we don't get a prompt until
477 # we know the kernel is ready. This keeps the connection
477 # we know the kernel is ready. This keeps the connection
478 # message above the first prompt.
478 # message above the first prompt.
479 if not self.wait_for_kernel(self.kernel_timeout):
479 if not self.wait_for_kernel(self.kernel_timeout):
480 error("Kernel did not respond\n")
480 error("Kernel did not respond\n")
481 return
481 return
482
482
483 if self.has_readline:
483 if self.has_readline:
484 self.readline_startup_hook(self.pre_readline)
484 self.readline_startup_hook(self.pre_readline)
485 hlen_b4_cell = self.readline.get_current_history_length()
485 hlen_b4_cell = self.readline.get_current_history_length()
486 else:
486 else:
487 hlen_b4_cell = 0
487 hlen_b4_cell = 0
488 # exit_now is set by a call to %Exit or %Quit, through the
488 # exit_now is set by a call to %Exit or %Quit, through the
489 # ask_exit callback.
489 # ask_exit callback.
490
490
491 while not self.exit_now:
491 while not self.exit_now:
492 if not self.client.is_alive():
492 if not self.client.is_alive():
493 # kernel died, prompt for action or exit
493 # kernel died, prompt for action or exit
494
494
495 action = "restart" if self.manager else "wait for restart"
495 action = "restart" if self.manager else "wait for restart"
496 ans = self.ask_yes_no("kernel died, %s ([y]/n)?" % action, default='y')
496 ans = self.ask_yes_no("kernel died, %s ([y]/n)?" % action, default='y')
497 if ans:
497 if ans:
498 if self.manager:
498 if self.manager:
499 self.manager.restart_kernel(True)
499 self.manager.restart_kernel(True)
500 self.wait_for_kernel(self.kernel_timeout)
500 self.wait_for_kernel(self.kernel_timeout)
501 else:
501 else:
502 self.exit_now = True
502 self.exit_now = True
503 continue
503 continue
504 try:
504 try:
505 # protect prompt block from KeyboardInterrupt
505 # protect prompt block from KeyboardInterrupt
506 # when sitting on ctrl-C
506 # when sitting on ctrl-C
507 self.hooks.pre_prompt_hook()
507 self.hooks.pre_prompt_hook()
508 if more:
508 if more:
509 try:
509 try:
510 prompt = self.prompt_manager.render('in2')
510 prompt = self.prompt_manager.render('in2')
511 except Exception:
511 except Exception:
512 self.showtraceback()
512 self.showtraceback()
513 if self.autoindent:
513 if self.autoindent:
514 self.rl_do_indent = True
514 self.rl_do_indent = True
515
515
516 else:
516 else:
517 try:
517 try:
518 prompt = self.separate_in + self.prompt_manager.render('in')
518 prompt = self.separate_in + self.prompt_manager.render('in')
519 except Exception:
519 except Exception:
520 self.showtraceback()
520 self.showtraceback()
521
521
522 line = self.raw_input(prompt)
522 line = self.raw_input(prompt)
523 if self.exit_now:
523 if self.exit_now:
524 # quick exit on sys.std[in|out] close
524 # quick exit on sys.std[in|out] close
525 break
525 break
526 if self.autoindent:
526 if self.autoindent:
527 self.rl_do_indent = False
527 self.rl_do_indent = False
528
528
529 except KeyboardInterrupt:
529 except KeyboardInterrupt:
530 #double-guard against keyboardinterrupts during kbdint handling
530 #double-guard against keyboardinterrupts during kbdint handling
531 try:
531 try:
532 self.write('\n' + self.get_exception_only())
532 self.write('\n' + self.get_exception_only())
533 source_raw = self.input_splitter.raw_reset()
533 source_raw = self.input_splitter.raw_reset()
534 hlen_b4_cell = self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
534 hlen_b4_cell = self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
535 more = False
535 more = False
536 except KeyboardInterrupt:
536 except KeyboardInterrupt:
537 pass
537 pass
538 except EOFError:
538 except EOFError:
539 if self.autoindent:
539 if self.autoindent:
540 self.rl_do_indent = False
540 self.rl_do_indent = False
541 if self.has_readline:
541 if self.has_readline:
542 self.readline_startup_hook(None)
542 self.readline_startup_hook(None)
543 self.write('\n')
543 self.write('\n')
544 self.exit()
544 self.exit()
545 except bdb.BdbQuit:
545 except bdb.BdbQuit:
546 warn('The Python debugger has exited with a BdbQuit exception.\n'
546 warn('The Python debugger has exited with a BdbQuit exception.\n'
547 'Because of how pdb handles the stack, it is impossible\n'
547 'Because of how pdb handles the stack, it is impossible\n'
548 'for IPython to properly format this particular exception.\n'
548 'for IPython to properly format this particular exception.\n'
549 'IPython will resume normal operation.')
549 'IPython will resume normal operation.')
550 except:
550 except:
551 # exceptions here are VERY RARE, but they can be triggered
551 # exceptions here are VERY RARE, but they can be triggered
552 # asynchronously by signal handlers, for example.
552 # asynchronously by signal handlers, for example.
553 self.showtraceback()
553 self.showtraceback()
554 else:
554 else:
555 try:
555 try:
556 self.input_splitter.push(line)
556 self.input_splitter.push(line)
557 more = self.input_splitter.push_accepts_more()
557 more = self.input_splitter.push_accepts_more()
558 except SyntaxError:
558 except SyntaxError:
559 # Run the code directly - run_cell takes care of displaying
559 # Run the code directly - run_cell takes care of displaying
560 # the exception.
560 # the exception.
561 more = False
561 more = False
562 if (self.SyntaxTB.last_syntax_error and
562 if (self.SyntaxTB.last_syntax_error and
563 self.autoedit_syntax):
563 self.autoedit_syntax):
564 self.edit_syntax_error()
564 self.edit_syntax_error()
565 if not more:
565 if not more:
566 source_raw = self.input_splitter.raw_reset()
566 source_raw = self.input_splitter.raw_reset()
567 hlen_b4_cell = self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
567 hlen_b4_cell = self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
568 self.run_cell(source_raw)
568 self.run_cell(source_raw)
569
569
570
570
571 # Turn off the exit flag, so the mainloop can be restarted if desired
571 # Turn off the exit flag, so the mainloop can be restarted if desired
572 self.exit_now = False
572 self.exit_now = False
573
573
574 def init_history(self):
574 def init_history(self):
575 """Sets up the command history. """
575 """Sets up the command history. """
576 self.history_manager = ZMQHistoryManager(client=self.client)
576 self.history_manager = ZMQHistoryManager(client=self.client)
577 self.configurables.append(self.history_manager)
577 self.configurables.append(self.history_manager)
578
578
General Comments 0
You need to be logged in to leave comments. Login now