This diff has been collapsed as it changes many lines, (566 lines changed)
Show them
Hide them
|
|
@@
-1,19
+1,80
b''
|
|
1
|
=====================
|
|
1
|
======================
|
|
2
|
Message Specification
|
|
2
|
Messaging in IPython
|
|
3
|
=====================
|
|
3
|
======================
|
|
4
|
|
|
4
|
|
|
5
|
Note: not all of these have yet been fully fleshed out, but the key ones are,
|
|
|
|
|
6
|
see kernel and frontend files for actual implementation details.
|
|
|
|
|
7
|
|
|
5
|
|
|
8
|
Messages are dicts of dicts with string keys and values that are reasonably
|
|
6
|
Introduction
|
|
9
|
representable in JSON. Our current implementation uses JSON explicitly as its
|
|
7
|
============
|
|
10
|
message format, but this shouldn't be considered a permanent feature. As we've
|
|
8
|
|
|
11
|
discovered that JSON has non-trivial performance issues due to excessive
|
|
9
|
This document explains the basic communications design and messaging
|
|
12
|
copying, we may in the future move to a pure pickle-based raw message format.
|
|
10
|
specification for how the various IPython objects interact over a network
|
|
13
|
However, it should be possible to easily convert from the raw objects to JSON,
|
|
11
|
transport. The current implementation uses the ZeroMQ_ library for messaging
|
|
14
|
since we may have non-python clients (e.g. a web frontend). As long as it's
|
|
12
|
within and between hosts.
|
|
15
|
easy to make a JSON version of the objects that is a faithful representation of
|
|
13
|
|
|
16
|
all the data, we can communicate with such clients.
|
|
14
|
.. Note::
|
|
|
|
|
15
|
|
|
|
|
|
16
|
This document should be considered the authoritative description of the
|
|
|
|
|
17
|
IPython messaging protocol, and all developers are strongly encouraged to
|
|
|
|
|
18
|
keep it updated as the implementation evolves, so that we have a single
|
|
|
|
|
19
|
common reference for all protocol details.
|
|
|
|
|
20
|
|
|
|
|
|
21
|
The basic design is explained in the following diagram:
|
|
|
|
|
22
|
|
|
|
|
|
23
|
.. image:: frontend-kernel.png
|
|
|
|
|
24
|
:width: 450px
|
|
|
|
|
25
|
:alt: IPython kernel/frontend messaging architecture.
|
|
|
|
|
26
|
:align: center
|
|
|
|
|
27
|
:target: ../_images/frontend-kernel.png
|
|
|
|
|
28
|
|
|
|
|
|
29
|
A single kernel can be simultaneously connected to one or more frontends. The
|
|
|
|
|
30
|
kernel has three sockets that serve the following functions:
|
|
|
|
|
31
|
|
|
|
|
|
32
|
1. REQ: this socket is connected to a *single* frontend at a time, and it allows
|
|
|
|
|
33
|
the kernel to request input from a frontend when :func:`raw_input` is called.
|
|
|
|
|
34
|
The frontend holding the matching REP socket acts as a 'virtual keyboard'
|
|
|
|
|
35
|
for the kernel while this communication is happening (illustrated in the
|
|
|
|
|
36
|
figure by the black outline around the central keyboard). In practice,
|
|
|
|
|
37
|
frontends may display such kernel requests using a special input widget or
|
|
|
|
|
38
|
otherwise indicating that the user is to type input for the kernel instead
|
|
|
|
|
39
|
of normal commands in the frontend.
|
|
|
|
|
40
|
|
|
|
|
|
41
|
2. XREP: this single sockets allows multiple incoming connections from
|
|
|
|
|
42
|
frontends, and this is the socket where requests for code execution, object
|
|
|
|
|
43
|
information, prompts, etc. are made to the kernel by any frontend. The
|
|
|
|
|
44
|
communication on this socket is a sequence of request/reply actions from
|
|
|
|
|
45
|
each frontend and the kernel.
|
|
|
|
|
46
|
|
|
|
|
|
47
|
3. PUB: this socket is the 'broadcast channel' where the kernel publishes all
|
|
|
|
|
48
|
side effects (stdout, stderr, etc.) as well as the requests coming from any
|
|
|
|
|
49
|
client over the XREP socket and its own requests on the REP socket. There
|
|
|
|
|
50
|
are a number of actions in Python which generate side effects: :func:`print`
|
|
|
|
|
51
|
writes to ``sys.stdout``, errors generate tracebacks, etc. Additionally, in
|
|
|
|
|
52
|
a multi-client scenario, we want all frontends to be able to know what each
|
|
|
|
|
53
|
other has sent to the kernel (this can be useful in collaborative scenarios,
|
|
|
|
|
54
|
for example). This socket allows both side effects and the information
|
|
|
|
|
55
|
about communications taking place with one client over the XREQ/XREP channel
|
|
|
|
|
56
|
to be made available to all clients in a uniform manner.
|
|
|
|
|
57
|
|
|
|
|
|
58
|
All messages are tagged with enough information (details below) for clients
|
|
|
|
|
59
|
to know which messages come from their own interaction with the kernel and
|
|
|
|
|
60
|
which ones are from other clients, so they can display each type
|
|
|
|
|
61
|
appropriately.
|
|
|
|
|
62
|
|
|
|
|
|
63
|
The actual format of the messages allowed on each of these channels is
|
|
|
|
|
64
|
specified below. Messages are dicts of dicts with string keys and values that
|
|
|
|
|
65
|
are reasonably representable in JSON. Our current implementation uses JSON
|
|
|
|
|
66
|
explicitly as its message format, but this shouldn't be considered a permanent
|
|
|
|
|
67
|
feature. As we've discovered that JSON has non-trivial performance issues due
|
|
|
|
|
68
|
to excessive copying, we may in the future move to a pure pickle-based raw
|
|
|
|
|
69
|
message format. However, it should be possible to easily convert from the raw
|
|
|
|
|
70
|
objects to JSON, since we may have non-python clients (e.g. a web frontend).
|
|
|
|
|
71
|
As long as it's easy to make a JSON version of the objects that is a faithful
|
|
|
|
|
72
|
representation of all the data, we can communicate with such clients.
|
|
|
|
|
73
|
|
|
|
|
|
74
|
.. Note::
|
|
|
|
|
75
|
|
|
|
|
|
76
|
Not all of these have yet been fully fleshed out, but the key ones are, see
|
|
|
|
|
77
|
kernel and frontend files for actual implementation details.
|
|
17
|
|
|
78
|
|
|
18
|
|
|
79
|
|
|
19
|
Python functional API
|
|
80
|
Python functional API
|
|
@@
-26,100
+87,43
b' for sending.'
|
|
26
|
|
|
87
|
|
|
27
|
|
|
88
|
|
|
28
|
General Message Format
|
|
89
|
General Message Format
|
|
29
|
=====================
|
|
90
|
======================
|
|
30
|
|
|
91
|
|
|
31
|
General message format::
|
|
92
|
All messages send or received by any IPython process should have the following
|
|
|
|
|
93
|
generic structure::
|
|
32
|
|
|
94
|
|
|
33
|
{
|
|
95
|
{
|
|
34
|
header : { 'msg_id' : 10, # start with 0
|
|
96
|
# The message header contains a pair of unique identifiers for the
|
|
35
|
'username' : 'name',
|
|
97
|
# originating session and the actual message id, in addition to the
|
|
|
|
|
98
|
# username for the process that generated the message. This is useful in
|
|
|
|
|
99
|
# collaborative settings where multiple users may be interacting with the
|
|
|
|
|
100
|
# same kernel simultaneously, so that frontends can label the various
|
|
|
|
|
101
|
# messages in a meaningful way.
|
|
|
|
|
102
|
'header' : { 'msg_id' : uuid,
|
|
|
|
|
103
|
'username' : str,
|
|
36
|
'session' : uuid
|
|
104
|
'session' : uuid
|
|
37
|
},
|
|
105
|
},
|
|
38
|
parent_header : dict,
|
|
|
|
|
39
|
msg_type : 'string_message_type',
|
|
|
|
|
40
|
content : blackbox_dict , # Must be a dict
|
|
|
|
|
41
|
}
|
|
|
|
|
42
|
|
|
|
|
|
43
|
|
|
|
|
|
44
|
Request/Reply going from kernel for stdin
|
|
|
|
|
45
|
=========================================
|
|
|
|
|
46
|
|
|
|
|
|
47
|
This is a socket that goes in the opposite direction: from the kernel to a
|
|
|
|
|
48
|
*single* frontend, and its purpose is to allow ``raw_input`` and similar
|
|
|
|
|
49
|
operations that read from ``sys.stdin`` on the kernel to be fulfilled by the
|
|
|
|
|
50
|
client. For now we will keep these messages as simple as possible, since they
|
|
|
|
|
51
|
basically only mean to convey the ``raw_input(prompt)`` call.
|
|
|
|
|
52
|
|
|
|
|
|
53
|
Message type: 'input_request'::
|
|
|
|
|
54
|
|
|
|
|
|
55
|
content = { prompt : string }
|
|
|
|
|
56
|
|
|
|
|
|
57
|
Message type: 'input_reply'::
|
|
|
|
|
58
|
|
|
|
|
|
59
|
content = { value : string }
|
|
|
|
|
60
|
|
|
|
|
|
61
|
|
|
|
|
|
62
|
Side effect: (PUB/SUB)
|
|
|
|
|
63
|
======================
|
|
|
|
|
64
|
|
|
|
|
|
65
|
Message type: 'stream'::
|
|
|
|
|
66
|
|
|
|
|
|
67
|
content = {
|
|
|
|
|
68
|
name : 'stdout',
|
|
|
|
|
69
|
data : 'blob',
|
|
|
|
|
70
|
}
|
|
|
|
|
71
|
|
|
|
|
|
72
|
When a kernel receives a raw_input call, it should also broadcast it on the pub
|
|
|
|
|
73
|
socket with the names 'stdin' and 'stdin_reply'. This will allow other clients
|
|
|
|
|
74
|
to monitor/display kernel interactions and possibly replay them to their user
|
|
|
|
|
75
|
or otherwise expose them.
|
|
|
|
|
76
|
|
|
|
|
|
77
|
Message type: 'pyin'::
|
|
|
|
|
78
|
|
|
|
|
|
79
|
content = {
|
|
|
|
|
80
|
code = 'x=1',
|
|
|
|
|
81
|
}
|
|
|
|
|
82
|
|
|
|
|
|
83
|
Message type: 'pyout'::
|
|
|
|
|
84
|
|
|
|
|
|
85
|
content = {
|
|
|
|
|
86
|
data = 'repr(obj)',
|
|
|
|
|
87
|
prompt_number = 10
|
|
|
|
|
88
|
}
|
|
|
|
|
89
|
|
|
|
|
|
90
|
Message type: 'pyerr'::
|
|
|
|
|
91
|
|
|
|
|
|
92
|
content = {
|
|
|
|
|
93
|
# Same as the data payload of a code execute_reply, minus the 'status'
|
|
|
|
|
94
|
# field. See below.
|
|
|
|
|
95
|
}
|
|
|
|
|
96
|
|
|
106
|
|
|
97
|
When the kernel has an unexpected exception, caught by the last-resort
|
|
107
|
# In a chain of messages, the header from the parent is copied so that
|
|
98
|
sys.excepthook, we should broadcast the crash handler's output before exiting.
|
|
108
|
# clients can track where messages come from.
|
|
99
|
This will allow clients to notice that a kernel died, inform the user and
|
|
109
|
'parent_header' : dict,
|
|
100
|
propose further actions.
|
|
|
|
|
101
|
|
|
110
|
|
|
102
|
Message type: 'crash'::
|
|
111
|
# All recognized message type strings are listed below.
|
|
|
|
|
112
|
'msg_type' : str,
|
|
103
|
|
|
113
|
|
|
104
|
content = {
|
|
114
|
# The actual content of the message must be a dict, whose structure
|
|
105
|
traceback : 'full traceback',
|
|
115
|
# depends on the message type.x
|
|
106
|
exc_type : 'TypeError',
|
|
116
|
'content' : dict,
|
|
107
|
exc_value : 'msg'
|
|
|
|
|
108
|
}
|
|
117
|
}
|
|
109
|
|
|
118
|
|
|
|
|
|
119
|
For each message type, the actual content will differ and all existing message
|
|
|
|
|
120
|
types are specified in what follows of this document.
|
|
110
|
|
|
121
|
|
|
111
|
Other potential message types, currently unimplemented, listed below as ideas.
|
|
|
|
|
112
|
|
|
|
|
|
113
|
Message type: 'file'::
|
|
|
|
|
114
|
content = {
|
|
|
|
|
115
|
path : 'cool.jpg',
|
|
|
|
|
116
|
mimetype : string
|
|
|
|
|
117
|
data : 'blob'
|
|
|
|
|
118
|
}
|
|
|
|
|
119
|
|
|
122
|
|
|
|
|
|
123
|
Messages on the XREP/XREQ socket
|
|
|
|
|
124
|
================================
|
|
120
|
|
|
125
|
|
|
121
|
Request/Reply
|
|
126
|
.. _execute:
|
|
122
|
=============
|
|
|
|
|
123
|
|
|
127
|
|
|
124
|
Execute
|
|
128
|
Execute
|
|
125
|
-------
|
|
129
|
-------
|
|
@@
-132,20
+136,34
b" splitting the input for blocks that can all be run as 'single', but in the long"
|
|
132
|
run it may prove cleaner to only use 'single' mode for truly single-line
|
|
136
|
run it may prove cleaner to only use 'single' mode for truly single-line
|
|
133
|
inputs, and run all multiline input in 'exec' mode. This would preserve the
|
|
137
|
inputs, and run all multiline input in 'exec' mode. This would preserve the
|
|
134
|
natural behavior of single-line inputs while allowing long cells to behave more
|
|
138
|
natural behavior of single-line inputs while allowing long cells to behave more
|
|
135
|
likea a script. Some thought is still required here...
|
|
139
|
likea a script. This design will be refined as we complete the implementation.
|
|
136
|
|
|
140
|
|
|
137
|
Message type: 'execute_request'::
|
|
141
|
Message type: ``execute_request``::
|
|
138
|
|
|
142
|
|
|
139
|
content = {
|
|
143
|
content = {
|
|
140
|
code : 'a = 10',
|
|
144
|
# Source code to be executed by the kernel, one or more lines.
|
|
|
|
|
145
|
'code' : str,
|
|
|
|
|
146
|
|
|
|
|
|
147
|
# A boolean flag which, if True, signals the kernel to execute this
|
|
|
|
|
148
|
# code as quietly as possible. This means that the kernel will compile
|
|
|
|
|
149
|
# the code with 'exec' instead of 'single' (so sys.displayhook will not
|
|
|
|
|
150
|
# fire), and will *not*:
|
|
|
|
|
151
|
# - broadcast exceptions on the PUB socket
|
|
|
|
|
152
|
# - do any logging
|
|
|
|
|
153
|
# - populate any history
|
|
|
|
|
154
|
# The default is False.
|
|
|
|
|
155
|
'silent' : bool,
|
|
141
|
}
|
|
156
|
}
|
|
142
|
|
|
157
|
|
|
143
|
Reply:
|
|
158
|
Upon execution, the kernel *always* sends a reply, with a status code
|
|
|
|
|
159
|
indicating what happened and additional data depending on the outcome.
|
|
144
|
|
|
160
|
|
|
145
|
Message type: 'execute_reply'::
|
|
161
|
Message type: ``execute_reply``::
|
|
146
|
|
|
162
|
|
|
147
|
content = {
|
|
163
|
content = {
|
|
148
|
'status' : 'ok' OR 'error' OR 'abort'
|
|
164
|
# One of: 'ok' OR 'error' OR 'abort'
|
|
|
|
|
165
|
'status' : str,
|
|
|
|
|
166
|
|
|
149
|
# Any additional data depends on status value
|
|
167
|
# Any additional data depends on status value
|
|
150
|
}
|
|
168
|
}
|
|
151
|
|
|
169
|
|
|
@@
-156,9
+174,9
b" When status is 'ok', the following extra fields are present::"
|
|
156
|
# for the client to set up the *next* prompt (with identical limitations
|
|
174
|
# for the client to set up the *next* prompt (with identical limitations
|
|
157
|
# to a prompt request)
|
|
175
|
# to a prompt request)
|
|
158
|
'next_prompt' : {
|
|
176
|
'next_prompt' : {
|
|
159
|
prompt_string : string
|
|
177
|
'prompt_string' : str,
|
|
160
|
prompt_number : int
|
|
178
|
'prompt_number' : int,
|
|
161
|
}
|
|
179
|
},
|
|
162
|
|
|
180
|
|
|
163
|
# The prompt number of the actual execution for this code, which may be
|
|
181
|
# The prompt number of the actual execution for this code, which may be
|
|
164
|
# different from the one used when the code was typed, which was the
|
|
182
|
# different from the one used when the code was typed, which was the
|
|
@@
-167,25
+185,39
b" When status is 'ok', the following extra fields are present::"
|
|
167
|
# kernel, since the numbers can go out of sync. GUI clients can use this
|
|
185
|
# kernel, since the numbers can go out of sync. GUI clients can use this
|
|
168
|
# to correct the previously written number in-place, terminal ones may
|
|
186
|
# to correct the previously written number in-place, terminal ones may
|
|
169
|
# re-print a corrected one if desired.
|
|
187
|
# re-print a corrected one if desired.
|
|
170
|
'prompt_number' : number
|
|
188
|
'prompt_number' : int,
|
|
171
|
|
|
189
|
|
|
172
|
# The kernel will often transform the input provided to it. This
|
|
190
|
# The kernel will often transform the input provided to it. This
|
|
173
|
# contains the transformed code, which is what was actually executed.
|
|
191
|
# contains the transformed code, which is what was actually executed.
|
|
174
|
'transformed_code' : new_code
|
|
192
|
'transformed_code' : str,
|
|
175
|
|
|
193
|
|
|
176
|
# This 'payload' needs a bit more thinking. The basic idea is that
|
|
194
|
# The execution payload is a dict with string keys that may have been
|
|
177
|
# certain actions will want to return additional information, such as
|
|
195
|
# produced by the code being executed. It is retrieved by the kernel at
|
|
178
|
# magics producing data output for display by the clients. We may need
|
|
196
|
# the end of the execution and sent back to the front end, which can take
|
|
179
|
# to define a few types of payload, or specify a syntax for the, not sure
|
|
197
|
# action on it as needed. See main text for further details.
|
|
180
|
# yet... FIXME here.
|
|
198
|
'payload' : dict,
|
|
181
|
'payload' : things from page(), for example.
|
|
|
|
|
182
|
}
|
|
199
|
}
|
|
183
|
|
|
200
|
|
|
|
|
|
201
|
.. admonition:: Execution payloads
|
|
|
|
|
202
|
|
|
|
|
|
203
|
The notion of an 'execution payload' is different from a return value of a
|
|
|
|
|
204
|
given set of code, which normally is just displayed on the pyout stream
|
|
|
|
|
205
|
through the PUB socket. The idea of a payload is to allow special types of
|
|
|
|
|
206
|
code, typically magics, to populate a data container in the IPython kernel
|
|
|
|
|
207
|
that will be shipped back to the caller via this channel. The kernel will
|
|
|
|
|
208
|
have an API for this, probably something along the lines of::
|
|
|
|
|
209
|
|
|
|
|
|
210
|
ip.exec_payload_add(key, value)
|
|
|
|
|
211
|
|
|
|
|
|
212
|
though this API is still in the design stages. The data returned in this
|
|
|
|
|
213
|
payload will allow frontends to present special views of what just happened.
|
|
|
|
|
214
|
|
|
|
|
|
215
|
|
|
184
|
When status is 'error', the following extra fields are present::
|
|
216
|
When status is 'error', the following extra fields are present::
|
|
185
|
|
|
217
|
|
|
186
|
{
|
|
218
|
{
|
|
187
|
etype : str # Exception type, as a string
|
|
219
|
'exc_name' : str, # Exception name, as a string
|
|
188
|
evalue : str # Exception value, as a string
|
|
220
|
'exc_value' : str, # Exception value, as a string
|
|
189
|
|
|
221
|
|
|
190
|
# The traceback will contain a list of frames, represented each as a
|
|
222
|
# The traceback will contain a list of frames, represented each as a
|
|
191
|
# string. For now we'll stick to the existing design of ultraTB, which
|
|
223
|
# string. For now we'll stick to the existing design of ultraTB, which
|
|
@@
-195,11
+227,12
b" When status is 'error', the following extra fields are present::"
|
|
195
|
# how much of it to unpack. But for now, let's start with a simple list
|
|
227
|
# how much of it to unpack. But for now, let's start with a simple list
|
|
196
|
# of strings, since that requires only minimal changes to ultratb as
|
|
228
|
# of strings, since that requires only minimal changes to ultratb as
|
|
197
|
# written.
|
|
229
|
# written.
|
|
198
|
traceback : list of strings
|
|
230
|
'traceback' : list,
|
|
199
|
}
|
|
231
|
}
|
|
200
|
|
|
232
|
|
|
201
|
|
|
233
|
|
|
202
|
When status is 'abort', there are for now no additional data fields.
|
|
234
|
When status is 'abort', there are for now no additional data fields. This
|
|
|
|
|
235
|
happens when the kernel was interrupted by a signal.
|
|
203
|
|
|
236
|
|
|
204
|
|
|
237
|
|
|
205
|
Prompt
|
|
238
|
Prompt
|
|
@@
-207,18
+240,18
b' Prompt'
|
|
207
|
|
|
240
|
|
|
208
|
A simple request for a current prompt string.
|
|
241
|
A simple request for a current prompt string.
|
|
209
|
|
|
242
|
|
|
210
|
Message type: 'prompt_request'::
|
|
243
|
Message type: ``prompt_request``::
|
|
211
|
|
|
244
|
|
|
212
|
content = {}
|
|
245
|
content = {}
|
|
213
|
|
|
246
|
|
|
214
|
In the reply, the prompt string comes back with the prompt number placeholder
|
|
247
|
In the reply, the prompt string comes back with the prompt number placeholder
|
|
215
|
*unevaluated*. The message format is:
|
|
248
|
*unevaluated*. The message format is:
|
|
216
|
|
|
249
|
|
|
217
|
Message type: 'prompt_reply'::
|
|
250
|
Message type: ``prompt_reply``::
|
|
218
|
|
|
251
|
|
|
219
|
content = {
|
|
252
|
content = {
|
|
220
|
prompt_string : string
|
|
253
|
'prompt_string' : str,
|
|
221
|
prompt_number : int
|
|
254
|
'prompt_number' : int,
|
|
222
|
}
|
|
255
|
}
|
|
223
|
|
|
256
|
|
|
224
|
Clients can produce a prompt with ``prompt_string.format(prompt_number)``, but
|
|
257
|
Clients can produce a prompt with ``prompt_string.format(prompt_number)``, but
|
|
@@
-227,58
+260,301
b' later, in the case where multiple clients are interacting with a single'
|
|
227
|
kernel.
|
|
260
|
kernel.
|
|
228
|
|
|
261
|
|
|
229
|
|
|
262
|
|
|
|
|
|
263
|
Object information
|
|
|
|
|
264
|
------------------
|
|
|
|
|
265
|
|
|
|
|
|
266
|
One of IPython's most used capabilities is the introspection of Python objects
|
|
|
|
|
267
|
in the user's namespace, typically invoked via the ``?`` and ``??`` characters
|
|
|
|
|
268
|
(which in reality are shorthands for the ``%pinfo`` magic). This is used often
|
|
|
|
|
269
|
enough that it warrants an explicit message type, especially because frontends
|
|
|
|
|
270
|
may want to get object information in response to user keystrokes (like Tab or
|
|
|
|
|
271
|
F1) besides from the user explicitly typing code like ``x??``.
|
|
|
|
|
272
|
|
|
|
|
|
273
|
Message type: ``object_info_request``::
|
|
|
|
|
274
|
|
|
|
|
|
275
|
content = {
|
|
|
|
|
276
|
# The (possibly dotted) name of the object to be searched in all
|
|
|
|
|
277
|
# relevant namespaces
|
|
|
|
|
278
|
'name' : str,
|
|
|
|
|
279
|
|
|
|
|
|
280
|
# The level of detail desired. The default (0) is equivalent to typing
|
|
|
|
|
281
|
# 'x?' at the prompt, 1 is equivalent to 'x??'.
|
|
|
|
|
282
|
'detail_level' : int,
|
|
|
|
|
283
|
}
|
|
|
|
|
284
|
|
|
|
|
|
285
|
The returned information will be a dictionary with keys very similar to the
|
|
|
|
|
286
|
field names that IPython prints at the terminal.
|
|
|
|
|
287
|
|
|
|
|
|
288
|
Message type: ``object_info_reply``::
|
|
|
|
|
289
|
|
|
|
|
|
290
|
content = {
|
|
|
|
|
291
|
# Flags for magics and system aliases
|
|
|
|
|
292
|
'ismagic' : bool,
|
|
|
|
|
293
|
'isalias' : bool,
|
|
|
|
|
294
|
|
|
|
|
|
295
|
# The name of the namespace where the object was found ('builtin',
|
|
|
|
|
296
|
# 'magics', 'alias', 'interactive', etc.)
|
|
|
|
|
297
|
'namespace' : str,
|
|
|
|
|
298
|
|
|
|
|
|
299
|
# The type name will be type.__name__ for normal Python objects, but it
|
|
|
|
|
300
|
# can also be a string like 'Magic function' or 'System alias'
|
|
|
|
|
301
|
'type_name' : str,
|
|
|
|
|
302
|
|
|
|
|
|
303
|
'string_form' : str,
|
|
|
|
|
304
|
|
|
|
|
|
305
|
# For objects with a __class__ attribute this will be set
|
|
|
|
|
306
|
'base_class' : str,
|
|
|
|
|
307
|
|
|
|
|
|
308
|
# For objects with a __len__ attribute this will be set
|
|
|
|
|
309
|
'length' : int,
|
|
|
|
|
310
|
|
|
|
|
|
311
|
# If the object is a function, class or method whose file we can find,
|
|
|
|
|
312
|
# we give its full path
|
|
|
|
|
313
|
'file' : str,
|
|
|
|
|
314
|
|
|
|
|
|
315
|
# For pure Python callable objects, we can reconstruct the object
|
|
|
|
|
316
|
# definition line which provides its call signature
|
|
|
|
|
317
|
'definition' : str,
|
|
|
|
|
318
|
|
|
|
|
|
319
|
# For instances, provide the constructor signature (the definition of
|
|
|
|
|
320
|
# the __init__ method):
|
|
|
|
|
321
|
'init_definition' : str,
|
|
|
|
|
322
|
|
|
|
|
|
323
|
# Docstrings: for any object (function, method, module, package) with a
|
|
|
|
|
324
|
# docstring, we show it. But in addition, we may provide additional
|
|
|
|
|
325
|
# docstrings. For example, for instances we will show the constructor
|
|
|
|
|
326
|
# and class docstrings as well, if available.
|
|
|
|
|
327
|
'docstring' : str,
|
|
|
|
|
328
|
|
|
|
|
|
329
|
# For instances, provide the constructor and class docstrings
|
|
|
|
|
330
|
'init_docstring' : str,
|
|
|
|
|
331
|
'class_docstring' : str,
|
|
|
|
|
332
|
|
|
|
|
|
333
|
# If detail_level was 1, we also try to find the source code that
|
|
|
|
|
334
|
# defines the object, if possible. The string 'None' will indicate
|
|
|
|
|
335
|
# that no source was found.
|
|
|
|
|
336
|
'source' : str,
|
|
|
|
|
337
|
}
|
|
|
|
|
338
|
|
|
|
|
|
339
|
|
|
230
|
Complete
|
|
340
|
Complete
|
|
231
|
--------
|
|
341
|
--------
|
|
232
|
|
|
342
|
|
|
233
|
Message type: 'complete_request'::
|
|
343
|
Message type: ``complete_request``::
|
|
234
|
|
|
344
|
|
|
235
|
content = {
|
|
345
|
content = {
|
|
236
|
text : 'a.f', # complete on this
|
|
346
|
# The text to be completed, such as 'a.is'
|
|
237
|
line : 'print a.f' # full line
|
|
347
|
'text' : str,
|
|
|
|
|
348
|
|
|
|
|
|
349
|
# The full line, such as 'print a.is'. This allows completers to
|
|
|
|
|
350
|
# make decisions that may require information about more than just the
|
|
|
|
|
351
|
# current word.
|
|
|
|
|
352
|
'line' : str,
|
|
238
|
}
|
|
353
|
}
|
|
239
|
|
|
354
|
|
|
240
|
Message type: 'complete_reply'::
|
|
355
|
Message type: ``complete_reply``::
|
|
241
|
|
|
356
|
|
|
242
|
content = {
|
|
357
|
content = {
|
|
243
|
matches : ['a.foo', 'a.bar']
|
|
358
|
# The list of all matches to the completion request, such as
|
|
|
|
|
359
|
# ['a.isalnum', 'a.isalpha'] for the above example.
|
|
|
|
|
360
|
'matches' : list
|
|
244
|
}
|
|
361
|
}
|
|
245
|
|
|
362
|
|
|
246
|
|
|
363
|
|
|
247
|
History
|
|
364
|
History
|
|
248
|
-------
|
|
365
|
-------
|
|
249
|
|
|
366
|
|
|
250
|
For clients to explicitly request history from a kernel
|
|
367
|
For clients to explicitly request history from a kernel. The kernel has all
|
|
|
|
|
368
|
the actual execution history stored in a single location, so clients can
|
|
|
|
|
369
|
request it from the kernel when needed.
|
|
251
|
|
|
370
|
|
|
252
|
Message type: 'history_request'::
|
|
371
|
Message type: ``history_request``::
|
|
253
|
|
|
372
|
|
|
254
|
content = {
|
|
373
|
content = {
|
|
255
|
output : boolean. If true, also return output history in the resulting
|
|
374
|
|
|
256
|
dict.
|
|
375
|
# If true, also return output history in the resulting dict.
|
|
257
|
|
|
376
|
'output' : bool,
|
|
258
|
range : optional. A number, a pair of numbers, 'all'
|
|
377
|
|
|
259
|
If not given, last 40 are returned.
|
|
378
|
# This parameter can be one of: A number, a pair of numbers, 'all'
|
|
260
|
- number n: return the last n entries.
|
|
379
|
# If not given, last 40 are returned.
|
|
261
|
- pair n1, n2: return entries in the range(n1, n2).
|
|
380
|
# - number n: return the last n entries.
|
|
262
|
- 'all': return all history
|
|
381
|
# - pair n1, n2: return entries in the range(n1, n2).
|
|
263
|
|
|
382
|
# - 'all': return all history
|
|
264
|
filter : optional, string
|
|
383
|
'range' : n or (n1, n2) or 'all',
|
|
265
|
If given, treated as a regular expression and only matching entries are
|
|
384
|
|
|
266
|
returned. re.search() is used to find matches.
|
|
385
|
# If a filter is given, it is treated as a regular expression and only
|
|
|
|
|
386
|
# matching entries are returned. re.search() is used to find matches.
|
|
|
|
|
387
|
'filter' : str,
|
|
267
|
}
|
|
388
|
}
|
|
268
|
|
|
389
|
|
|
269
|
Message type: 'history_reply'::
|
|
390
|
Message type: ``history_reply``::
|
|
270
|
|
|
391
|
|
|
271
|
content = {
|
|
392
|
content = {
|
|
272
|
input : list of pairs (number, input)
|
|
393
|
# A list of (number, input) pairs
|
|
273
|
output : list of pairs (number, output). Empty if not requested.
|
|
394
|
'input' : list,
|
|
|
|
|
395
|
|
|
|
|
|
396
|
# A list of (number, output) pairs
|
|
|
|
|
397
|
'output' : list,
|
|
274
|
}
|
|
398
|
}
|
|
275
|
|
|
399
|
|
|
276
|
|
|
400
|
|
|
277
|
Control
|
|
401
|
Control
|
|
278
|
-------
|
|
402
|
-------
|
|
279
|
|
|
403
|
|
|
280
|
Message type: 'heartbeat'::
|
|
404
|
Message type: ``heartbeat``::
|
|
281
|
|
|
405
|
|
|
282
|
content = {
|
|
406
|
content = {
|
|
283
|
# XXX - unfinished
|
|
407
|
# FIXME - unfinished
|
|
284
|
}
|
|
408
|
}
|
|
|
|
|
409
|
|
|
|
|
|
410
|
|
|
|
|
|
411
|
Messages on the PUB/SUB socket
|
|
|
|
|
412
|
==============================
|
|
|
|
|
413
|
|
|
|
|
|
414
|
Streams (stdout, stderr, etc)
|
|
|
|
|
415
|
------------------------------
|
|
|
|
|
416
|
|
|
|
|
|
417
|
Message type: ``stream``::
|
|
|
|
|
418
|
|
|
|
|
|
419
|
content = {
|
|
|
|
|
420
|
# The name of the stream is one of 'stdin', 'stdout', 'stderr'
|
|
|
|
|
421
|
'name' : str,
|
|
|
|
|
422
|
|
|
|
|
|
423
|
# The data is an arbitrary string to be written to that stream
|
|
|
|
|
424
|
'data' : str,
|
|
|
|
|
425
|
}
|
|
|
|
|
426
|
|
|
|
|
|
427
|
When a kernel receives a raw_input call, it should also broadcast it on the pub
|
|
|
|
|
428
|
socket with the names 'stdin' and 'stdin_reply'. This will allow other clients
|
|
|
|
|
429
|
to monitor/display kernel interactions and possibly replay them to their user
|
|
|
|
|
430
|
or otherwise expose them.
|
|
|
|
|
431
|
|
|
|
|
|
432
|
Python inputs
|
|
|
|
|
433
|
-------------
|
|
|
|
|
434
|
|
|
|
|
|
435
|
These messages are the re-broadcast of the ``execute_request``.
|
|
|
|
|
436
|
|
|
|
|
|
437
|
Message type: ``pyin``::
|
|
|
|
|
438
|
|
|
|
|
|
439
|
content = {
|
|
|
|
|
440
|
# Source code to be executed, one or more lines
|
|
|
|
|
441
|
'code' : str
|
|
|
|
|
442
|
}
|
|
|
|
|
443
|
|
|
|
|
|
444
|
Python outputs
|
|
|
|
|
445
|
--------------
|
|
|
|
|
446
|
|
|
|
|
|
447
|
When Python produces output from code that has been compiled in with the
|
|
|
|
|
448
|
'single' flag to :func:`compile`, any expression that produces a value (such as
|
|
|
|
|
449
|
``1+1``) is passed to ``sys.displayhook``, which is a callable that can do with
|
|
|
|
|
450
|
this value whatever it wants. The default behavior of ``sys.displayhook`` in
|
|
|
|
|
451
|
the Python interactive prompt is to print to ``sys.stdout`` the :func:`repr` of
|
|
|
|
|
452
|
the value as long as it is not ``None`` (which isn't printed at all). In our
|
|
|
|
|
453
|
case, the kernel instantiates as ``sys.displayhook`` an object which has
|
|
|
|
|
454
|
similar behavior, but which instead of printing to stdout, broadcasts these
|
|
|
|
|
455
|
values as ``pyout`` messages for clients to display appropriately.
|
|
|
|
|
456
|
|
|
|
|
|
457
|
Message type: ``pyout``::
|
|
|
|
|
458
|
|
|
|
|
|
459
|
content = {
|
|
|
|
|
460
|
# The data is typically the repr() of the object.
|
|
|
|
|
461
|
'data' : str,
|
|
|
|
|
462
|
|
|
|
|
|
463
|
# The prompt number for this execution is also provided so that clients
|
|
|
|
|
464
|
# can display it, since IPython automatically creates variables called
|
|
|
|
|
465
|
# _N (for prompt N).
|
|
|
|
|
466
|
'prompt_number' : int,
|
|
|
|
|
467
|
}
|
|
|
|
|
468
|
|
|
|
|
|
469
|
Python errors
|
|
|
|
|
470
|
-------------
|
|
|
|
|
471
|
|
|
|
|
|
472
|
When an error occurs during code execution
|
|
|
|
|
473
|
|
|
|
|
|
474
|
Message type: ``pyerr``::
|
|
|
|
|
475
|
|
|
|
|
|
476
|
content = {
|
|
|
|
|
477
|
# Similar content to the execute_reply messages for the 'error' case,
|
|
|
|
|
478
|
# except the 'status' field is omitted.
|
|
|
|
|
479
|
}
|
|
|
|
|
480
|
|
|
|
|
|
481
|
Kernel crashes
|
|
|
|
|
482
|
--------------
|
|
|
|
|
483
|
|
|
|
|
|
484
|
When the kernel has an unexpected exception, caught by the last-resort
|
|
|
|
|
485
|
sys.excepthook, we should broadcast the crash handler's output before exiting.
|
|
|
|
|
486
|
This will allow clients to notice that a kernel died, inform the user and
|
|
|
|
|
487
|
propose further actions.
|
|
|
|
|
488
|
|
|
|
|
|
489
|
Message type: ``crash``::
|
|
|
|
|
490
|
|
|
|
|
|
491
|
content = {
|
|
|
|
|
492
|
# Similarly to the 'error' case for execute_reply messages, this will
|
|
|
|
|
493
|
# contain exc_name, exc_type and traceback fields.
|
|
|
|
|
494
|
|
|
|
|
|
495
|
# An additional field with supplementary information such as where to
|
|
|
|
|
496
|
# send the crash message
|
|
|
|
|
497
|
'info' : str,
|
|
|
|
|
498
|
}
|
|
|
|
|
499
|
|
|
|
|
|
500
|
|
|
|
|
|
501
|
Future ideas
|
|
|
|
|
502
|
------------
|
|
|
|
|
503
|
|
|
|
|
|
504
|
Other potential message types, currently unimplemented, listed below as ideas.
|
|
|
|
|
505
|
|
|
|
|
|
506
|
Message type: ``file``::
|
|
|
|
|
507
|
|
|
|
|
|
508
|
content = {
|
|
|
|
|
509
|
'path' : 'cool.jpg',
|
|
|
|
|
510
|
'mimetype' : str,
|
|
|
|
|
511
|
'data' : str,
|
|
|
|
|
512
|
}
|
|
|
|
|
513
|
|
|
|
|
|
514
|
|
|
|
|
|
515
|
Messages on the REQ/REP socket
|
|
|
|
|
516
|
==============================
|
|
|
|
|
517
|
|
|
|
|
|
518
|
This is a socket that goes in the opposite direction: from the kernel to a
|
|
|
|
|
519
|
*single* frontend, and its purpose is to allow ``raw_input`` and similar
|
|
|
|
|
520
|
operations that read from ``sys.stdin`` on the kernel to be fulfilled by the
|
|
|
|
|
521
|
client. For now we will keep these messages as simple as possible, since they
|
|
|
|
|
522
|
basically only mean to convey the ``raw_input(prompt)`` call.
|
|
|
|
|
523
|
|
|
|
|
|
524
|
Message type: ``input_request``::
|
|
|
|
|
525
|
|
|
|
|
|
526
|
content = { 'prompt' : str }
|
|
|
|
|
527
|
|
|
|
|
|
528
|
Message type: ``input_reply``::
|
|
|
|
|
529
|
|
|
|
|
|
530
|
content = { 'value' : str }
|
|
|
|
|
531
|
|
|
|
|
|
532
|
.. Note::
|
|
|
|
|
533
|
|
|
|
|
|
534
|
We do not explicitly try to forward the raw ``sys.stdin`` object, because in
|
|
|
|
|
535
|
practice the kernel should behave like an interactive program. When a
|
|
|
|
|
536
|
program is opened on the console, the keyboard effectively takes over the
|
|
|
|
|
537
|
``stdin`` file descriptor, and it can't be used for raw reading anymore.
|
|
|
|
|
538
|
Since the IPython kernel effectively behaves like a console program (albeit
|
|
|
|
|
539
|
one whose "keyboard" is actually living in a separate process and
|
|
|
|
|
540
|
transported over the zmq connection), raw ``stdin`` isn't expected to be
|
|
|
|
|
541
|
available.
|
|
|
|
|
542
|
|
|
|
|
|
543
|
|
|
|
|
|
544
|
ToDo
|
|
|
|
|
545
|
====
|
|
|
|
|
546
|
|
|
|
|
|
547
|
Missing things include:
|
|
|
|
|
548
|
|
|
|
|
|
549
|
* Important: finish thinking through the payload concept and API.
|
|
|
|
|
550
|
|
|
|
|
|
551
|
* Important: ensure that we have a good solution for magics like %edit. It's
|
|
|
|
|
552
|
likely that with the payload concept we can build a full solution, but not
|
|
|
|
|
553
|
100% clear yet.
|
|
|
|
|
554
|
|
|
|
|
|
555
|
* Finishing the details of the heartbeat protocol.
|
|
|
|
|
556
|
|
|
|
|
|
557
|
* Signal handling: specify what kind of information kernel should broadcast (or
|
|
|
|
|
558
|
not) when it receives signals.
|
|
|
|
|
559
|
|
|
|
|
|
560
|
.. include:: ../links.rst
|