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