mirror of
https://github.com/denoland/deno.git
synced 2024-12-24 08:09:08 -05:00
fix(cli): Enhanced errors for Jupyter (#20530)
This commit is contained in:
parent
3de9af4d0b
commit
788bc8d021
2 changed files with 197 additions and 53 deletions
167
cli/tests/testdata/jupyter/integration_test.ipynb
vendored
167
cli/tests/testdata/jupyter/integration_test.ipynb
vendored
|
@ -44,7 +44,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"execution_count": 21,
|
||||
"id": "a5d38758",
|
||||
"metadata": {
|
||||
"hidden": true
|
||||
|
@ -52,7 +52,7 @@
|
|||
"outputs": [
|
||||
{
|
||||
"data": {},
|
||||
"execution_count": 1,
|
||||
"execution_count": 21,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
},
|
||||
|
@ -81,7 +81,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"execution_count": 22,
|
||||
"id": "f7fa885a",
|
||||
"metadata": {
|
||||
"hidden": true
|
||||
|
@ -89,7 +89,7 @@
|
|||
"outputs": [
|
||||
{
|
||||
"data": {},
|
||||
"execution_count": 2,
|
||||
"execution_count": 22,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
},
|
||||
|
@ -120,7 +120,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"execution_count": 23,
|
||||
"id": "08a17340",
|
||||
"metadata": {
|
||||
"hidden": true
|
||||
|
@ -132,7 +132,7 @@
|
|||
"{ color: \u001b[32m\"red\"\u001b[39m, area: \u001b[33m10000\u001b[39m }"
|
||||
]
|
||||
},
|
||||
"execution_count": 3,
|
||||
"execution_count": 23,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -177,7 +177,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"execution_count": 24,
|
||||
"id": "bbf2c09b",
|
||||
"metadata": {
|
||||
"hidden": true
|
||||
|
@ -185,7 +185,7 @@
|
|||
"outputs": [
|
||||
{
|
||||
"data": {},
|
||||
"execution_count": 4,
|
||||
"execution_count": 24,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -207,7 +207,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"execution_count": 25,
|
||||
"id": "d9801d80",
|
||||
"metadata": {
|
||||
"hidden": true
|
||||
|
@ -219,7 +219,7 @@
|
|||
"\u001b[1mnull\u001b[22m"
|
||||
]
|
||||
},
|
||||
"execution_count": 5,
|
||||
"execution_count": 25,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -241,7 +241,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"execution_count": 26,
|
||||
"id": "cfaac330",
|
||||
"metadata": {
|
||||
"hidden": true
|
||||
|
@ -253,7 +253,7 @@
|
|||
"\u001b[33mtrue\u001b[39m"
|
||||
]
|
||||
},
|
||||
"execution_count": 6,
|
||||
"execution_count": 26,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -275,7 +275,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"execution_count": 27,
|
||||
"id": "ec3be2da",
|
||||
"metadata": {
|
||||
"hidden": true
|
||||
|
@ -287,7 +287,7 @@
|
|||
"\u001b[33m42\u001b[39m"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"execution_count": 27,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -309,7 +309,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"execution_count": 28,
|
||||
"id": "997cf2d7",
|
||||
"metadata": {
|
||||
"hidden": true
|
||||
|
@ -321,7 +321,7 @@
|
|||
"\u001b[32m\"this is a test of the emergency broadcast system\"\u001b[39m"
|
||||
]
|
||||
},
|
||||
"execution_count": 8,
|
||||
"execution_count": 28,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -343,7 +343,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"execution_count": 29,
|
||||
"id": "44b63807",
|
||||
"metadata": {
|
||||
"hidden": true
|
||||
|
@ -355,7 +355,7 @@
|
|||
"\u001b[33m31337n\u001b[39m"
|
||||
]
|
||||
},
|
||||
"execution_count": 9,
|
||||
"execution_count": 29,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -377,7 +377,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"execution_count": 30,
|
||||
"id": "e10c0d31",
|
||||
"metadata": {
|
||||
"hidden": true
|
||||
|
@ -389,7 +389,7 @@
|
|||
"\u001b[32mSymbol(foo)\u001b[39m"
|
||||
]
|
||||
},
|
||||
"execution_count": 10,
|
||||
"execution_count": 30,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -411,7 +411,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"execution_count": 31,
|
||||
"id": "81c99233",
|
||||
"metadata": {
|
||||
"hidden": true
|
||||
|
@ -423,7 +423,7 @@
|
|||
"{ foo: \u001b[32m\"bar\"\u001b[39m }"
|
||||
]
|
||||
},
|
||||
"execution_count": 11,
|
||||
"execution_count": 31,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -445,7 +445,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"execution_count": 32,
|
||||
"id": "43c1581b",
|
||||
"metadata": {
|
||||
"hidden": true
|
||||
|
@ -457,7 +457,7 @@
|
|||
"Promise { \u001b[32m\"it worked!\"\u001b[39m }"
|
||||
]
|
||||
},
|
||||
"execution_count": 13,
|
||||
"execution_count": 32,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -468,7 +468,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"execution_count": 33,
|
||||
"id": "9a34b725",
|
||||
"metadata": {
|
||||
"hidden": true
|
||||
|
@ -483,7 +483,7 @@
|
|||
"}"
|
||||
]
|
||||
},
|
||||
"execution_count": 14,
|
||||
"execution_count": 33,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -494,17 +494,22 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"execution_count": 34,
|
||||
"id": "b5c7b819",
|
||||
"metadata": {
|
||||
"scrolled": true
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"ename": "Error: this is a test\n at foo (<anonymous>:3:9)\n at <anonymous>:4:3",
|
||||
"evalue": "",
|
||||
"ename": "Error",
|
||||
"evalue": "this is a test",
|
||||
"output_type": "error",
|
||||
"traceback": []
|
||||
"traceback": [
|
||||
"Stack trace:",
|
||||
"Error: this is a test",
|
||||
" at foo (<anonymous>:3:9)",
|
||||
" at <anonymous>:4:3"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
|
@ -515,7 +520,28 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"execution_count": 35,
|
||||
"id": "14844fc9-536e-4121-a9bd-fc2d3f7b6395",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"ename": "Unknown error",
|
||||
"evalue": "a party",
|
||||
"output_type": "error",
|
||||
"traceback": [
|
||||
"Stack trace:",
|
||||
"\"a party\"",
|
||||
" at <unknown>"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"throw \"a party\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 36,
|
||||
"id": "72d01fdd",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
|
@ -523,13 +549,13 @@
|
|||
"data": {
|
||||
"text/plain": [
|
||||
"Promise {\n",
|
||||
" \u001b[36m<rejected>\u001b[39m TypeError: Expected string at position 0\n",
|
||||
" \u001b[36m<rejected>\u001b[39m TypeError: Expected string at position 1\n",
|
||||
" at Object.readFile (ext:deno_fs/30_fs.js:716:29)\n",
|
||||
" at <anonymous>:2:6\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
"execution_count": 16,
|
||||
"execution_count": 36,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
@ -540,40 +566,99 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 37,
|
||||
"id": "28cf59d0-6908-4edc-bb10-c325beeee362",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"data": {},
|
||||
"execution_count": 37,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Hello from Deno!\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"console.log(\"Hello from Deno!\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 38,
|
||||
"id": "8d5485c3-0da3-43fe-8ef5-a61e672f5e81",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"data": {},
|
||||
"execution_count": 38,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"\u001b[48;2;21;128;61m\u001b[37m Hello Deno \u001b[0m\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"console.log(\"%c Hello Deno \", \"background-color: #15803d; color: white;\");"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 39,
|
||||
"id": "1401d9d5-6994-4c7b-b55a-db3c16a1e2dc",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"\u001b[32m\"Cool 🫡\"\u001b[39m"
|
||||
]
|
||||
},
|
||||
"execution_count": 39,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"\"Cool 🫡\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 40,
|
||||
"id": "7afdaa0a-a2a0-4f52-8c7d-b6c5f237aa0d",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"data": {},
|
||||
"execution_count": 40,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"┌───────┬────────┐\n",
|
||||
"│ (idx) │ Values │\n",
|
||||
"├───────┼────────┤\n",
|
||||
"│ 0 │ 1 │\n",
|
||||
"│ 1 │ 2 │\n",
|
||||
"│ 2 │ 3 │\n",
|
||||
"└───────┴────────┘\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"console.table([1, 2, 3])"
|
||||
]
|
||||
|
|
|
@ -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 {
|
||||
"Unknown exception".to_string()
|
||||
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 {
|
||||
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?;
|
||||
|
|
Loading…
Reference in a new issue