diff options
author | Kyle Kelley <rgbkrk@gmail.com> | 2023-09-18 15:07:33 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-18 22:07:33 +0000 |
commit | 788bc8d021ab0ec2d58837b129c178300b2c2a39 (patch) | |
tree | 05a3b977dfec95644ede58aa9e52f92b528e2da3 /cli/tools/jupyter/server.rs | |
parent | 3de9af4d0bf5a411e4c43ce1ce474665585502b9 (diff) |
fix(cli): Enhanced errors for Jupyter (#20530)
Diffstat (limited to 'cli/tools/jupyter/server.rs')
-rw-r--r-- | cli/tools/jupyter/server.rs | 83 |
1 files changed, 71 insertions, 12 deletions
diff --git a/cli/tools/jupyter/server.rs b/cli/tools/jupyter/server.rs index f0e523e1e..f53f5209c 100644 --- a/cli/tools/jupyter/server.rs +++ b/cli/tools/jupyter/server.rs @@ -408,25 +408,84 @@ impl JupyterServer { tokio::time::sleep(std::time::Duration::from_millis(5)).await; } else { let exception_details = exception_details.unwrap(); - let name = if let Some(exception) = exception_details.exception { - if let Some(description) = exception.description { - description - } else if let Some(value) = exception.value { - value.to_string() + + // Determine the exception value and name + let (name, message, stack) = + if let Some(exception) = exception_details.exception { + let result = self + .repl_session + .call_function_on_args( + r#" + function(object) { + if (object instanceof Error) { + const name = "name" in object ? String(object.name) : ""; + const message = "message" in object ? String(object.message) : ""; + const stack = "stack" in object ? String(object.stack) : ""; + return JSON.stringify({ name, message, stack }); + } else { + const message = String(object); + return JSON.stringify({ name: "", message, stack: "" }); + } + } + "# + .into(), + &[exception], + ) + .await?; + + match result.result.value { + Some(serde_json::Value::String(str)) => { + if let Ok(object) = + serde_json::from_str::<HashMap<String, String>>(&str) + { + let get = |k| object.get(k).cloned().unwrap_or_default(); + (get("name"), get("message"), get("stack")) + } else { + eprintln!("Unexpected result while parsing JSON {str}"); + ("".into(), "".into(), "".into()) + } + } + _ => { + eprintln!("Unexpected result while parsing exception {result:?}"); + ("".into(), "".into(), "".into()) + } + } } else { - "undefined".to_string() - } + eprintln!("Unexpectedly missing exception {exception_details:?}"); + ("".into(), "".into(), "".into()) + }; + + let stack = if stack.is_empty() { + format!( + "{}\n at <unknown>", + serde_json::to_string(&message).unwrap() + ) + } else { + stack + }; + let traceback = format!("Stack trace:\n{stack}") + .split('\n') + .map(|s| s.to_owned()) + .collect::<Vec<_>>(); + + let ename = if name.is_empty() { + "Unknown error".into() + } else { + name + }; + + let evalue = if message.is_empty() { + "(none)".into() } else { - "Unknown exception".to_string() + message }; - // TODO(bartlomieju): fill all the fields msg .new_message("error") .with_content(json!({ - "ename": name, - "evalue": " ", // Fake value, otherwise old Jupyter frontends don't show the error - "traceback": [], + "ename": ename, + "evalue": evalue, + "traceback": traceback, })) .send(&mut *self.iopub_socket.lock().await) .await?; |