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