From b7efe29e36633654fdae819c7e795c2a10643064 Mon Sep 17 00:00:00 2001 From: ikappaki Date: Sat, 15 Jun 2024 12:14:54 +0100 Subject: [PATCH] Improved Exception formatting --- CHANGELOG.md | 1 + basilisp_kernel/kernel.py | 13 ++++++++++++- pyproject.toml | 2 +- test_basilisp.py | 13 +++++++++++++ 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f31b9bd..c58d994 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased - Optimized output to stdout/stderr by removing proxy string intermediary. +- Improved Exception formatting (requires basilisp>=0.1.0b2). ## 1.0.0 diff --git a/basilisp_kernel/kernel.py b/basilisp_kernel/kernel.py index 45a5e85..1cc406d 100644 --- a/basilisp_kernel/kernel.py +++ b/basilisp_kernel/kernel.py @@ -6,6 +6,7 @@ from basilisp.lang import reader as reader from basilisp.lang import runtime as runtime from basilisp.lang import symbol as sym +from basilisp.lang.exception import format_exception import re from typing import Any, Callable, Optional, Sequence, Type @@ -27,7 +28,17 @@ def do_execute(code): runtime.Var.find_safe(sym.symbol("*out*", ns=runtime.CORE_NS)) : sys.stdout, runtime.Var.find_safe(sym.symbol("*err*", ns=runtime.CORE_NS)) : sys.stderr }): - return cli.eval_str(code, ctx, user_ns, eof) + try: + return cli.eval_str(code, ctx, user_ns, eof) + except reader.SyntaxError as e: + msg = "".join(format_exception(e, reader.SyntaxError, e.__traceback__)) + raise reader.SyntaxError(msg) from None + except compiler.CompilerException as e: + msg = "".join(format_exception(e, compiler.CompilerException, e.__traceback__)) + raise compiler.CompilerException(msg, phase=e.phase, filename=e.filename) from None + except Exception as e: + msg = "".join(format_exception(e, Exception, e.__traceback__)) + raise Exception(msg) from None class BasilispKernel(IPythonKernel): diff --git a/pyproject.toml b/pyproject.toml index 181f7d9..29281b3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,7 +23,7 @@ requires-python = ">=3.8" dependencies = [ "ipykernel", "jupyter_client", - "basilisp" + "basilisp>=0.1.0b2" ] [project.optional-dependencies] diff --git a/test_basilisp.py b/test_basilisp.py index 79818b3..6520ccd 100644 --- a/test_basilisp.py +++ b/test_basilisp.py @@ -63,6 +63,19 @@ class BasilispKernelTests(jkt.KernelTests): {"code": "(map #(* % %) (range 1 4))", "result": "(1 4 9)"}, ] + def test_basilisp_kernel_exceptions(self): + reply, output_msgs = self.execute_helper(code='#lmn') + self.assertEqual("SyntaxError", output_msgs[0]['content']['ename']) + self.assertIn("message: No data reader found for tag #lmn", output_msgs[0]['content']['evalue']) + + reply, output_msgs = self.execute_helper(code='(xyz)') + self.assertEqual("CompilerException", output_msgs[0]['content']['ename']) + self.assertIn("message: unable to resolve symbol 'xyz' in this context", output_msgs[0]['content']['evalue']) + + reply, output_msgs = self.execute_helper(code='(/ 2 0)') + self.assertEqual("Exception", output_msgs[0]['content']['ename']) + self.assertIn("Traceback (most recent call last):", output_msgs[0]['content']['evalue']) + # code which generates some sort of rich output # for each `code` input a single rich display object with the specified # `mime` type should be sent to the frontend