Gracefully handle errors in the inspect protocol (#934)

This commit is contained in:
Jonatan Kłosko 2022-01-25 17:54:02 +01:00 committed by GitHub
parent 928cb5c592
commit 6b19f1d71b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 40 additions and 5 deletions

View file

@ -35,14 +35,13 @@ defmodule Livebook.Evaluator.DefaultFormatter do
defp to_output(value) do
# Kino is a "client side" extension for Livebook that may be
# installed into the runtime node. If it is installed we use
# its more precies output rendering rules.
# its more precise output rendering rules.
if Code.ensure_loaded?(Kino.Render) do
try do
Kino.Render.to_livebook(value)
catch
kind, error ->
{error, stacktrace} = Exception.blame(kind, error, __STACKTRACE__)
formatted = Exception.format(kind, error, stacktrace)
formatted = format_error(kind, error, __STACKTRACE__)
Logger.error(formatted)
to_inspect_output(value)
end
@ -52,8 +51,19 @@ defmodule Livebook.Evaluator.DefaultFormatter do
end
defp to_inspect_output(value, opts \\ []) do
inspected = inspect(value, inspect_opts(opts))
{:text, inspected}
try do
inspected = inspect(value, inspect_opts(opts))
{:text, inspected}
catch
kind, error ->
formatted = format_error(kind, error, __STACKTRACE__)
{:error, formatted, :other}
end
end
defp format_error(kind, error, stacktrace) do
{error, stacktrace} = Exception.blame(kind, error, stacktrace)
Exception.format(kind, error, stacktrace)
end
defp inspect_opts(opts) do

View file

@ -0,0 +1,16 @@
defmodule Livebook.Evaluator.DefaultFormatterTest do
use ExUnit.Case, async: true
alias Livebook.Evaluator.DefaultFormatter
test "inspects successful results" do
result = 10
assert {:text, "\e[34m10\e[0m"} = DefaultFormatter.format_response({:ok, result})
end
test "gracefully handles errors in the inspect protocol" do
result = %Livebook.TestModules.BadInspect{}
assert {:error, error, :other} = DefaultFormatter.format_response({:ok, result})
assert error =~ ":bad_return"
end
end

View file

@ -0,0 +1,9 @@
defmodule Livebook.TestModules.BadInspect do
defstruct []
defimpl Inspect do
def inspect(%Livebook.TestModules.BadInspect{}, _opts) do
:bad_return
end
end
end