jupyter_client/commands.rs
1/*! Available commands to send to the kernel.
2
3These should be constructed, and then sent to the kernel via
4[`Client::send_shell_command`][send-shell-command] or
5[`Client::send_control_command`][send-control-command].
6
7[send-shell-command]: ../struct.Client.html#method.send_shell_command
8[send-control-command]: ../struct.Client.html#method.send_control_command
9*/
10use errors::Result;
11use header::Header;
12use hmac::Mac;
13use log::trace;
14use serde::{Serialize as SerdeSerialize, Serializer};
15use serde_derive::Serialize;
16use serde_json::json;
17use std::collections::HashMap;
18use std::fmt::Debug;
19use wire::WireMessage;
20
21/** Available commands.
22 */
23#[derive(Serialize, Debug)]
24#[serde(untagged)]
25pub enum Command {
26 /// Ask for information about the running kernel
27 KernelInfo,
28 /// Execute a specific command
29 Execute {
30 /// Source code to be executed by the kernel, one or more lines.
31 code: String,
32 /** A boolean flag which, if `true`, signals the kernel to execute
33 this code as quietly as possible. `silent=true` forces `store_history` to be `false`, and
34 will *not*:
35 - broadcast output on the IOPub channel
36 - have an execute_result
37 The default is `false`.
38 */
39 silent: bool,
40 /** A boolean flag which, if `true`, signals the kernel to populate history
41 The default is `true` if silent is `false`. If silent is `true`, `store_history` is forced
42 to be `false`.
43 */
44 store_history: bool,
45 /** A `HashMap` mapping names to expressions to be evaluated in the
46 user's `HashMap`. The rich display-data representation of each will be evaluated after
47 execution. See the `display_data` content for the structure of the representation data.
48 */
49 user_expressions: HashMap<String, String>,
50 /** Some frontends do not support stdin requests.
51 If this is true, code running in the kernel can prompt the user for input with an
52 `input_request` message. If it is `false`, the kernel should not send these messages.
53 */
54 allow_stdin: bool,
55 /** A boolean flag, which, if `true`, does not abort the execution queue, if an exception
56 * is encountered.
57 This allows the queued execution of multiple `execute_requests`, even if they generate
58 exceptions.
59 */
60 stop_on_error: bool,
61 },
62 /// Perform introspection into a piece of code.
63 Inspect {
64 /** The code context in which introspection is requested
65 this may be up to an entire multiline cell.
66 */
67 code: String,
68
69 /** The cursor position within 'code' (in unicode characters) where inspection is requested
70 */
71 cursor_pos: u64,
72
73 /** The level of detail desired. In IPython, the default (0) is equivalent to typing
74 'x?' at the prompt, 1 is equivalent to 'x??'.
75 The difference is up to kernels, but in IPython level 1 includes the source code
76 if available.
77 */
78 detail_level: DetailLevel,
79 },
80 /// Ask the kernel to complete the code at the cursor.
81 Complete {
82 /** The code context in which completion is requested
83 this may be up to an entire multiline cell, such as
84 'foo = a.isal'
85 */
86 code: String,
87
88 /** The cursor position within 'code' (in unicode characters) where completion is requested
89 */
90 cursor_pos: u64,
91 },
92 /// Fetch history from the kernel.
93 History {
94 /// If True, also return output history in the resulting dict.
95 output: bool,
96
97 /// If True, return the raw input history, else the transformed input.
98 raw: bool,
99
100 /** So far, this can be `range`, `tail` or `search`.
101 If `hist_access_type` is `range`, get a range of input cells. session
102 is a number counting up each time the kernel starts; you can give
103 a positive session number, or a negative number to count back from
104 the current session.
105 `start` and `stop` are line (cell) numbers within that session.
106 If `hist_access_type` is 'tail' or 'search', get the last n cells.
107 If `hist_access_type` is 'search', get cells matching the specified glob
108 pattern (with * and ? as wildcards).
109 */
110 hist_access_type: HistoryAccessType,
111
112 /** If `hist_access_type` is 'search' and unique is true, do not
113 include duplicated history. Default is false.
114 */
115 unique: bool,
116 },
117 /// Ask the kernel if the current code is complete
118 IsComplete {
119 /// The code entered so far as a multiline string
120 code: String,
121 },
122 /// Tell the kernel to shutdown.
123 Shutdown {
124 /// False if final shutdown, or True if shutdown precedes a restart
125 restart: bool,
126 },
127 /// Fetch comm info.
128 CommInfo {
129 /// The target name
130 target_name: Option<String>,
131 },
132}
133
134impl Command {
135 pub(crate) fn into_wire<M: Mac + Debug>(self, auth: M) -> Result<WireMessage<M>> {
136 let msg = match self {
137 Command::KernelInfo => {
138 let header = Header::new("kernel_info_request");
139 let header_bytes = header.to_bytes()?;
140 Ok(WireMessage {
141 header: header_bytes.to_vec(),
142 parent_header: b"{}".to_vec(),
143 metadata: b"{}".to_vec(),
144 content: b"{}".to_vec(),
145 auth,
146 })
147 }
148 r @ Command::Execute { .. } => {
149 let header = Header::new("execute_request");
150 let header_bytes = header.to_bytes()?;
151 let content_str = serde_json::to_string(&r)?;
152 let content = content_str.into_bytes();
153
154 Ok(WireMessage {
155 header: header_bytes.to_vec(),
156 parent_header: b"{}".to_vec(),
157 metadata: b"{}".to_vec(),
158 content,
159 auth,
160 })
161 }
162 r @ Command::Inspect { .. } => {
163 let header = Header::new("inspect_request");
164 let header_bytes = header.to_bytes()?;
165 let content_str = serde_json::to_string(&r)?;
166 let content = content_str.into_bytes();
167
168 Ok(WireMessage {
169 header: header_bytes.to_vec(),
170 parent_header: b"{}".to_vec(),
171 metadata: b"{}".to_vec(),
172 content,
173 auth,
174 })
175 }
176 r @ Command::Complete { .. } => {
177 let header = Header::new("complete_request");
178 let header_bytes = header.to_bytes()?;
179 let content_str = serde_json::to_string(&r)?;
180 let content = content_str.into_bytes();
181
182 Ok(WireMessage {
183 header: header_bytes.to_vec(),
184 parent_header: b"{}".to_vec(),
185 metadata: b"{}".to_vec(),
186 content,
187 auth,
188 })
189 }
190 Command::History {
191 output,
192 raw,
193 hist_access_type,
194 unique,
195 } => {
196 let header = Header::new("history_request");
197 let header_bytes = header.to_bytes()?;
198
199 let content = match hist_access_type {
200 HistoryAccessType::Tail { n } => json!({
201 "output": output,
202 "raw": raw,
203 "unique": unique,
204 "hist_access_type": "tail",
205 "session": null,
206 "start": null,
207 "stop": null,
208 "n": n,
209 "pattern": null,
210 }),
211 HistoryAccessType::Range {
212 session,
213 start,
214 stop,
215 } => json!({
216 "output": output,
217 "raw": raw,
218 "unique": unique,
219 "hist_access_type": "tail",
220 "session": session,
221 "start": start,
222 "stop": stop,
223 "n": null,
224 "pattern": null,
225 }),
226 HistoryAccessType::Search { pattern } => json!({
227 "output": output,
228 "raw": raw,
229 "unique": unique,
230 "hist_access_type": "tail",
231 "session": null,
232 "start": null,
233 "stop": null,
234 "n": null,
235 "pattern": pattern,
236 }),
237 };
238
239 let content_str = serde_json::to_string(&content)?;
240 let content = content_str.into_bytes();
241
242 Ok(WireMessage {
243 header: header_bytes.to_vec(),
244 parent_header: b"{}".to_vec(),
245 metadata: b"{}".to_vec(),
246 content,
247 auth,
248 })
249 }
250 Command::IsComplete { code } => {
251 let header = Header::new("is_complete_request");
252 let header_bytes = header.to_bytes()?;
253
254 let content_json = json!({
255 "code": code,
256 });
257 let content_str = serde_json::to_string(&content_json)?;
258 let content = content_str.into_bytes();
259
260 Ok(WireMessage {
261 header: header_bytes.to_vec(),
262 parent_header: b"{}".to_vec(),
263 metadata: b"{}".to_vec(),
264 content: content,
265 auth,
266 })
267 }
268 Command::Shutdown { restart } => {
269 let header = Header::new("shutdown_request");
270 let header_bytes = header.to_bytes()?;
271 let content_json = json!({
272 "restart": restart,
273 });
274 let content_str = serde_json::to_string(&content_json)?;
275 let content = content_str.into_bytes();
276
277 Ok(WireMessage {
278 header: header_bytes.to_vec(),
279 parent_header: b"{}".to_vec(),
280 metadata: b"{}".to_vec(),
281 content,
282 auth,
283 })
284 }
285 Command::CommInfo { target_name } => {
286 let header = Header::new("comm_info_request");
287 let header_bytes = header.to_bytes()?;
288 let content_json = match target_name {
289 Some(target_name) => json!({
290 "target_name": target_name,
291 }),
292 None => json!({}),
293 };
294 let content_str = serde_json::to_string(&content_json)?;
295 let content = content_str.into_bytes();
296
297 Ok(WireMessage {
298 header: header_bytes.to_vec(),
299 parent_header: b"{}".to_vec(),
300 metadata: b"{}".to_vec(),
301 content,
302 auth,
303 })
304 }
305 };
306
307 trace!("creating message {:?}", msg);
308 msg
309 }
310}
311
312/// Type of history requested.
313#[derive(Serialize, Debug)]
314pub enum HistoryAccessType {
315 /// Get the last `n` cells.
316 Tail {
317 /// Number of cells requested.
318 n: u64,
319 },
320 /// Get the range of cells associated with a session within a range.
321 Range {
322 /// Session to query for.
323 session: i64,
324 /// Start of the range
325 start: u64,
326 /// End of the range.
327 stop: u64,
328 },
329 /// Search for history items matching a pattern.
330 Search {
331 /// Pattern to search for.
332 pattern: String,
333 },
334}
335
336/// Level of detail requested when requesting code introspection
337#[derive(Debug)]
338pub enum DetailLevel {
339 /** Equivalent to IPython's `?` operator.
340
341 Typically fetches the documentation.
342 */
343 Zero,
344 /** Equivalent to IPython's `??` operator.
345
346 Typically fetches the source code.
347 */
348 One,
349}
350
351impl SerdeSerialize for DetailLevel {
352 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
353 where
354 S: Serializer,
355 {
356 match *self {
357 DetailLevel::Zero => serializer.serialize_i32(0),
358 DetailLevel::One => serializer.serialize_i32(1),
359 }
360 }
361}