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