##// END OF EJS Templates
More complete message specification covering all the major types.
Fernando Perez -
Show More
@@ -5,6 +5,26 b' Message Specification'
5 Note: not all of these have yet been fully fleshed out, but the key ones are,
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.
6 see kernel and frontend files for actual implementation details.
7
7
8 Messages are dicts of dicts with string keys and values that are reasonably
9 representable in JSON. Our current implementation uses JSON explicitly as its
10 message format, but this shouldn't be considered a permanent feature. As we've
11 discovered that JSON has non-trivial performance issues due to excessive
12 copying, we may in the future move to a pure pickle-based raw message format.
13 However, it should be possible to easily convert from the raw objects to JSON,
14 since we may have non-python clients (e.g. a web frontend). As long as it's
15 easy to make a JSON version of the objects that is a faithful representation of
16 all the data, we can communicate with such clients.
17
18
19 Python functional API
20 =====================
21
22 As messages are dicts, they map naturally to a ``func(**kw)`` call form. We
23 should develop, at a few key points, functional forms of all the requests that
24 take arguments in this manner and automatically construct the necessary dict
25 for sending.
26
27
8 General Message Format
28 General Message Format
9 =====================
29 =====================
10
30
@@ -20,30 +40,66 b' General message format::'
20 content : blackbox_dict , # Must be a dict
40 content : blackbox_dict , # Must be a dict
21 }
41 }
22
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
23 Side effect: (PUB/SUB)
62 Side effect: (PUB/SUB)
24 ======================
63 ======================
25
64
26 # msg_type = 'stream'::
65 Message type: 'stream'::
27
66
28 content = {
67 content = {
29 name : 'stdout',
68 name : 'stdout',
30 data : 'blob',
69 data : 'blob',
31 }
70 }
32
71
33 # msg_type = 'pyin'::
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'::
34
78
35 content = {
79 content = {
36 code = 'x=1',
80 code = 'x=1',
37 }
81 }
38
82
39 # msg_type = 'pyout'::
83 Message type: 'pyout'::
40
84
41 content = {
85 content = {
42 data = 'repr(obj)',
86 data = 'repr(obj)',
43 prompt_number = 10
87 prompt_number = 10
44 }
88 }
45
89
46 # msg_type = 'pyerr'::
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
97 When the kernel has an unexpected exception, caught by the last-resort
98 sys.excepthook, we should broadcast the crash handler's output before exiting.
99 This will allow clients to notice that a kernel died, inform the user and
100 propose further actions.
101
102 Message type: 'crash'::
47
103
48 content = {
104 content = {
49 traceback : 'full traceback',
105 traceback : 'full traceback',
@@ -51,21 +107,34 b' Side effect: (PUB/SUB)'
51 exc_value : 'msg'
107 exc_value : 'msg'
52 }
108 }
53
109
54 # msg_type = 'file':
110
111 Other potential message types, currently unimplemented, listed below as ideas.
112
113 Message type: 'file'::
55 content = {
114 content = {
56 path = 'cool.jpg',
115 path : 'cool.jpg',
116 mimetype : string
57 data : 'blob'
117 data : 'blob'
58 }
118 }
59
119
120
60 Request/Reply
121 Request/Reply
61 =============
122 =============
62
123
63 Execute
124 Execute
64 -------
125 -------
65
126
66 Request:
127 The execution request contains a single string, but this may be a multiline
128 string. The kernel is responsible for splitting this into possibly more than
129 one block and deciding whether to compile these in 'single' or 'exec' mode.
130 We're still sorting out this policy. The current inputsplitter is capable of
131 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
133 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
135 likea a script. Some thought is still required here...
67
136
68 # msg_type = 'execute_request'::
137 Message type: 'execute_request'::
69
138
70 content = {
139 content = {
71 code : 'a = 10',
140 code : 'a = 10',
@@ -73,33 +142,142 b' Request:'
73
142
74 Reply:
143 Reply:
75
144
76 # msg_type = 'execute_reply'::
145 Message type: 'execute_reply'::
77
146
78 content = {
147 content = {
79 'status' : 'ok' OR 'error' OR 'abort'
148 'status' : 'ok' OR 'error' OR 'abort'
80 # data depends on status value
149 # Any additional data depends on status value
150 }
151
152 When status is 'ok', the following extra fields are present::
153
154 {
155 # This has the same structure as the output of a prompt request, but is
156 # for the client to set up the *next* prompt (with identical limitations
157 # to a prompt request)
158 'next_prompt' : {
159 prompt_string : string
160 prompt_number : int
161 }
162
163 # 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
165 # 'next_prompt' field of the *previous* request. They will differ in the
166 # case where there is more than one client talking simultaneously to a
167 # 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
169 # re-print a corrected one if desired.
170 'prompt_number' : number
171
172 # The kernel will often transform the input provided to it. This
173 # contains the transformed code, which is what was actually executed.
174 'transformed_code' : new_code
175
176 # This 'payload' needs a bit more thinking. The basic idea is that
177 # certain actions will want to return additional information, such as
178 # magics producing data output for display by the clients. We may need
179 # to define a few types of payload, or specify a syntax for the, not sure
180 # yet... FIXME here.
181 'payload' : things from page(), for example.
182 }
183
184 When status is 'error', the following extra fields are present::
185
186 {
187 etype : str # Exception type, as a string
188 evalue : str # Exception value, as a string
189
190 # 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
192 # controls exception level of detail statefully. But eventually we'll
193 # want to grow into a model where more information is collected and
194 # packed into the traceback object, with clients deciding how little or
195 # 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
197 # written.
198 traceback : list of strings
199 }
200
201
202 When status is 'abort', there are for now no additional data fields.
203
204
205 Prompt
206 ------
207
208 A simple request for a current prompt string.
209
210 Message type: 'prompt_request'::
211
212 content = {}
213
214 In the reply, the prompt string comes back with the prompt number placeholder
215 *unevaluated*. The message format is:
216
217 Message type: 'prompt_reply'::
218
219 content = {
220 prompt_string : string
221 prompt_number : int
81 }
222 }
82
223
224 Clients can produce a prompt with ``prompt_string.format(prompt_number)``, but
225 they should be aware that the actual prompt number for that input could change
226 later, in the case where multiple clients are interacting with a single
227 kernel.
228
229
83 Complete
230 Complete
84 --------
231 --------
85
232
86 # msg_type = 'complete_request'::
233 Message type: 'complete_request'::
87
234
88 content = {
235 content = {
89 text : 'a.f', # complete on this
236 text : 'a.f', # complete on this
90 line : 'print a.f' # full line
237 line : 'print a.f' # full line
91 }
238 }
92
239
93 # msg_type = 'complete_reply'::
240 Message type: 'complete_reply'::
94
241
95 content = {
242 content = {
96 matches : ['a.foo', 'a.bar']
243 matches : ['a.foo', 'a.bar']
97 }
244 }
98
245
246
247 History
248 -------
249
250 For clients to explicitly request history from a kernel
251
252 Message type: 'history_request'::
253
254 content = {
255 output : boolean. If true, also return output history in the resulting
256 dict.
257
258 range : optional. A number, a pair of numbers, 'all'
259 If not given, last 40 are returned.
260 - number n: return the last n entries.
261 - pair n1, n2: return entries in the range(n1, n2).
262 - 'all': return all history
263
264 filter : optional, string
265 If given, treated as a regular expression and only matching entries are
266 returned. re.search() is used to find matches.
267 }
268
269 Message type: 'history_reply'::
270
271 content = {
272 input : list of pairs (number, input)
273 output : list of pairs (number, output). Empty if not requested.
274 }
275
276
99 Control
277 Control
100 -------
278 -------
101
279
102 # msg_type = 'heartbeat'::
280 Message type: 'heartbeat'::
103
281
104 content = {
282 content = {
105 # XXX - unfinished
283 # XXX - unfinished
General Comments 0
You need to be logged in to leave comments. Login now