##// END OF EJS Templates
flush output before showing tracebacks...
MinRK -
Show More
@@ -1,572 +1,575 b''
1 """A ZMQ-based subclass of InteractiveShell.
1 """A ZMQ-based subclass of InteractiveShell.
2
2
3 This code is meant to ease the refactoring of the base InteractiveShell into
3 This code is meant to ease the refactoring of the base InteractiveShell into
4 something with a cleaner architecture for 2-process use, without actually
4 something with a cleaner architecture for 2-process use, without actually
5 breaking InteractiveShell itself. So we're doing something a bit ugly, where
5 breaking InteractiveShell itself. So we're doing something a bit ugly, where
6 we subclass and override what we want to fix. Once this is working well, we
6 we subclass and override what we want to fix. Once this is working well, we
7 can go back to the base class and refactor the code for a cleaner inheritance
7 can go back to the base class and refactor the code for a cleaner inheritance
8 implementation that doesn't rely on so much monkeypatching.
8 implementation that doesn't rely on so much monkeypatching.
9
9
10 But this lets us maintain a fully working IPython as we develop the new
10 But this lets us maintain a fully working IPython as we develop the new
11 machinery. This should thus be thought of as scaffolding.
11 machinery. This should thus be thought of as scaffolding.
12 """
12 """
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from __future__ import print_function
16 from __future__ import print_function
17
17
18 # Stdlib
18 # Stdlib
19 import os
19 import os
20 import sys
20 import sys
21 import time
21 import time
22
22
23 # System library imports
23 # System library imports
24 from zmq.eventloop import ioloop
24 from zmq.eventloop import ioloop
25
25
26 # Our own
26 # Our own
27 from IPython.core.interactiveshell import (
27 from IPython.core.interactiveshell import (
28 InteractiveShell, InteractiveShellABC
28 InteractiveShell, InteractiveShellABC
29 )
29 )
30 from IPython.core import page
30 from IPython.core import page
31 from IPython.core.autocall import ZMQExitAutocall
31 from IPython.core.autocall import ZMQExitAutocall
32 from IPython.core.displaypub import DisplayPublisher
32 from IPython.core.displaypub import DisplayPublisher
33 from IPython.core.error import UsageError
33 from IPython.core.error import UsageError
34 from IPython.core.magics import MacroToEdit, CodeMagics
34 from IPython.core.magics import MacroToEdit, CodeMagics
35 from IPython.core.magic import magics_class, line_magic, Magics
35 from IPython.core.magic import magics_class, line_magic, Magics
36 from IPython.core.payloadpage import install_payload_page
36 from IPython.core.payloadpage import install_payload_page
37 from IPython.display import display, Javascript
37 from IPython.display import display, Javascript
38 from IPython.kernel.inprocess.socket import SocketABC
38 from IPython.kernel.inprocess.socket import SocketABC
39 from IPython.kernel import (
39 from IPython.kernel import (
40 get_connection_file, get_connection_info, connect_qtconsole
40 get_connection_file, get_connection_info, connect_qtconsole
41 )
41 )
42 from IPython.testing.skipdoctest import skip_doctest
42 from IPython.testing.skipdoctest import skip_doctest
43 from IPython.utils import openpy
43 from IPython.utils import openpy
44 from IPython.utils.jsonutil import json_clean, encode_images
44 from IPython.utils.jsonutil import json_clean, encode_images
45 from IPython.utils.process import arg_split
45 from IPython.utils.process import arg_split
46 from IPython.utils import py3compat
46 from IPython.utils import py3compat
47 from IPython.utils.py3compat import unicode_type
47 from IPython.utils.py3compat import unicode_type
48 from IPython.utils.traitlets import Instance, Type, Dict, CBool, CBytes, Any
48 from IPython.utils.traitlets import Instance, Type, Dict, CBool, CBytes, Any
49 from IPython.utils.warn import error
49 from IPython.utils.warn import error
50 from IPython.kernel.zmq.displayhook import ZMQShellDisplayHook
50 from IPython.kernel.zmq.displayhook import ZMQShellDisplayHook
51 from IPython.kernel.zmq.datapub import ZMQDataPublisher
51 from IPython.kernel.zmq.datapub import ZMQDataPublisher
52 from IPython.kernel.zmq.session import extract_header
52 from IPython.kernel.zmq.session import extract_header
53 from IPython.kernel.comm import CommManager
53 from IPython.kernel.comm import CommManager
54 from .session import Session
54 from .session import Session
55
55
56 #-----------------------------------------------------------------------------
56 #-----------------------------------------------------------------------------
57 # Functions and classes
57 # Functions and classes
58 #-----------------------------------------------------------------------------
58 #-----------------------------------------------------------------------------
59
59
60 class ZMQDisplayPublisher(DisplayPublisher):
60 class ZMQDisplayPublisher(DisplayPublisher):
61 """A display publisher that publishes data using a ZeroMQ PUB socket."""
61 """A display publisher that publishes data using a ZeroMQ PUB socket."""
62
62
63 session = Instance(Session)
63 session = Instance(Session)
64 pub_socket = Instance(SocketABC)
64 pub_socket = Instance(SocketABC)
65 parent_header = Dict({})
65 parent_header = Dict({})
66 topic = CBytes(b'display_data')
66 topic = CBytes(b'display_data')
67
67
68 def set_parent(self, parent):
68 def set_parent(self, parent):
69 """Set the parent for outbound messages."""
69 """Set the parent for outbound messages."""
70 self.parent_header = extract_header(parent)
70 self.parent_header = extract_header(parent)
71
71
72 def _flush_streams(self):
72 def _flush_streams(self):
73 """flush IO Streams prior to display"""
73 """flush IO Streams prior to display"""
74 sys.stdout.flush()
74 sys.stdout.flush()
75 sys.stderr.flush()
75 sys.stderr.flush()
76
76
77 def publish(self, source, data, metadata=None):
77 def publish(self, source, data, metadata=None):
78 self._flush_streams()
78 self._flush_streams()
79 if metadata is None:
79 if metadata is None:
80 metadata = {}
80 metadata = {}
81 self._validate_data(source, data, metadata)
81 self._validate_data(source, data, metadata)
82 content = {}
82 content = {}
83 content['source'] = source
83 content['source'] = source
84 content['data'] = encode_images(data)
84 content['data'] = encode_images(data)
85 content['metadata'] = metadata
85 content['metadata'] = metadata
86 self.session.send(
86 self.session.send(
87 self.pub_socket, u'display_data', json_clean(content),
87 self.pub_socket, u'display_data', json_clean(content),
88 parent=self.parent_header, ident=self.topic,
88 parent=self.parent_header, ident=self.topic,
89 )
89 )
90
90
91 def clear_output(self, wait=False):
91 def clear_output(self, wait=False):
92 content = dict(wait=wait)
92 content = dict(wait=wait)
93
93
94 print('\r', file=sys.stdout, end='')
94 print('\r', file=sys.stdout, end='')
95 print('\r', file=sys.stderr, end='')
95 print('\r', file=sys.stderr, end='')
96 self._flush_streams()
96 self._flush_streams()
97
97
98 self.session.send(
98 self.session.send(
99 self.pub_socket, u'clear_output', content,
99 self.pub_socket, u'clear_output', content,
100 parent=self.parent_header, ident=self.topic,
100 parent=self.parent_header, ident=self.topic,
101 )
101 )
102
102
103 @magics_class
103 @magics_class
104 class KernelMagics(Magics):
104 class KernelMagics(Magics):
105 #------------------------------------------------------------------------
105 #------------------------------------------------------------------------
106 # Magic overrides
106 # Magic overrides
107 #------------------------------------------------------------------------
107 #------------------------------------------------------------------------
108 # Once the base class stops inheriting from magic, this code needs to be
108 # Once the base class stops inheriting from magic, this code needs to be
109 # moved into a separate machinery as well. For now, at least isolate here
109 # moved into a separate machinery as well. For now, at least isolate here
110 # the magics which this class needs to implement differently from the base
110 # the magics which this class needs to implement differently from the base
111 # class, or that are unique to it.
111 # class, or that are unique to it.
112
112
113 @line_magic
113 @line_magic
114 def doctest_mode(self, parameter_s=''):
114 def doctest_mode(self, parameter_s=''):
115 """Toggle doctest mode on and off.
115 """Toggle doctest mode on and off.
116
116
117 This mode is intended to make IPython behave as much as possible like a
117 This mode is intended to make IPython behave as much as possible like a
118 plain Python shell, from the perspective of how its prompts, exceptions
118 plain Python shell, from the perspective of how its prompts, exceptions
119 and output look. This makes it easy to copy and paste parts of a
119 and output look. This makes it easy to copy and paste parts of a
120 session into doctests. It does so by:
120 session into doctests. It does so by:
121
121
122 - Changing the prompts to the classic ``>>>`` ones.
122 - Changing the prompts to the classic ``>>>`` ones.
123 - Changing the exception reporting mode to 'Plain'.
123 - Changing the exception reporting mode to 'Plain'.
124 - Disabling pretty-printing of output.
124 - Disabling pretty-printing of output.
125
125
126 Note that IPython also supports the pasting of code snippets that have
126 Note that IPython also supports the pasting of code snippets that have
127 leading '>>>' and '...' prompts in them. This means that you can paste
127 leading '>>>' and '...' prompts in them. This means that you can paste
128 doctests from files or docstrings (even if they have leading
128 doctests from files or docstrings (even if they have leading
129 whitespace), and the code will execute correctly. You can then use
129 whitespace), and the code will execute correctly. You can then use
130 '%history -t' to see the translated history; this will give you the
130 '%history -t' to see the translated history; this will give you the
131 input after removal of all the leading prompts and whitespace, which
131 input after removal of all the leading prompts and whitespace, which
132 can be pasted back into an editor.
132 can be pasted back into an editor.
133
133
134 With these features, you can switch into this mode easily whenever you
134 With these features, you can switch into this mode easily whenever you
135 need to do testing and changes to doctests, without having to leave
135 need to do testing and changes to doctests, without having to leave
136 your existing IPython session.
136 your existing IPython session.
137 """
137 """
138
138
139 from IPython.utils.ipstruct import Struct
139 from IPython.utils.ipstruct import Struct
140
140
141 # Shorthands
141 # Shorthands
142 shell = self.shell
142 shell = self.shell
143 disp_formatter = self.shell.display_formatter
143 disp_formatter = self.shell.display_formatter
144 ptformatter = disp_formatter.formatters['text/plain']
144 ptformatter = disp_formatter.formatters['text/plain']
145 # dstore is a data store kept in the instance metadata bag to track any
145 # dstore is a data store kept in the instance metadata bag to track any
146 # changes we make, so we can undo them later.
146 # changes we make, so we can undo them later.
147 dstore = shell.meta.setdefault('doctest_mode', Struct())
147 dstore = shell.meta.setdefault('doctest_mode', Struct())
148 save_dstore = dstore.setdefault
148 save_dstore = dstore.setdefault
149
149
150 # save a few values we'll need to recover later
150 # save a few values we'll need to recover later
151 mode = save_dstore('mode', False)
151 mode = save_dstore('mode', False)
152 save_dstore('rc_pprint', ptformatter.pprint)
152 save_dstore('rc_pprint', ptformatter.pprint)
153 save_dstore('rc_active_types',disp_formatter.active_types)
153 save_dstore('rc_active_types',disp_formatter.active_types)
154 save_dstore('xmode', shell.InteractiveTB.mode)
154 save_dstore('xmode', shell.InteractiveTB.mode)
155
155
156 if mode == False:
156 if mode == False:
157 # turn on
157 # turn on
158 ptformatter.pprint = False
158 ptformatter.pprint = False
159 disp_formatter.active_types = ['text/plain']
159 disp_formatter.active_types = ['text/plain']
160 shell.magic('xmode Plain')
160 shell.magic('xmode Plain')
161 else:
161 else:
162 # turn off
162 # turn off
163 ptformatter.pprint = dstore.rc_pprint
163 ptformatter.pprint = dstore.rc_pprint
164 disp_formatter.active_types = dstore.rc_active_types
164 disp_formatter.active_types = dstore.rc_active_types
165 shell.magic("xmode " + dstore.xmode)
165 shell.magic("xmode " + dstore.xmode)
166
166
167 # Store new mode and inform on console
167 # Store new mode and inform on console
168 dstore.mode = bool(1-int(mode))
168 dstore.mode = bool(1-int(mode))
169 mode_label = ['OFF','ON'][dstore.mode]
169 mode_label = ['OFF','ON'][dstore.mode]
170 print('Doctest mode is:', mode_label)
170 print('Doctest mode is:', mode_label)
171
171
172 # Send the payload back so that clients can modify their prompt display
172 # Send the payload back so that clients can modify their prompt display
173 payload = dict(
173 payload = dict(
174 source='doctest_mode',
174 source='doctest_mode',
175 mode=dstore.mode)
175 mode=dstore.mode)
176 shell.payload_manager.write_payload(payload)
176 shell.payload_manager.write_payload(payload)
177
177
178
178
179 _find_edit_target = CodeMagics._find_edit_target
179 _find_edit_target = CodeMagics._find_edit_target
180
180
181 @skip_doctest
181 @skip_doctest
182 @line_magic
182 @line_magic
183 def edit(self, parameter_s='', last_call=['','']):
183 def edit(self, parameter_s='', last_call=['','']):
184 """Bring up an editor and execute the resulting code.
184 """Bring up an editor and execute the resulting code.
185
185
186 Usage:
186 Usage:
187 %edit [options] [args]
187 %edit [options] [args]
188
188
189 %edit runs an external text editor. You will need to set the command for
189 %edit runs an external text editor. You will need to set the command for
190 this editor via the ``TerminalInteractiveShell.editor`` option in your
190 this editor via the ``TerminalInteractiveShell.editor`` option in your
191 configuration file before it will work.
191 configuration file before it will work.
192
192
193 This command allows you to conveniently edit multi-line code right in
193 This command allows you to conveniently edit multi-line code right in
194 your IPython session.
194 your IPython session.
195
195
196 If called without arguments, %edit opens up an empty editor with a
196 If called without arguments, %edit opens up an empty editor with a
197 temporary file and will execute the contents of this file when you
197 temporary file and will execute the contents of this file when you
198 close it (don't forget to save it!).
198 close it (don't forget to save it!).
199
199
200 Options:
200 Options:
201
201
202 -n <number>
202 -n <number>
203 Open the editor at a specified line number. By default, the IPython
203 Open the editor at a specified line number. By default, the IPython
204 editor hook uses the unix syntax 'editor +N filename', but you can
204 editor hook uses the unix syntax 'editor +N filename', but you can
205 configure this by providing your own modified hook if your favorite
205 configure this by providing your own modified hook if your favorite
206 editor supports line-number specifications with a different syntax.
206 editor supports line-number specifications with a different syntax.
207
207
208 -p
208 -p
209 Call the editor with the same data as the previous time it was used,
209 Call the editor with the same data as the previous time it was used,
210 regardless of how long ago (in your current session) it was.
210 regardless of how long ago (in your current session) it was.
211
211
212 -r
212 -r
213 Use 'raw' input. This option only applies to input taken from the
213 Use 'raw' input. This option only applies to input taken from the
214 user's history. By default, the 'processed' history is used, so that
214 user's history. By default, the 'processed' history is used, so that
215 magics are loaded in their transformed version to valid Python. If
215 magics are loaded in their transformed version to valid Python. If
216 this option is given, the raw input as typed as the command line is
216 this option is given, the raw input as typed as the command line is
217 used instead. When you exit the editor, it will be executed by
217 used instead. When you exit the editor, it will be executed by
218 IPython's own processor.
218 IPython's own processor.
219
219
220 Arguments:
220 Arguments:
221
221
222 If arguments are given, the following possibilites exist:
222 If arguments are given, the following possibilites exist:
223
223
224 - The arguments are numbers or pairs of colon-separated numbers (like
224 - The arguments are numbers or pairs of colon-separated numbers (like
225 1 4:8 9). These are interpreted as lines of previous input to be
225 1 4:8 9). These are interpreted as lines of previous input to be
226 loaded into the editor. The syntax is the same of the %macro command.
226 loaded into the editor. The syntax is the same of the %macro command.
227
227
228 - If the argument doesn't start with a number, it is evaluated as a
228 - If the argument doesn't start with a number, it is evaluated as a
229 variable and its contents loaded into the editor. You can thus edit
229 variable and its contents loaded into the editor. You can thus edit
230 any string which contains python code (including the result of
230 any string which contains python code (including the result of
231 previous edits).
231 previous edits).
232
232
233 - If the argument is the name of an object (other than a string),
233 - If the argument is the name of an object (other than a string),
234 IPython will try to locate the file where it was defined and open the
234 IPython will try to locate the file where it was defined and open the
235 editor at the point where it is defined. You can use ``%edit function``
235 editor at the point where it is defined. You can use ``%edit function``
236 to load an editor exactly at the point where 'function' is defined,
236 to load an editor exactly at the point where 'function' is defined,
237 edit it and have the file be executed automatically.
237 edit it and have the file be executed automatically.
238
238
239 If the object is a macro (see %macro for details), this opens up your
239 If the object is a macro (see %macro for details), this opens up your
240 specified editor with a temporary file containing the macro's data.
240 specified editor with a temporary file containing the macro's data.
241 Upon exit, the macro is reloaded with the contents of the file.
241 Upon exit, the macro is reloaded with the contents of the file.
242
242
243 Note: opening at an exact line is only supported under Unix, and some
243 Note: opening at an exact line is only supported under Unix, and some
244 editors (like kedit and gedit up to Gnome 2.8) do not understand the
244 editors (like kedit and gedit up to Gnome 2.8) do not understand the
245 '+NUMBER' parameter necessary for this feature. Good editors like
245 '+NUMBER' parameter necessary for this feature. Good editors like
246 (X)Emacs, vi, jed, pico and joe all do.
246 (X)Emacs, vi, jed, pico and joe all do.
247
247
248 - If the argument is not found as a variable, IPython will look for a
248 - If the argument is not found as a variable, IPython will look for a
249 file with that name (adding .py if necessary) and load it into the
249 file with that name (adding .py if necessary) and load it into the
250 editor. It will execute its contents with execfile() when you exit,
250 editor. It will execute its contents with execfile() when you exit,
251 loading any code in the file into your interactive namespace.
251 loading any code in the file into your interactive namespace.
252
252
253 Unlike in the terminal, this is designed to use a GUI editor, and we do
253 Unlike in the terminal, this is designed to use a GUI editor, and we do
254 not know when it has closed. So the file you edit will not be
254 not know when it has closed. So the file you edit will not be
255 automatically executed or printed.
255 automatically executed or printed.
256
256
257 Note that %edit is also available through the alias %ed.
257 Note that %edit is also available through the alias %ed.
258 """
258 """
259
259
260 opts,args = self.parse_options(parameter_s,'prn:')
260 opts,args = self.parse_options(parameter_s,'prn:')
261
261
262 try:
262 try:
263 filename, lineno, _ = CodeMagics._find_edit_target(self.shell, args, opts, last_call)
263 filename, lineno, _ = CodeMagics._find_edit_target(self.shell, args, opts, last_call)
264 except MacroToEdit as e:
264 except MacroToEdit as e:
265 # TODO: Implement macro editing over 2 processes.
265 # TODO: Implement macro editing over 2 processes.
266 print("Macro editing not yet implemented in 2-process model.")
266 print("Macro editing not yet implemented in 2-process model.")
267 return
267 return
268
268
269 # Make sure we send to the client an absolute path, in case the working
269 # Make sure we send to the client an absolute path, in case the working
270 # directory of client and kernel don't match
270 # directory of client and kernel don't match
271 filename = os.path.abspath(filename)
271 filename = os.path.abspath(filename)
272
272
273 payload = {
273 payload = {
274 'source' : 'edit_magic',
274 'source' : 'edit_magic',
275 'filename' : filename,
275 'filename' : filename,
276 'line_number' : lineno
276 'line_number' : lineno
277 }
277 }
278 self.shell.payload_manager.write_payload(payload)
278 self.shell.payload_manager.write_payload(payload)
279
279
280 # A few magics that are adapted to the specifics of using pexpect and a
280 # A few magics that are adapted to the specifics of using pexpect and a
281 # remote terminal
281 # remote terminal
282
282
283 @line_magic
283 @line_magic
284 def clear(self, arg_s):
284 def clear(self, arg_s):
285 """Clear the terminal."""
285 """Clear the terminal."""
286 if os.name == 'posix':
286 if os.name == 'posix':
287 self.shell.system("clear")
287 self.shell.system("clear")
288 else:
288 else:
289 self.shell.system("cls")
289 self.shell.system("cls")
290
290
291 if os.name == 'nt':
291 if os.name == 'nt':
292 # This is the usual name in windows
292 # This is the usual name in windows
293 cls = line_magic('cls')(clear)
293 cls = line_magic('cls')(clear)
294
294
295 # Terminal pagers won't work over pexpect, but we do have our own pager
295 # Terminal pagers won't work over pexpect, but we do have our own pager
296
296
297 @line_magic
297 @line_magic
298 def less(self, arg_s):
298 def less(self, arg_s):
299 """Show a file through the pager.
299 """Show a file through the pager.
300
300
301 Files ending in .py are syntax-highlighted."""
301 Files ending in .py are syntax-highlighted."""
302 if not arg_s:
302 if not arg_s:
303 raise UsageError('Missing filename.')
303 raise UsageError('Missing filename.')
304
304
305 cont = open(arg_s).read()
305 cont = open(arg_s).read()
306 if arg_s.endswith('.py'):
306 if arg_s.endswith('.py'):
307 cont = self.shell.pycolorize(openpy.read_py_file(arg_s, skip_encoding_cookie=False))
307 cont = self.shell.pycolorize(openpy.read_py_file(arg_s, skip_encoding_cookie=False))
308 else:
308 else:
309 cont = open(arg_s).read()
309 cont = open(arg_s).read()
310 page.page(cont)
310 page.page(cont)
311
311
312 more = line_magic('more')(less)
312 more = line_magic('more')(less)
313
313
314 # Man calls a pager, so we also need to redefine it
314 # Man calls a pager, so we also need to redefine it
315 if os.name == 'posix':
315 if os.name == 'posix':
316 @line_magic
316 @line_magic
317 def man(self, arg_s):
317 def man(self, arg_s):
318 """Find the man page for the given command and display in pager."""
318 """Find the man page for the given command and display in pager."""
319 page.page(self.shell.getoutput('man %s | col -b' % arg_s,
319 page.page(self.shell.getoutput('man %s | col -b' % arg_s,
320 split=False))
320 split=False))
321
321
322 @line_magic
322 @line_magic
323 def connect_info(self, arg_s):
323 def connect_info(self, arg_s):
324 """Print information for connecting other clients to this kernel
324 """Print information for connecting other clients to this kernel
325
325
326 It will print the contents of this session's connection file, as well as
326 It will print the contents of this session's connection file, as well as
327 shortcuts for local clients.
327 shortcuts for local clients.
328
328
329 In the simplest case, when called from the most recently launched kernel,
329 In the simplest case, when called from the most recently launched kernel,
330 secondary clients can be connected, simply with:
330 secondary clients can be connected, simply with:
331
331
332 $> ipython <app> --existing
332 $> ipython <app> --existing
333
333
334 """
334 """
335
335
336 from IPython.core.application import BaseIPythonApplication as BaseIPApp
336 from IPython.core.application import BaseIPythonApplication as BaseIPApp
337
337
338 if BaseIPApp.initialized():
338 if BaseIPApp.initialized():
339 app = BaseIPApp.instance()
339 app = BaseIPApp.instance()
340 security_dir = app.profile_dir.security_dir
340 security_dir = app.profile_dir.security_dir
341 profile = app.profile
341 profile = app.profile
342 else:
342 else:
343 profile = 'default'
343 profile = 'default'
344 security_dir = ''
344 security_dir = ''
345
345
346 try:
346 try:
347 connection_file = get_connection_file()
347 connection_file = get_connection_file()
348 info = get_connection_info(unpack=False)
348 info = get_connection_info(unpack=False)
349 except Exception as e:
349 except Exception as e:
350 error("Could not get connection info: %r" % e)
350 error("Could not get connection info: %r" % e)
351 return
351 return
352
352
353 # add profile flag for non-default profile
353 # add profile flag for non-default profile
354 profile_flag = "--profile %s" % profile if profile != 'default' else ""
354 profile_flag = "--profile %s" % profile if profile != 'default' else ""
355
355
356 # if it's in the security dir, truncate to basename
356 # if it's in the security dir, truncate to basename
357 if security_dir == os.path.dirname(connection_file):
357 if security_dir == os.path.dirname(connection_file):
358 connection_file = os.path.basename(connection_file)
358 connection_file = os.path.basename(connection_file)
359
359
360
360
361 print (info + '\n')
361 print (info + '\n')
362 print ("Paste the above JSON into a file, and connect with:\n"
362 print ("Paste the above JSON into a file, and connect with:\n"
363 " $> ipython <app> --existing <file>\n"
363 " $> ipython <app> --existing <file>\n"
364 "or, if you are local, you can connect with just:\n"
364 "or, if you are local, you can connect with just:\n"
365 " $> ipython <app> --existing {0} {1}\n"
365 " $> ipython <app> --existing {0} {1}\n"
366 "or even just:\n"
366 "or even just:\n"
367 " $> ipython <app> --existing {1}\n"
367 " $> ipython <app> --existing {1}\n"
368 "if this is the most recent IPython session you have started.".format(
368 "if this is the most recent IPython session you have started.".format(
369 connection_file, profile_flag
369 connection_file, profile_flag
370 )
370 )
371 )
371 )
372
372
373 @line_magic
373 @line_magic
374 def qtconsole(self, arg_s):
374 def qtconsole(self, arg_s):
375 """Open a qtconsole connected to this kernel.
375 """Open a qtconsole connected to this kernel.
376
376
377 Useful for connecting a qtconsole to running notebooks, for better
377 Useful for connecting a qtconsole to running notebooks, for better
378 debugging.
378 debugging.
379 """
379 """
380
380
381 # %qtconsole should imply bind_kernel for engines:
381 # %qtconsole should imply bind_kernel for engines:
382 try:
382 try:
383 from IPython.parallel import bind_kernel
383 from IPython.parallel import bind_kernel
384 except ImportError:
384 except ImportError:
385 # technically possible, because parallel has higher pyzmq min-version
385 # technically possible, because parallel has higher pyzmq min-version
386 pass
386 pass
387 else:
387 else:
388 bind_kernel()
388 bind_kernel()
389
389
390 try:
390 try:
391 p = connect_qtconsole(argv=arg_split(arg_s, os.name=='posix'))
391 p = connect_qtconsole(argv=arg_split(arg_s, os.name=='posix'))
392 except Exception as e:
392 except Exception as e:
393 error("Could not start qtconsole: %r" % e)
393 error("Could not start qtconsole: %r" % e)
394 return
394 return
395
395
396 @line_magic
396 @line_magic
397 def autosave(self, arg_s):
397 def autosave(self, arg_s):
398 """Set the autosave interval in the notebook (in seconds).
398 """Set the autosave interval in the notebook (in seconds).
399
399
400 The default value is 120, or two minutes.
400 The default value is 120, or two minutes.
401 ``%autosave 0`` will disable autosave.
401 ``%autosave 0`` will disable autosave.
402
402
403 This magic only has an effect when called from the notebook interface.
403 This magic only has an effect when called from the notebook interface.
404 It has no effect when called in a startup file.
404 It has no effect when called in a startup file.
405 """
405 """
406
406
407 try:
407 try:
408 interval = int(arg_s)
408 interval = int(arg_s)
409 except ValueError:
409 except ValueError:
410 raise UsageError("%%autosave requires an integer, got %r" % arg_s)
410 raise UsageError("%%autosave requires an integer, got %r" % arg_s)
411
411
412 # javascript wants milliseconds
412 # javascript wants milliseconds
413 milliseconds = 1000 * interval
413 milliseconds = 1000 * interval
414 display(Javascript("IPython.notebook.set_autosave_interval(%i)" % milliseconds),
414 display(Javascript("IPython.notebook.set_autosave_interval(%i)" % milliseconds),
415 include=['application/javascript']
415 include=['application/javascript']
416 )
416 )
417 if interval:
417 if interval:
418 print("Autosaving every %i seconds" % interval)
418 print("Autosaving every %i seconds" % interval)
419 else:
419 else:
420 print("Autosave disabled")
420 print("Autosave disabled")
421
421
422
422
423 class ZMQInteractiveShell(InteractiveShell):
423 class ZMQInteractiveShell(InteractiveShell):
424 """A subclass of InteractiveShell for ZMQ."""
424 """A subclass of InteractiveShell for ZMQ."""
425
425
426 displayhook_class = Type(ZMQShellDisplayHook)
426 displayhook_class = Type(ZMQShellDisplayHook)
427 display_pub_class = Type(ZMQDisplayPublisher)
427 display_pub_class = Type(ZMQDisplayPublisher)
428 data_pub_class = Type(ZMQDataPublisher)
428 data_pub_class = Type(ZMQDataPublisher)
429 kernel = Any()
429 kernel = Any()
430 parent_header = Any()
430 parent_header = Any()
431
431
432 # Override the traitlet in the parent class, because there's no point using
432 # Override the traitlet in the parent class, because there's no point using
433 # readline for the kernel. Can be removed when the readline code is moved
433 # readline for the kernel. Can be removed when the readline code is moved
434 # to the terminal frontend.
434 # to the terminal frontend.
435 colors_force = CBool(True)
435 colors_force = CBool(True)
436 readline_use = CBool(False)
436 readline_use = CBool(False)
437 # autoindent has no meaning in a zmqshell, and attempting to enable it
437 # autoindent has no meaning in a zmqshell, and attempting to enable it
438 # will print a warning in the absence of readline.
438 # will print a warning in the absence of readline.
439 autoindent = CBool(False)
439 autoindent = CBool(False)
440
440
441 exiter = Instance(ZMQExitAutocall)
441 exiter = Instance(ZMQExitAutocall)
442 def _exiter_default(self):
442 def _exiter_default(self):
443 return ZMQExitAutocall(self)
443 return ZMQExitAutocall(self)
444
444
445 def _exit_now_changed(self, name, old, new):
445 def _exit_now_changed(self, name, old, new):
446 """stop eventloop when exit_now fires"""
446 """stop eventloop when exit_now fires"""
447 if new:
447 if new:
448 loop = ioloop.IOLoop.instance()
448 loop = ioloop.IOLoop.instance()
449 loop.add_timeout(time.time()+0.1, loop.stop)
449 loop.add_timeout(time.time()+0.1, loop.stop)
450
450
451 keepkernel_on_exit = None
451 keepkernel_on_exit = None
452
452
453 # Over ZeroMQ, GUI control isn't done with PyOS_InputHook as there is no
453 # Over ZeroMQ, GUI control isn't done with PyOS_InputHook as there is no
454 # interactive input being read; we provide event loop support in ipkernel
454 # interactive input being read; we provide event loop support in ipkernel
455 @staticmethod
455 @staticmethod
456 def enable_gui(gui):
456 def enable_gui(gui):
457 from .eventloops import enable_gui as real_enable_gui
457 from .eventloops import enable_gui as real_enable_gui
458 try:
458 try:
459 real_enable_gui(gui)
459 real_enable_gui(gui)
460 except ValueError as e:
460 except ValueError as e:
461 raise UsageError("%s" % e)
461 raise UsageError("%s" % e)
462
462
463 def init_environment(self):
463 def init_environment(self):
464 """Configure the user's environment.
464 """Configure the user's environment.
465
465
466 """
466 """
467 env = os.environ
467 env = os.environ
468 # These two ensure 'ls' produces nice coloring on BSD-derived systems
468 # These two ensure 'ls' produces nice coloring on BSD-derived systems
469 env['TERM'] = 'xterm-color'
469 env['TERM'] = 'xterm-color'
470 env['CLICOLOR'] = '1'
470 env['CLICOLOR'] = '1'
471 # Since normal pagers don't work at all (over pexpect we don't have
471 # Since normal pagers don't work at all (over pexpect we don't have
472 # single-key control of the subprocess), try to disable paging in
472 # single-key control of the subprocess), try to disable paging in
473 # subprocesses as much as possible.
473 # subprocesses as much as possible.
474 env['PAGER'] = 'cat'
474 env['PAGER'] = 'cat'
475 env['GIT_PAGER'] = 'cat'
475 env['GIT_PAGER'] = 'cat'
476
476
477 # And install the payload version of page.
477 # And install the payload version of page.
478 install_payload_page()
478 install_payload_page()
479
479
480 def auto_rewrite_input(self, cmd):
480 def auto_rewrite_input(self, cmd):
481 """Called to show the auto-rewritten input for autocall and friends.
481 """Called to show the auto-rewritten input for autocall and friends.
482
482
483 FIXME: this payload is currently not correctly processed by the
483 FIXME: this payload is currently not correctly processed by the
484 frontend.
484 frontend.
485 """
485 """
486 new = self.prompt_manager.render('rewrite') + cmd
486 new = self.prompt_manager.render('rewrite') + cmd
487 payload = dict(
487 payload = dict(
488 source='auto_rewrite_input',
488 source='auto_rewrite_input',
489 transformed_input=new,
489 transformed_input=new,
490 )
490 )
491 self.payload_manager.write_payload(payload)
491 self.payload_manager.write_payload(payload)
492
492
493 def ask_exit(self):
493 def ask_exit(self):
494 """Engage the exit actions."""
494 """Engage the exit actions."""
495 self.exit_now = True
495 self.exit_now = True
496 payload = dict(
496 payload = dict(
497 source='ask_exit',
497 source='ask_exit',
498 exit=True,
498 exit=True,
499 keepkernel=self.keepkernel_on_exit,
499 keepkernel=self.keepkernel_on_exit,
500 )
500 )
501 self.payload_manager.write_payload(payload)
501 self.payload_manager.write_payload(payload)
502
502
503 def _showtraceback(self, etype, evalue, stb):
503 def _showtraceback(self, etype, evalue, stb):
504 # try to preserve ordering of tracebacks and print statements
505 sys.stdout.flush()
506 sys.stderr.flush()
504
507
505 exc_content = {
508 exc_content = {
506 u'traceback' : stb,
509 u'traceback' : stb,
507 u'ename' : unicode_type(etype.__name__),
510 u'ename' : unicode_type(etype.__name__),
508 u'evalue' : py3compat.safe_unicode(evalue),
511 u'evalue' : py3compat.safe_unicode(evalue),
509 }
512 }
510
513
511 dh = self.displayhook
514 dh = self.displayhook
512 # Send exception info over pub socket for other clients than the caller
515 # Send exception info over pub socket for other clients than the caller
513 # to pick up
516 # to pick up
514 topic = None
517 topic = None
515 if dh.topic:
518 if dh.topic:
516 topic = dh.topic.replace(b'pyout', b'pyerr')
519 topic = dh.topic.replace(b'pyout', b'pyerr')
517
520
518 exc_msg = dh.session.send(dh.pub_socket, u'pyerr', json_clean(exc_content), dh.parent_header, ident=topic)
521 exc_msg = dh.session.send(dh.pub_socket, u'pyerr', json_clean(exc_content), dh.parent_header, ident=topic)
519
522
520 # FIXME - Hack: store exception info in shell object. Right now, the
523 # FIXME - Hack: store exception info in shell object. Right now, the
521 # caller is reading this info after the fact, we need to fix this logic
524 # caller is reading this info after the fact, we need to fix this logic
522 # to remove this hack. Even uglier, we need to store the error status
525 # to remove this hack. Even uglier, we need to store the error status
523 # here, because in the main loop, the logic that sets it is being
526 # here, because in the main loop, the logic that sets it is being
524 # skipped because runlines swallows the exceptions.
527 # skipped because runlines swallows the exceptions.
525 exc_content[u'status'] = u'error'
528 exc_content[u'status'] = u'error'
526 self._reply_content = exc_content
529 self._reply_content = exc_content
527 # /FIXME
530 # /FIXME
528
531
529 return exc_content
532 return exc_content
530
533
531 def set_next_input(self, text):
534 def set_next_input(self, text):
532 """Send the specified text to the frontend to be presented at the next
535 """Send the specified text to the frontend to be presented at the next
533 input cell."""
536 input cell."""
534 payload = dict(
537 payload = dict(
535 source='set_next_input',
538 source='set_next_input',
536 text=text
539 text=text
537 )
540 )
538 self.payload_manager.write_payload(payload)
541 self.payload_manager.write_payload(payload)
539
542
540 def set_parent(self, parent):
543 def set_parent(self, parent):
541 """Set the parent header for associating output with its triggering input"""
544 """Set the parent header for associating output with its triggering input"""
542 self.parent_header = parent
545 self.parent_header = parent
543 self.displayhook.set_parent(parent)
546 self.displayhook.set_parent(parent)
544 self.display_pub.set_parent(parent)
547 self.display_pub.set_parent(parent)
545 self.data_pub.set_parent(parent)
548 self.data_pub.set_parent(parent)
546 try:
549 try:
547 sys.stdout.set_parent(parent)
550 sys.stdout.set_parent(parent)
548 except AttributeError:
551 except AttributeError:
549 pass
552 pass
550 try:
553 try:
551 sys.stderr.set_parent(parent)
554 sys.stderr.set_parent(parent)
552 except AttributeError:
555 except AttributeError:
553 pass
556 pass
554
557
555 def get_parent(self):
558 def get_parent(self):
556 return self.parent_header
559 return self.parent_header
557
560
558 #-------------------------------------------------------------------------
561 #-------------------------------------------------------------------------
559 # Things related to magics
562 # Things related to magics
560 #-------------------------------------------------------------------------
563 #-------------------------------------------------------------------------
561
564
562 def init_magics(self):
565 def init_magics(self):
563 super(ZMQInteractiveShell, self).init_magics()
566 super(ZMQInteractiveShell, self).init_magics()
564 self.register_magics(KernelMagics)
567 self.register_magics(KernelMagics)
565 self.magics_manager.register_alias('ed', 'edit')
568 self.magics_manager.register_alias('ed', 'edit')
566
569
567 def init_comms(self):
570 def init_comms(self):
568 self.comm_manager = CommManager(shell=self, parent=self)
571 self.comm_manager = CommManager(shell=self, parent=self)
569 self.configurables.append(self.comm_manager)
572 self.configurables.append(self.comm_manager)
570
573
571
574
572 InteractiveShellABC.register(ZMQInteractiveShell)
575 InteractiveShellABC.register(ZMQInteractiveShell)
General Comments 0
You need to be logged in to leave comments. Login now