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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
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 |
|
|
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 |
|
|
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. | |||
81 | } |
|
182 | } | |
82 |
|
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 | |||
|
222 | } | |||
|
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 |
|
|
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 |
|
|
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 |
|
|
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