##// END OF EJS Templates
Fixing small bug in display logic....
Brian Granger -
Show More
@@ -1,184 +1,184 b''
1 import os
1 import os
2 import uuid
2 import uuid
3 import pprint
3 import pprint
4
4
5 import zmq
5 import zmq
6
6
7 from zmq.utils import jsonapi as json
7 from zmq.utils import jsonapi as json
8
8
9 class Message(object):
9 class Message(object):
10 """A simple message object that maps dict keys to attributes.
10 """A simple message object that maps dict keys to attributes.
11
11
12 A Message can be created from a dict and a dict from a Message instance
12 A Message can be created from a dict and a dict from a Message instance
13 simply by calling dict(msg_obj)."""
13 simply by calling dict(msg_obj)."""
14
14
15 def __init__(self, msg_dict):
15 def __init__(self, msg_dict):
16 dct = self.__dict__
16 dct = self.__dict__
17 for k, v in msg_dict.iteritems():
17 for k, v in msg_dict.iteritems():
18 if isinstance(v, dict):
18 if isinstance(v, dict):
19 v = Message(v)
19 v = Message(v)
20 dct[k] = v
20 dct[k] = v
21
21
22 # Having this iterator lets dict(msg_obj) work out of the box.
22 # Having this iterator lets dict(msg_obj) work out of the box.
23 def __iter__(self):
23 def __iter__(self):
24 return iter(self.__dict__.iteritems())
24 return iter(self.__dict__.iteritems())
25
25
26 def __repr__(self):
26 def __repr__(self):
27 return repr(self.__dict__)
27 return repr(self.__dict__)
28
28
29 def __str__(self):
29 def __str__(self):
30 return pprint.pformat(self.__dict__)
30 return pprint.pformat(self.__dict__)
31
31
32 def __contains__(self, k):
32 def __contains__(self, k):
33 return k in self.__dict__
33 return k in self.__dict__
34
34
35 def __getitem__(self, k):
35 def __getitem__(self, k):
36 return self.__dict__[k]
36 return self.__dict__[k]
37
37
38
38
39 def msg_header(msg_id, username, session):
39 def msg_header(msg_id, username, session):
40 return {
40 return {
41 'msg_id' : msg_id,
41 'msg_id' : msg_id,
42 'username' : username,
42 'username' : username,
43 'session' : session
43 'session' : session
44 }
44 }
45
45
46
46
47 def extract_header(msg_or_header):
47 def extract_header(msg_or_header):
48 """Given a message or header, return the header."""
48 """Given a message or header, return the header."""
49 if not msg_or_header:
49 if not msg_or_header:
50 return {}
50 return {}
51 try:
51 try:
52 # See if msg_or_header is the entire message.
52 # See if msg_or_header is the entire message.
53 h = msg_or_header['header']
53 h = msg_or_header['header']
54 except KeyError:
54 except KeyError:
55 try:
55 try:
56 # See if msg_or_header is just the header
56 # See if msg_or_header is just the header
57 h = msg_or_header['msg_id']
57 h = msg_or_header['msg_id']
58 except KeyError:
58 except KeyError:
59 raise
59 raise
60 else:
60 else:
61 h = msg_or_header
61 h = msg_or_header
62 if not isinstance(h, dict):
62 if not isinstance(h, dict):
63 h = dict(h)
63 h = dict(h)
64 return h
64 return h
65
65
66
66
67 class Session(object):
67 class Session(object):
68
68
69 def __init__(self, username=os.environ.get('USER','username'), session=None):
69 def __init__(self, username=os.environ.get('USER','username'), session=None):
70 self.username = username
70 self.username = username
71 if session is None:
71 if session is None:
72 self.session = str(uuid.uuid4())
72 self.session = str(uuid.uuid4())
73 else:
73 else:
74 self.session = session
74 self.session = session
75 self.msg_id = 0
75 self.msg_id = 0
76
76
77 def msg_header(self):
77 def msg_header(self):
78 h = msg_header(self.msg_id, self.username, self.session)
78 h = msg_header(self.msg_id, self.username, self.session)
79 self.msg_id += 1
79 self.msg_id += 1
80 return h
80 return h
81
81
82 def msg(self, msg_type, content=None, parent=None):
82 def msg(self, msg_type, content=None, parent=None):
83 """Construct a standard-form message, with a given type, content, and parent.
83 """Construct a standard-form message, with a given type, content, and parent.
84
84
85 NOT to be called directly.
85 NOT to be called directly.
86 """
86 """
87 msg = {}
87 msg = {}
88 msg['header'] = self.msg_header()
88 msg['header'] = self.msg_header()
89 msg['parent_header'] = {} if parent is None else extract_header(parent)
89 msg['parent_header'] = {} if parent is None else extract_header(parent)
90 msg['msg_type'] = msg_type
90 msg['msg_type'] = msg_type
91 msg['content'] = {} if content is None else content
91 msg['content'] = {} if content is None else content
92 return msg
92 return msg
93
93
94 def send(self, socket, msg_or_type, content=None, parent=None, ident=None):
94 def send(self, socket, msg_or_type, content=None, parent=None, ident=None):
95 """send a message via a socket, using a uniform message pattern.
95 """send a message via a socket, using a uniform message pattern.
96
96
97 Parameters
97 Parameters
98 ----------
98 ----------
99 socket : zmq.Socket
99 socket : zmq.Socket
100 The socket on which to send.
100 The socket on which to send.
101 msg_or_type : Message/dict or str
101 msg_or_type : Message/dict or str
102 if str : then a new message will be constructed from content,parent
102 if str : then a new message will be constructed from content,parent
103 if Message/dict : then content and parent are ignored, and the message
103 if Message/dict : then content and parent are ignored, and the message
104 is sent. This is only for use when sending a Message for a second time.
104 is sent. This is only for use when sending a Message for a second time.
105 content : dict, optional
105 content : dict, optional
106 The contents of the message
106 The contents of the message
107 parent : dict, optional
107 parent : dict, optional
108 The parent header, or parent message, of this message
108 The parent header, or parent message, of this message
109 ident : bytes, optional
109 ident : bytes, optional
110 The zmq.IDENTITY prefix of the destination.
110 The zmq.IDENTITY prefix of the destination.
111 Only for use on certain socket types.
111 Only for use on certain socket types.
112
112
113 Returns
113 Returns
114 -------
114 -------
115 msg : dict
115 msg : dict
116 The message, as constructed by self.msg(msg_type,content,parent)
116 The message, as constructed by self.msg(msg_type,content,parent)
117 """
117 """
118 if isinstance(msg_or_type, (Message, dict)):
118 if isinstance(msg_or_type, (Message, dict)):
119 msg = dict(msg_or_type)
119 msg = dict(msg_or_type)
120 else:
120 else:
121 msg = self.msg(msg_or_type, content, parent)
121 msg = self.msg(msg_or_type, content, parent)
122 if ident is not None:
122 if ident is not None:
123 socket.send(ident, zmq.SNDMORE)
123 socket.send(ident, zmq.SNDMORE)
124 socket.send_json(msg)
124 socket.send_json(msg)
125 return msg
125 return msg
126
126
127 def recv(self, socket, mode=zmq.NOBLOCK):
127 def recv(self, socket, mode=zmq.NOBLOCK):
128 """recv a message on a socket.
128 """recv a message on a socket.
129
129
130 Receive an optionally identity-prefixed message, as sent via session.send().
130 Receive an optionally identity-prefixed message, as sent via session.send().
131
131
132 Parameters
132 Parameters
133 ----------
133 ----------
134
134
135 socket : zmq.Socket
135 socket : zmq.Socket
136 The socket on which to recv a message.
136 The socket on which to recv a message.
137 mode : int, optional
137 mode : int, optional
138 the mode flag passed to socket.recv
138 the mode flag passed to socket.recv
139 default: zmq.NOBLOCK
139 default: zmq.NOBLOCK
140
140
141 Returns
141 Returns
142 -------
142 -------
143 (ident,msg) : tuple
143 (ident,msg) : tuple
144 always length 2. If no message received, then return is (None,None)
144 always length 2. If no message received, then return is (None,None)
145 ident : bytes or None
145 ident : bytes or None
146 the identity prefix is there was one, None otherwise.
146 the identity prefix is there was one, None otherwise.
147 msg : dict or None
147 msg : dict or None
148 The actual message. If mode==zmq.NOBLOCK and no message was waiting,
148 The actual message. If mode==zmq.NOBLOCK and no message was waiting,
149 it will be None.
149 it will be None.
150 """
150 """
151 try:
151 try:
152 msg = socket.recv_multipart(mode)
152 msg = socket.recv_multipart(mode)
153 except zmq.ZMQError, e:
153 except zmq.ZMQError, e:
154 if e.errno == zmq.EAGAIN:
154 if e.errno == zmq.EAGAIN:
155 # We can convert EAGAIN to None as we know in this case
155 # We can convert EAGAIN to None as we know in this case
156 # recv_json won't return None.
156 # recv_json won't return None.
157 return None,None
157 return None,None
158 else:
158 else:
159 raise
159 raise
160 if len(msg) == 1:
160 if len(msg) == 1:
161 ident=None
161 ident=None
162 msg = msg[0]
162 msg = msg[0]
163 elif len(msg) == 2:
163 elif len(msg) == 2:
164 ident, msg = msg
164 ident, msg = msg
165 else:
165 else:
166 raise ValueError("Got message with length > 2, which is invalid")
166 raise ValueError("Got message with length > 2, which is invalid")
167
167
168 return ident, json.loads(msg)
168 return ident, json.loads(msg)
169
169
170 def test_msg2obj():
170 def test_msg2obj():
171 am = dict(x=1)
171 am = dict(x=1)
172 ao = Message(am)
172 ao = Message(am)
173 assert ao.x == am['x']
173 assert ao.x == am['x']
174
174
175 am['y'] = dict(z=1)
175 am['y'] = dict(z=1)
176 ao = Message(am)
176 ao = Message(am)
177 assert ao.y.z == am['y']['z']
177 assert ao.y.z == am['y']['z']
178
178
179 k1, k2 = 'y', 'z'
179 k1, k2 = 'y', 'z'
180 assert ao[k1][k2] == am[k1][k2]
180 assert ao[k1][k2] == am[k1][k2]
181
181
182 am2 = dict(ao)
182 am2 = dict(ao)
183 assert am['x'] == am2['x']
183 assert am['x'] == am2['x']
184 assert am['y']['z'] == am2['y']['z']
184 assert am['y']['z'] == am2['y']['z']
@@ -1,592 +1,598 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 from base64 import encodestring
19 from base64 import encodestring
20 import inspect
20 import inspect
21 import os
21 import os
22
22
23 # Our own
23 # Our own
24 from IPython.core.interactiveshell import (
24 from IPython.core.interactiveshell import (
25 InteractiveShell, InteractiveShellABC
25 InteractiveShell, InteractiveShellABC
26 )
26 )
27 from IPython.core import page
27 from IPython.core import page
28 from IPython.core.autocall import ZMQExitAutocall
28 from IPython.core.autocall import ZMQExitAutocall
29 from IPython.core.displayhook import DisplayHook
29 from IPython.core.displayhook import DisplayHook
30 from IPython.core.displaypub import DisplayPublisher
30 from IPython.core.displaypub import DisplayPublisher
31 from IPython.core.macro import Macro
31 from IPython.core.macro import Macro
32 from IPython.core.payloadpage import install_payload_page
32 from IPython.core.payloadpage import install_payload_page
33 from IPython.utils import io
33 from IPython.utils import io
34 from IPython.utils.path import get_py_filename
34 from IPython.utils.path import get_py_filename
35 from IPython.utils.traitlets import Instance, Type, Dict
35 from IPython.utils.traitlets import Instance, Type, Dict
36 from IPython.utils.warn import warn
36 from IPython.utils.warn import warn
37 from IPython.zmq.session import extract_header
37 from IPython.zmq.session import extract_header
38 from session import Session
38 from session import Session
39
39
40 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
41 # Globals and side-effects
41 # Globals and side-effects
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43
43
44 # Install the payload version of page.
44 # Install the payload version of page.
45 install_payload_page()
45 install_payload_page()
46
46
47 #-----------------------------------------------------------------------------
47 #-----------------------------------------------------------------------------
48 # Functions and classes
48 # Functions and classes
49 #-----------------------------------------------------------------------------
49 #-----------------------------------------------------------------------------
50
50
51 def _encode_png(data):
52 pngdata = data.get('image/png')
53 if pngdata is not None:
54 data['image/png'] = encodestring(pngdata)
55
56
51 class ZMQDisplayHook(DisplayHook):
57 class ZMQDisplayHook(DisplayHook):
52 """A displayhook subclass that publishes data using ZeroMQ."""
58 """A displayhook subclass that publishes data using ZeroMQ."""
53
59
54 session = Instance(Session)
60 session = Instance(Session)
55 pub_socket = Instance('zmq.Socket')
61 pub_socket = Instance('zmq.Socket')
56 parent_header = Dict({})
62 parent_header = Dict({})
57
63
58 def set_parent(self, parent):
64 def set_parent(self, parent):
59 """Set the parent for outbound messages."""
65 """Set the parent for outbound messages."""
60 self.parent_header = extract_header(parent)
66 self.parent_header = extract_header(parent)
61
67
62 def start_displayhook(self):
68 def start_displayhook(self):
63 self.msg = self.session.msg(u'pyout', {}, parent=self.parent_header)
69 self.msg = self.session.msg(u'pyout', {}, parent=self.parent_header)
64
70
65 def write_output_prompt(self):
71 def write_output_prompt(self):
66 """Write the output prompt."""
72 """Write the output prompt."""
67 if self.do_full_cache:
73 if self.do_full_cache:
68 self.msg['content']['execution_count'] = self.prompt_count
74 self.msg['content']['execution_count'] = self.prompt_count
69
75
70 def write_format_data(self, format_dict):
76 def write_format_data(self, format_dict):
71 pngdata = format_dict.get('image/png')
77 pngdata = format_dict.get('image/png')
72 if pngdata is not None:
78 _encode_png(format_dict)
73 format_dict['image/png'] = encodestring(pngdata)
74 self.msg['content']['data'] = format_dict
79 self.msg['content']['data'] = format_dict
75
80
76 def finish_displayhook(self):
81 def finish_displayhook(self):
77 """Finish up all displayhook activities."""
82 """Finish up all displayhook activities."""
78 self.session.send(self.pub_socket, self.msg)
83 self.session.send(self.pub_socket, self.msg)
79 self.msg = None
84 self.msg = None
80
85
81
86
82 class ZMQDisplayPublisher(DisplayPublisher):
87 class ZMQDisplayPublisher(DisplayPublisher):
83 """A display publisher that publishes data using a ZeroMQ PUB socket."""
88 """A display publisher that publishes data using a ZeroMQ PUB socket."""
84
89
85 session = Instance(Session)
90 session = Instance(Session)
86 pub_socket = Instance('zmq.Socket')
91 pub_socket = Instance('zmq.Socket')
87 parent_header = Dict({})
92 parent_header = Dict({})
88
93
89 def set_parent(self, parent):
94 def set_parent(self, parent):
90 """Set the parent for outbound messages."""
95 """Set the parent for outbound messages."""
91 self.parent_header = extract_header(parent)
96 self.parent_header = extract_header(parent)
92
97
93 def publish(self, source, data, metadata=None):
98 def publish(self, source, data, metadata=None):
94 if metadata is None:
99 if metadata is None:
95 metadata = {}
100 metadata = {}
96 self._validate_data(source, data, metadata)
101 self._validate_data(source, data, metadata)
97 content = {}
102 content = {}
98 content['source'] = source
103 content['source'] = source
104 _encode_png(data)
99 content['data'] = data
105 content['data'] = data
100 content['metadata'] = metadata
106 content['metadata'] = metadata
101 self.session.send(
107 self.session.send(
102 self.pub_socket, u'display_data', content,
108 self.pub_socket, u'display_data', content,
103 parent=self.parent_header
109 parent=self.parent_header
104 )
110 )
105
111
106
112
107 class ZMQInteractiveShell(InteractiveShell):
113 class ZMQInteractiveShell(InteractiveShell):
108 """A subclass of InteractiveShell for ZMQ."""
114 """A subclass of InteractiveShell for ZMQ."""
109
115
110 displayhook_class = Type(ZMQDisplayHook)
116 displayhook_class = Type(ZMQDisplayHook)
111 display_pub_class = Type(ZMQDisplayPublisher)
117 display_pub_class = Type(ZMQDisplayPublisher)
112
118
113 exiter = Instance(ZMQExitAutocall)
119 exiter = Instance(ZMQExitAutocall)
114 def _exiter_default(self):
120 def _exiter_default(self):
115 return ZMQExitAutocall(self)
121 return ZMQExitAutocall(self)
116
122
117 keepkernel_on_exit = None
123 keepkernel_on_exit = None
118
124
119 def init_environment(self):
125 def init_environment(self):
120 """Configure the user's environment.
126 """Configure the user's environment.
121
127
122 """
128 """
123 env = os.environ
129 env = os.environ
124 # These two ensure 'ls' produces nice coloring on BSD-derived systems
130 # These two ensure 'ls' produces nice coloring on BSD-derived systems
125 env['TERM'] = 'xterm-color'
131 env['TERM'] = 'xterm-color'
126 env['CLICOLOR'] = '1'
132 env['CLICOLOR'] = '1'
127 # Since normal pagers don't work at all (over pexpect we don't have
133 # Since normal pagers don't work at all (over pexpect we don't have
128 # single-key control of the subprocess), try to disable paging in
134 # single-key control of the subprocess), try to disable paging in
129 # subprocesses as much as possible.
135 # subprocesses as much as possible.
130 env['PAGER'] = 'cat'
136 env['PAGER'] = 'cat'
131 env['GIT_PAGER'] = 'cat'
137 env['GIT_PAGER'] = 'cat'
132
138
133 def auto_rewrite_input(self, cmd):
139 def auto_rewrite_input(self, cmd):
134 """Called to show the auto-rewritten input for autocall and friends.
140 """Called to show the auto-rewritten input for autocall and friends.
135
141
136 FIXME: this payload is currently not correctly processed by the
142 FIXME: this payload is currently not correctly processed by the
137 frontend.
143 frontend.
138 """
144 """
139 new = self.displayhook.prompt1.auto_rewrite() + cmd
145 new = self.displayhook.prompt1.auto_rewrite() + cmd
140 payload = dict(
146 payload = dict(
141 source='IPython.zmq.zmqshell.ZMQInteractiveShell.auto_rewrite_input',
147 source='IPython.zmq.zmqshell.ZMQInteractiveShell.auto_rewrite_input',
142 transformed_input=new,
148 transformed_input=new,
143 )
149 )
144 self.payload_manager.write_payload(payload)
150 self.payload_manager.write_payload(payload)
145
151
146 def ask_exit(self):
152 def ask_exit(self):
147 """Engage the exit actions."""
153 """Engage the exit actions."""
148 payload = dict(
154 payload = dict(
149 source='IPython.zmq.zmqshell.ZMQInteractiveShell.ask_exit',
155 source='IPython.zmq.zmqshell.ZMQInteractiveShell.ask_exit',
150 exit=True,
156 exit=True,
151 keepkernel=self.keepkernel_on_exit,
157 keepkernel=self.keepkernel_on_exit,
152 )
158 )
153 self.payload_manager.write_payload(payload)
159 self.payload_manager.write_payload(payload)
154
160
155 def _showtraceback(self, etype, evalue, stb):
161 def _showtraceback(self, etype, evalue, stb):
156
162
157 exc_content = {
163 exc_content = {
158 u'traceback' : stb,
164 u'traceback' : stb,
159 u'ename' : unicode(etype.__name__),
165 u'ename' : unicode(etype.__name__),
160 u'evalue' : unicode(evalue)
166 u'evalue' : unicode(evalue)
161 }
167 }
162
168
163 dh = self.displayhook
169 dh = self.displayhook
164 # Send exception info over pub socket for other clients than the caller
170 # Send exception info over pub socket for other clients than the caller
165 # to pick up
171 # to pick up
166 exc_msg = dh.session.send(dh.pub_socket, u'pyerr', exc_content, dh.parent_header)
172 exc_msg = dh.session.send(dh.pub_socket, u'pyerr', exc_content, dh.parent_header)
167
173
168 # FIXME - Hack: store exception info in shell object. Right now, the
174 # FIXME - Hack: store exception info in shell object. Right now, the
169 # caller is reading this info after the fact, we need to fix this logic
175 # caller is reading this info after the fact, we need to fix this logic
170 # to remove this hack. Even uglier, we need to store the error status
176 # to remove this hack. Even uglier, we need to store the error status
171 # here, because in the main loop, the logic that sets it is being
177 # here, because in the main loop, the logic that sets it is being
172 # skipped because runlines swallows the exceptions.
178 # skipped because runlines swallows the exceptions.
173 exc_content[u'status'] = u'error'
179 exc_content[u'status'] = u'error'
174 self._reply_content = exc_content
180 self._reply_content = exc_content
175 # /FIXME
181 # /FIXME
176
182
177 return exc_content
183 return exc_content
178
184
179 #------------------------------------------------------------------------
185 #------------------------------------------------------------------------
180 # Magic overrides
186 # Magic overrides
181 #------------------------------------------------------------------------
187 #------------------------------------------------------------------------
182 # Once the base class stops inheriting from magic, this code needs to be
188 # Once the base class stops inheriting from magic, this code needs to be
183 # moved into a separate machinery as well. For now, at least isolate here
189 # moved into a separate machinery as well. For now, at least isolate here
184 # the magics which this class needs to implement differently from the base
190 # the magics which this class needs to implement differently from the base
185 # class, or that are unique to it.
191 # class, or that are unique to it.
186
192
187 def magic_doctest_mode(self,parameter_s=''):
193 def magic_doctest_mode(self,parameter_s=''):
188 """Toggle doctest mode on and off.
194 """Toggle doctest mode on and off.
189
195
190 This mode is intended to make IPython behave as much as possible like a
196 This mode is intended to make IPython behave as much as possible like a
191 plain Python shell, from the perspective of how its prompts, exceptions
197 plain Python shell, from the perspective of how its prompts, exceptions
192 and output look. This makes it easy to copy and paste parts of a
198 and output look. This makes it easy to copy and paste parts of a
193 session into doctests. It does so by:
199 session into doctests. It does so by:
194
200
195 - Changing the prompts to the classic ``>>>`` ones.
201 - Changing the prompts to the classic ``>>>`` ones.
196 - Changing the exception reporting mode to 'Plain'.
202 - Changing the exception reporting mode to 'Plain'.
197 - Disabling pretty-printing of output.
203 - Disabling pretty-printing of output.
198
204
199 Note that IPython also supports the pasting of code snippets that have
205 Note that IPython also supports the pasting of code snippets that have
200 leading '>>>' and '...' prompts in them. This means that you can paste
206 leading '>>>' and '...' prompts in them. This means that you can paste
201 doctests from files or docstrings (even if they have leading
207 doctests from files or docstrings (even if they have leading
202 whitespace), and the code will execute correctly. You can then use
208 whitespace), and the code will execute correctly. You can then use
203 '%history -t' to see the translated history; this will give you the
209 '%history -t' to see the translated history; this will give you the
204 input after removal of all the leading prompts and whitespace, which
210 input after removal of all the leading prompts and whitespace, which
205 can be pasted back into an editor.
211 can be pasted back into an editor.
206
212
207 With these features, you can switch into this mode easily whenever you
213 With these features, you can switch into this mode easily whenever you
208 need to do testing and changes to doctests, without having to leave
214 need to do testing and changes to doctests, without having to leave
209 your existing IPython session.
215 your existing IPython session.
210 """
216 """
211
217
212 from IPython.utils.ipstruct import Struct
218 from IPython.utils.ipstruct import Struct
213
219
214 # Shorthands
220 # Shorthands
215 shell = self.shell
221 shell = self.shell
216 disp_formatter = self.shell.display_formatter
222 disp_formatter = self.shell.display_formatter
217 ptformatter = disp_formatter.formatters['text/plain']
223 ptformatter = disp_formatter.formatters['text/plain']
218 # dstore is a data store kept in the instance metadata bag to track any
224 # dstore is a data store kept in the instance metadata bag to track any
219 # changes we make, so we can undo them later.
225 # changes we make, so we can undo them later.
220 dstore = shell.meta.setdefault('doctest_mode', Struct())
226 dstore = shell.meta.setdefault('doctest_mode', Struct())
221 save_dstore = dstore.setdefault
227 save_dstore = dstore.setdefault
222
228
223 # save a few values we'll need to recover later
229 # save a few values we'll need to recover later
224 mode = save_dstore('mode', False)
230 mode = save_dstore('mode', False)
225 save_dstore('rc_pprint', ptformatter.pprint)
231 save_dstore('rc_pprint', ptformatter.pprint)
226 save_dstore('rc_plain_text_only',disp_formatter.plain_text_only)
232 save_dstore('rc_plain_text_only',disp_formatter.plain_text_only)
227 save_dstore('xmode', shell.InteractiveTB.mode)
233 save_dstore('xmode', shell.InteractiveTB.mode)
228
234
229 if mode == False:
235 if mode == False:
230 # turn on
236 # turn on
231 ptformatter.pprint = False
237 ptformatter.pprint = False
232 disp_formatter.plain_text_only = True
238 disp_formatter.plain_text_only = True
233 shell.magic_xmode('Plain')
239 shell.magic_xmode('Plain')
234 else:
240 else:
235 # turn off
241 # turn off
236 ptformatter.pprint = dstore.rc_pprint
242 ptformatter.pprint = dstore.rc_pprint
237 disp_formatter.plain_text_only = dstore.rc_plain_text_only
243 disp_formatter.plain_text_only = dstore.rc_plain_text_only
238 shell.magic_xmode(dstore.xmode)
244 shell.magic_xmode(dstore.xmode)
239
245
240 # Store new mode and inform on console
246 # Store new mode and inform on console
241 dstore.mode = bool(1-int(mode))
247 dstore.mode = bool(1-int(mode))
242 mode_label = ['OFF','ON'][dstore.mode]
248 mode_label = ['OFF','ON'][dstore.mode]
243 print('Doctest mode is:', mode_label)
249 print('Doctest mode is:', mode_label)
244
250
245 # Send the payload back so that clients can modify their prompt display
251 # Send the payload back so that clients can modify their prompt display
246 payload = dict(
252 payload = dict(
247 source='IPython.zmq.zmqshell.ZMQInteractiveShell.magic_doctest_mode',
253 source='IPython.zmq.zmqshell.ZMQInteractiveShell.magic_doctest_mode',
248 mode=dstore.mode)
254 mode=dstore.mode)
249 self.payload_manager.write_payload(payload)
255 self.payload_manager.write_payload(payload)
250
256
251 def magic_edit(self,parameter_s='',last_call=['','']):
257 def magic_edit(self,parameter_s='',last_call=['','']):
252 """Bring up an editor and execute the resulting code.
258 """Bring up an editor and execute the resulting code.
253
259
254 Usage:
260 Usage:
255 %edit [options] [args]
261 %edit [options] [args]
256
262
257 %edit runs IPython's editor hook. The default version of this hook is
263 %edit runs IPython's editor hook. The default version of this hook is
258 set to call the __IPYTHON__.rc.editor command. This is read from your
264 set to call the __IPYTHON__.rc.editor command. This is read from your
259 environment variable $EDITOR. If this isn't found, it will default to
265 environment variable $EDITOR. If this isn't found, it will default to
260 vi under Linux/Unix and to notepad under Windows. See the end of this
266 vi under Linux/Unix and to notepad under Windows. See the end of this
261 docstring for how to change the editor hook.
267 docstring for how to change the editor hook.
262
268
263 You can also set the value of this editor via the command line option
269 You can also set the value of this editor via the command line option
264 '-editor' or in your ipythonrc file. This is useful if you wish to use
270 '-editor' or in your ipythonrc file. This is useful if you wish to use
265 specifically for IPython an editor different from your typical default
271 specifically for IPython an editor different from your typical default
266 (and for Windows users who typically don't set environment variables).
272 (and for Windows users who typically don't set environment variables).
267
273
268 This command allows you to conveniently edit multi-line code right in
274 This command allows you to conveniently edit multi-line code right in
269 your IPython session.
275 your IPython session.
270
276
271 If called without arguments, %edit opens up an empty editor with a
277 If called without arguments, %edit opens up an empty editor with a
272 temporary file and will execute the contents of this file when you
278 temporary file and will execute the contents of this file when you
273 close it (don't forget to save it!).
279 close it (don't forget to save it!).
274
280
275
281
276 Options:
282 Options:
277
283
278 -n <number>: open the editor at a specified line number. By default,
284 -n <number>: open the editor at a specified line number. By default,
279 the IPython editor hook uses the unix syntax 'editor +N filename', but
285 the IPython editor hook uses the unix syntax 'editor +N filename', but
280 you can configure this by providing your own modified hook if your
286 you can configure this by providing your own modified hook if your
281 favorite editor supports line-number specifications with a different
287 favorite editor supports line-number specifications with a different
282 syntax.
288 syntax.
283
289
284 -p: this will call the editor with the same data as the previous time
290 -p: this will call the editor with the same data as the previous time
285 it was used, regardless of how long ago (in your current session) it
291 it was used, regardless of how long ago (in your current session) it
286 was.
292 was.
287
293
288 -r: use 'raw' input. This option only applies to input taken from the
294 -r: use 'raw' input. This option only applies to input taken from the
289 user's history. By default, the 'processed' history is used, so that
295 user's history. By default, the 'processed' history is used, so that
290 magics are loaded in their transformed version to valid Python. If
296 magics are loaded in their transformed version to valid Python. If
291 this option is given, the raw input as typed as the command line is
297 this option is given, the raw input as typed as the command line is
292 used instead. When you exit the editor, it will be executed by
298 used instead. When you exit the editor, it will be executed by
293 IPython's own processor.
299 IPython's own processor.
294
300
295 -x: do not execute the edited code immediately upon exit. This is
301 -x: do not execute the edited code immediately upon exit. This is
296 mainly useful if you are editing programs which need to be called with
302 mainly useful if you are editing programs which need to be called with
297 command line arguments, which you can then do using %run.
303 command line arguments, which you can then do using %run.
298
304
299
305
300 Arguments:
306 Arguments:
301
307
302 If arguments are given, the following possibilites exist:
308 If arguments are given, the following possibilites exist:
303
309
304 - The arguments are numbers or pairs of colon-separated numbers (like
310 - The arguments are numbers or pairs of colon-separated numbers (like
305 1 4:8 9). These are interpreted as lines of previous input to be
311 1 4:8 9). These are interpreted as lines of previous input to be
306 loaded into the editor. The syntax is the same of the %macro command.
312 loaded into the editor. The syntax is the same of the %macro command.
307
313
308 - If the argument doesn't start with a number, it is evaluated as a
314 - If the argument doesn't start with a number, it is evaluated as a
309 variable and its contents loaded into the editor. You can thus edit
315 variable and its contents loaded into the editor. You can thus edit
310 any string which contains python code (including the result of
316 any string which contains python code (including the result of
311 previous edits).
317 previous edits).
312
318
313 - If the argument is the name of an object (other than a string),
319 - If the argument is the name of an object (other than a string),
314 IPython will try to locate the file where it was defined and open the
320 IPython will try to locate the file where it was defined and open the
315 editor at the point where it is defined. You can use `%edit function`
321 editor at the point where it is defined. You can use `%edit function`
316 to load an editor exactly at the point where 'function' is defined,
322 to load an editor exactly at the point where 'function' is defined,
317 edit it and have the file be executed automatically.
323 edit it and have the file be executed automatically.
318
324
319 If the object is a macro (see %macro for details), this opens up your
325 If the object is a macro (see %macro for details), this opens up your
320 specified editor with a temporary file containing the macro's data.
326 specified editor with a temporary file containing the macro's data.
321 Upon exit, the macro is reloaded with the contents of the file.
327 Upon exit, the macro is reloaded with the contents of the file.
322
328
323 Note: opening at an exact line is only supported under Unix, and some
329 Note: opening at an exact line is only supported under Unix, and some
324 editors (like kedit and gedit up to Gnome 2.8) do not understand the
330 editors (like kedit and gedit up to Gnome 2.8) do not understand the
325 '+NUMBER' parameter necessary for this feature. Good editors like
331 '+NUMBER' parameter necessary for this feature. Good editors like
326 (X)Emacs, vi, jed, pico and joe all do.
332 (X)Emacs, vi, jed, pico and joe all do.
327
333
328 - If the argument is not found as a variable, IPython will look for a
334 - If the argument is not found as a variable, IPython will look for a
329 file with that name (adding .py if necessary) and load it into the
335 file with that name (adding .py if necessary) and load it into the
330 editor. It will execute its contents with execfile() when you exit,
336 editor. It will execute its contents with execfile() when you exit,
331 loading any code in the file into your interactive namespace.
337 loading any code in the file into your interactive namespace.
332
338
333 After executing your code, %edit will return as output the code you
339 After executing your code, %edit will return as output the code you
334 typed in the editor (except when it was an existing file). This way
340 typed in the editor (except when it was an existing file). This way
335 you can reload the code in further invocations of %edit as a variable,
341 you can reload the code in further invocations of %edit as a variable,
336 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
342 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
337 the output.
343 the output.
338
344
339 Note that %edit is also available through the alias %ed.
345 Note that %edit is also available through the alias %ed.
340
346
341 This is an example of creating a simple function inside the editor and
347 This is an example of creating a simple function inside the editor and
342 then modifying it. First, start up the editor:
348 then modifying it. First, start up the editor:
343
349
344 In [1]: ed
350 In [1]: ed
345 Editing... done. Executing edited code...
351 Editing... done. Executing edited code...
346 Out[1]: 'def foo():n print "foo() was defined in an editing session"n'
352 Out[1]: 'def foo():n print "foo() was defined in an editing session"n'
347
353
348 We can then call the function foo():
354 We can then call the function foo():
349
355
350 In [2]: foo()
356 In [2]: foo()
351 foo() was defined in an editing session
357 foo() was defined in an editing session
352
358
353 Now we edit foo. IPython automatically loads the editor with the
359 Now we edit foo. IPython automatically loads the editor with the
354 (temporary) file where foo() was previously defined:
360 (temporary) file where foo() was previously defined:
355
361
356 In [3]: ed foo
362 In [3]: ed foo
357 Editing... done. Executing edited code...
363 Editing... done. Executing edited code...
358
364
359 And if we call foo() again we get the modified version:
365 And if we call foo() again we get the modified version:
360
366
361 In [4]: foo()
367 In [4]: foo()
362 foo() has now been changed!
368 foo() has now been changed!
363
369
364 Here is an example of how to edit a code snippet successive
370 Here is an example of how to edit a code snippet successive
365 times. First we call the editor:
371 times. First we call the editor:
366
372
367 In [5]: ed
373 In [5]: ed
368 Editing... done. Executing edited code...
374 Editing... done. Executing edited code...
369 hello
375 hello
370 Out[5]: "print 'hello'n"
376 Out[5]: "print 'hello'n"
371
377
372 Now we call it again with the previous output (stored in _):
378 Now we call it again with the previous output (stored in _):
373
379
374 In [6]: ed _
380 In [6]: ed _
375 Editing... done. Executing edited code...
381 Editing... done. Executing edited code...
376 hello world
382 hello world
377 Out[6]: "print 'hello world'n"
383 Out[6]: "print 'hello world'n"
378
384
379 Now we call it with the output #8 (stored in _8, also as Out[8]):
385 Now we call it with the output #8 (stored in _8, also as Out[8]):
380
386
381 In [7]: ed _8
387 In [7]: ed _8
382 Editing... done. Executing edited code...
388 Editing... done. Executing edited code...
383 hello again
389 hello again
384 Out[7]: "print 'hello again'n"
390 Out[7]: "print 'hello again'n"
385
391
386
392
387 Changing the default editor hook:
393 Changing the default editor hook:
388
394
389 If you wish to write your own editor hook, you can put it in a
395 If you wish to write your own editor hook, you can put it in a
390 configuration file which you load at startup time. The default hook
396 configuration file which you load at startup time. The default hook
391 is defined in the IPython.core.hooks module, and you can use that as a
397 is defined in the IPython.core.hooks module, and you can use that as a
392 starting example for further modifications. That file also has
398 starting example for further modifications. That file also has
393 general instructions on how to set a new hook for use once you've
399 general instructions on how to set a new hook for use once you've
394 defined it."""
400 defined it."""
395
401
396 # FIXME: This function has become a convoluted mess. It needs a
402 # FIXME: This function has become a convoluted mess. It needs a
397 # ground-up rewrite with clean, simple logic.
403 # ground-up rewrite with clean, simple logic.
398
404
399 def make_filename(arg):
405 def make_filename(arg):
400 "Make a filename from the given args"
406 "Make a filename from the given args"
401 try:
407 try:
402 filename = get_py_filename(arg)
408 filename = get_py_filename(arg)
403 except IOError:
409 except IOError:
404 if args.endswith('.py'):
410 if args.endswith('.py'):
405 filename = arg
411 filename = arg
406 else:
412 else:
407 filename = None
413 filename = None
408 return filename
414 return filename
409
415
410 # custom exceptions
416 # custom exceptions
411 class DataIsObject(Exception): pass
417 class DataIsObject(Exception): pass
412
418
413 opts,args = self.parse_options(parameter_s,'prn:')
419 opts,args = self.parse_options(parameter_s,'prn:')
414 # Set a few locals from the options for convenience:
420 # Set a few locals from the options for convenience:
415 opts_p = opts.has_key('p')
421 opts_p = opts.has_key('p')
416 opts_r = opts.has_key('r')
422 opts_r = opts.has_key('r')
417
423
418 # Default line number value
424 # Default line number value
419 lineno = opts.get('n',None)
425 lineno = opts.get('n',None)
420 if lineno is not None:
426 if lineno is not None:
421 try:
427 try:
422 lineno = int(lineno)
428 lineno = int(lineno)
423 except:
429 except:
424 warn("The -n argument must be an integer.")
430 warn("The -n argument must be an integer.")
425 return
431 return
426
432
427 if opts_p:
433 if opts_p:
428 args = '_%s' % last_call[0]
434 args = '_%s' % last_call[0]
429 if not self.shell.user_ns.has_key(args):
435 if not self.shell.user_ns.has_key(args):
430 args = last_call[1]
436 args = last_call[1]
431
437
432 # use last_call to remember the state of the previous call, but don't
438 # use last_call to remember the state of the previous call, but don't
433 # let it be clobbered by successive '-p' calls.
439 # let it be clobbered by successive '-p' calls.
434 try:
440 try:
435 last_call[0] = self.shell.displayhook.prompt_count
441 last_call[0] = self.shell.displayhook.prompt_count
436 if not opts_p:
442 if not opts_p:
437 last_call[1] = parameter_s
443 last_call[1] = parameter_s
438 except:
444 except:
439 pass
445 pass
440
446
441 # by default this is done with temp files, except when the given
447 # by default this is done with temp files, except when the given
442 # arg is a filename
448 # arg is a filename
443 use_temp = True
449 use_temp = True
444
450
445 data = ''
451 data = ''
446 if args[0].isdigit():
452 if args[0].isdigit():
447 # Mode where user specifies ranges of lines, like in %macro.
453 # Mode where user specifies ranges of lines, like in %macro.
448 # This means that you can't edit files whose names begin with
454 # This means that you can't edit files whose names begin with
449 # numbers this way. Tough.
455 # numbers this way. Tough.
450 ranges = args.split()
456 ranges = args.split()
451 data = ''.join(self.extract_input_slices(ranges,opts_r))
457 data = ''.join(self.extract_input_slices(ranges,opts_r))
452 elif args.endswith('.py'):
458 elif args.endswith('.py'):
453 filename = make_filename(args)
459 filename = make_filename(args)
454 use_temp = False
460 use_temp = False
455 elif args:
461 elif args:
456 try:
462 try:
457 # Load the parameter given as a variable. If not a string,
463 # Load the parameter given as a variable. If not a string,
458 # process it as an object instead (below)
464 # process it as an object instead (below)
459
465
460 #print '*** args',args,'type',type(args) # dbg
466 #print '*** args',args,'type',type(args) # dbg
461 data = eval(args, self.shell.user_ns)
467 data = eval(args, self.shell.user_ns)
462 if not isinstance(data, basestring):
468 if not isinstance(data, basestring):
463 raise DataIsObject
469 raise DataIsObject
464
470
465 except (NameError,SyntaxError):
471 except (NameError,SyntaxError):
466 # given argument is not a variable, try as a filename
472 # given argument is not a variable, try as a filename
467 filename = make_filename(args)
473 filename = make_filename(args)
468 if filename is None:
474 if filename is None:
469 warn("Argument given (%s) can't be found as a variable "
475 warn("Argument given (%s) can't be found as a variable "
470 "or as a filename." % args)
476 "or as a filename." % args)
471 return
477 return
472 use_temp = False
478 use_temp = False
473
479
474 except DataIsObject:
480 except DataIsObject:
475 # macros have a special edit function
481 # macros have a special edit function
476 if isinstance(data, Macro):
482 if isinstance(data, Macro):
477 self._edit_macro(args,data)
483 self._edit_macro(args,data)
478 return
484 return
479
485
480 # For objects, try to edit the file where they are defined
486 # For objects, try to edit the file where they are defined
481 try:
487 try:
482 filename = inspect.getabsfile(data)
488 filename = inspect.getabsfile(data)
483 if 'fakemodule' in filename.lower() and inspect.isclass(data):
489 if 'fakemodule' in filename.lower() and inspect.isclass(data):
484 # class created by %edit? Try to find source
490 # class created by %edit? Try to find source
485 # by looking for method definitions instead, the
491 # by looking for method definitions instead, the
486 # __module__ in those classes is FakeModule.
492 # __module__ in those classes is FakeModule.
487 attrs = [getattr(data, aname) for aname in dir(data)]
493 attrs = [getattr(data, aname) for aname in dir(data)]
488 for attr in attrs:
494 for attr in attrs:
489 if not inspect.ismethod(attr):
495 if not inspect.ismethod(attr):
490 continue
496 continue
491 filename = inspect.getabsfile(attr)
497 filename = inspect.getabsfile(attr)
492 if filename and 'fakemodule' not in filename.lower():
498 if filename and 'fakemodule' not in filename.lower():
493 # change the attribute to be the edit target instead
499 # change the attribute to be the edit target instead
494 data = attr
500 data = attr
495 break
501 break
496
502
497 datafile = 1
503 datafile = 1
498 except TypeError:
504 except TypeError:
499 filename = make_filename(args)
505 filename = make_filename(args)
500 datafile = 1
506 datafile = 1
501 warn('Could not find file where `%s` is defined.\n'
507 warn('Could not find file where `%s` is defined.\n'
502 'Opening a file named `%s`' % (args,filename))
508 'Opening a file named `%s`' % (args,filename))
503 # Now, make sure we can actually read the source (if it was in
509 # Now, make sure we can actually read the source (if it was in
504 # a temp file it's gone by now).
510 # a temp file it's gone by now).
505 if datafile:
511 if datafile:
506 try:
512 try:
507 if lineno is None:
513 if lineno is None:
508 lineno = inspect.getsourcelines(data)[1]
514 lineno = inspect.getsourcelines(data)[1]
509 except IOError:
515 except IOError:
510 filename = make_filename(args)
516 filename = make_filename(args)
511 if filename is None:
517 if filename is None:
512 warn('The file `%s` where `%s` was defined cannot '
518 warn('The file `%s` where `%s` was defined cannot '
513 'be read.' % (filename,data))
519 'be read.' % (filename,data))
514 return
520 return
515 use_temp = False
521 use_temp = False
516
522
517 if use_temp:
523 if use_temp:
518 filename = self.shell.mktempfile(data)
524 filename = self.shell.mktempfile(data)
519 print('IPython will make a temporary file named:', filename)
525 print('IPython will make a temporary file named:', filename)
520
526
521 # Make sure we send to the client an absolute path, in case the working
527 # Make sure we send to the client an absolute path, in case the working
522 # directory of client and kernel don't match
528 # directory of client and kernel don't match
523 filename = os.path.abspath(filename)
529 filename = os.path.abspath(filename)
524
530
525 payload = {
531 payload = {
526 'source' : 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic',
532 'source' : 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic',
527 'filename' : filename,
533 'filename' : filename,
528 'line_number' : lineno
534 'line_number' : lineno
529 }
535 }
530 self.payload_manager.write_payload(payload)
536 self.payload_manager.write_payload(payload)
531
537
532 def magic_gui(self, *args, **kwargs):
538 def magic_gui(self, *args, **kwargs):
533 raise NotImplementedError(
539 raise NotImplementedError(
534 'GUI support must be enabled in command line options.')
540 'GUI support must be enabled in command line options.')
535
541
536 def magic_pylab(self, *args, **kwargs):
542 def magic_pylab(self, *args, **kwargs):
537 raise NotImplementedError(
543 raise NotImplementedError(
538 'pylab support must be enabled in command line options.')
544 'pylab support must be enabled in command line options.')
539
545
540 # A few magics that are adapted to the specifics of using pexpect and a
546 # A few magics that are adapted to the specifics of using pexpect and a
541 # remote terminal
547 # remote terminal
542
548
543 def magic_clear(self, arg_s):
549 def magic_clear(self, arg_s):
544 """Clear the terminal."""
550 """Clear the terminal."""
545 if os.name == 'posix':
551 if os.name == 'posix':
546 self.shell.system("clear")
552 self.shell.system("clear")
547 else:
553 else:
548 self.shell.system("cls")
554 self.shell.system("cls")
549
555
550 if os.name == 'nt':
556 if os.name == 'nt':
551 # This is the usual name in windows
557 # This is the usual name in windows
552 magic_cls = magic_clear
558 magic_cls = magic_clear
553
559
554 # Terminal pagers won't work over pexpect, but we do have our own pager
560 # Terminal pagers won't work over pexpect, but we do have our own pager
555
561
556 def magic_less(self, arg_s):
562 def magic_less(self, arg_s):
557 """Show a file through the pager.
563 """Show a file through the pager.
558
564
559 Files ending in .py are syntax-highlighted."""
565 Files ending in .py are syntax-highlighted."""
560 cont = open(arg_s).read()
566 cont = open(arg_s).read()
561 if arg_s.endswith('.py'):
567 if arg_s.endswith('.py'):
562 cont = self.shell.pycolorize(cont)
568 cont = self.shell.pycolorize(cont)
563 page.page(cont)
569 page.page(cont)
564
570
565 magic_more = magic_less
571 magic_more = magic_less
566
572
567 # Man calls a pager, so we also need to redefine it
573 # Man calls a pager, so we also need to redefine it
568 if os.name == 'posix':
574 if os.name == 'posix':
569 def magic_man(self, arg_s):
575 def magic_man(self, arg_s):
570 """Find the man page for the given command and display in pager."""
576 """Find the man page for the given command and display in pager."""
571 page.page(self.shell.getoutput('man %s | col -b' % arg_s,
577 page.page(self.shell.getoutput('man %s | col -b' % arg_s,
572 split=False))
578 split=False))
573
579
574 # FIXME: this is specific to the GUI, so we should let the gui app load
580 # FIXME: this is specific to the GUI, so we should let the gui app load
575 # magics at startup that are only for the gui. Once the gui app has proper
581 # magics at startup that are only for the gui. Once the gui app has proper
576 # profile and configuration management, we can have it initialize a kernel
582 # profile and configuration management, we can have it initialize a kernel
577 # with a special config file that provides these.
583 # with a special config file that provides these.
578 def magic_guiref(self, arg_s):
584 def magic_guiref(self, arg_s):
579 """Show a basic reference about the GUI console."""
585 """Show a basic reference about the GUI console."""
580 from IPython.core.usage import gui_reference
586 from IPython.core.usage import gui_reference
581 page.page(gui_reference, auto_html=True)
587 page.page(gui_reference, auto_html=True)
582
588
583 def set_next_input(self, text):
589 def set_next_input(self, text):
584 """Send the specified text to the frontend to be presented at the next
590 """Send the specified text to the frontend to be presented at the next
585 input cell."""
591 input cell."""
586 payload = dict(
592 payload = dict(
587 source='IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input',
593 source='IPython.zmq.zmqshell.ZMQInteractiveShell.set_next_input',
588 text=text
594 text=text
589 )
595 )
590 self.payload_manager.write_payload(payload)
596 self.payload_manager.write_payload(payload)
591
597
592 InteractiveShellABC.register(ZMQInteractiveShell)
598 InteractiveShellABC.register(ZMQInteractiveShell)
General Comments 0
You need to be logged in to leave comments. Login now