mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-10-11 22:16:10 +08:00
Add support for getting evaluation file during evaluation (#1362)
This commit is contained in:
parent
16fc23e62c
commit
1e324b4f75
6 changed files with 39 additions and 22 deletions
|
@ -35,7 +35,7 @@ export function initializeIframeSource(iframe, iframePort, iframeUrl) {
|
||||||
iframe.sandbox =
|
iframe.sandbox =
|
||||||
"allow-scripts allow-same-origin allow-downloads allow-modals allow-popups";
|
"allow-scripts allow-same-origin allow-downloads allow-modals allow-popups";
|
||||||
iframe.allow =
|
iframe.allow =
|
||||||
"accelerometer; ambient-light-sensor; camera; display-capture; encrypted-media; geolocation; gyroscope; microphone; midi; usb; xr-spatial-tracking";
|
"accelerometer; ambient-light-sensor; camera; display-capture; encrypted-media; geolocation; gyroscope; microphone; midi; usb; xr-spatial-tracking; clipboard-read; clipboard-write";
|
||||||
iframe.src = url;
|
iframe.src = url;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -308,8 +308,6 @@ defmodule Livebook.Runtime.Evaluator do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp handle_cast({:evaluate_code, code, ref, base_ref, opts}, state) do
|
defp handle_cast({:evaluate_code, code, ref, base_ref, opts}, state) do
|
||||||
Evaluator.IOProxy.configure(state.io_proxy, ref)
|
|
||||||
|
|
||||||
Evaluator.ObjectTracker.remove_reference(state.object_tracker, {self(), ref})
|
Evaluator.ObjectTracker.remove_reference(state.object_tracker, {self(), ref})
|
||||||
|
|
||||||
context = get_context(state, base_ref)
|
context = get_context(state, base_ref)
|
||||||
|
@ -317,6 +315,8 @@ defmodule Livebook.Runtime.Evaluator do
|
||||||
context = put_in(context.env.file, file)
|
context = put_in(context.env.file, file)
|
||||||
start_time = System.monotonic_time()
|
start_time = System.monotonic_time()
|
||||||
|
|
||||||
|
Evaluator.IOProxy.configure(state.io_proxy, ref, file)
|
||||||
|
|
||||||
{result_context, result, code_error} =
|
{result_context, result, code_error} =
|
||||||
case eval(code, context.binding, context.env) do
|
case eval(code, context.binding, context.env) do
|
||||||
{:ok, value, binding, env} ->
|
{:ok, value, binding, env} ->
|
||||||
|
|
|
@ -23,7 +23,9 @@ defmodule Livebook.Runtime.Evaluator.IOProxy do
|
||||||
@doc """
|
@doc """
|
||||||
Starts an IO device process.
|
Starts an IO device process.
|
||||||
|
|
||||||
Make sure to use `configure/3` to correctly proxy the requests.
|
For all supported requests a message is sent to the configured
|
||||||
|
`:send_to` process, so this device serves as a proxy. Make sure
|
||||||
|
to also call configure/3` before every evaluation.
|
||||||
"""
|
"""
|
||||||
@spec start_link(pid(), pid(), pid(), pid()) :: GenServer.on_start()
|
@spec start_link(pid(), pid(), pid(), pid()) :: GenServer.on_start()
|
||||||
def start_link(evaluator, send_to, runtime_broadcast_to, object_tracker) do
|
def start_link(evaluator, send_to, runtime_broadcast_to, object_tracker) do
|
||||||
|
@ -31,16 +33,13 @@ defmodule Livebook.Runtime.Evaluator.IOProxy do
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Sets IO proxy destination and the reference to be attached to all
|
Configures IO proxy for a new evaluation.
|
||||||
messages.
|
|
||||||
|
|
||||||
For all supported requests a message is sent to the configured
|
The given reference is attached to all the proxied messages.
|
||||||
`:send_to` process, so this device serves as a proxy. The given
|
|
||||||
evaluation reference is also included in all messages.
|
|
||||||
"""
|
"""
|
||||||
@spec configure(pid(), Evaluator.ref()) :: :ok
|
@spec configure(pid(), Evaluator.ref(), String.t()) :: :ok
|
||||||
def configure(pid, ref) do
|
def configure(pid, ref, file) do
|
||||||
GenServer.cast(pid, {:configure, ref})
|
GenServer.cast(pid, {:configure, ref, file})
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
@ -75,6 +74,7 @@ defmodule Livebook.Runtime.Evaluator.IOProxy do
|
||||||
%{
|
%{
|
||||||
encoding: :unicode,
|
encoding: :unicode,
|
||||||
ref: nil,
|
ref: nil,
|
||||||
|
file: nil,
|
||||||
buffer: [],
|
buffer: [],
|
||||||
input_cache: %{},
|
input_cache: %{},
|
||||||
token_count: 0,
|
token_count: 0,
|
||||||
|
@ -86,8 +86,8 @@ defmodule Livebook.Runtime.Evaluator.IOProxy do
|
||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def handle_cast({:configure, ref}, state) do
|
def handle_cast({:configure, ref, file}, state) do
|
||||||
{:noreply, %{state | ref: ref, token_count: 0}}
|
{:noreply, %{state | ref: ref, file: file, token_count: 0}}
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_cast(:clear_input_cache, state) do
|
def handle_cast(:clear_input_cache, state) do
|
||||||
|
@ -230,6 +230,10 @@ defmodule Livebook.Runtime.Evaluator.IOProxy do
|
||||||
{{:ok, state.runtime_broadcast_to}, state}
|
{{:ok, state.runtime_broadcast_to}, state}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp io_request(:livebook_get_evaluation_file, state) do
|
||||||
|
{state.file, state}
|
||||||
|
end
|
||||||
|
|
||||||
defp io_request(_, state) do
|
defp io_request(_, state) do
|
||||||
{{:error, :request}, state}
|
{{:error, :request}, state}
|
||||||
end
|
end
|
||||||
|
|
|
@ -1485,7 +1485,7 @@ defmodule Livebook.Session do
|
||||||
file -> file.path
|
file -> file.path
|
||||||
end
|
end
|
||||||
|
|
||||||
file = path <> "#cell"
|
file = path <> "#cell:#{cell.id}"
|
||||||
|
|
||||||
smart_cell_ref =
|
smart_cell_ref =
|
||||||
case cell do
|
case cell do
|
||||||
|
|
|
@ -34,6 +34,8 @@ defmodule LivebookWeb.Output do
|
||||||
defp border?({:stdout, _text}), do: true
|
defp border?({:stdout, _text}), do: true
|
||||||
defp border?({:text, _text}), do: true
|
defp border?({:text, _text}), do: true
|
||||||
defp border?({:error, _message}), do: true
|
defp border?({:error, _message}), do: true
|
||||||
|
# TODO fix spacing and make it an option
|
||||||
|
defp border?({:grid, _, _}), do: true
|
||||||
defp border?(_output), do: false
|
defp border?(_output), do: false
|
||||||
|
|
||||||
defp wrapper?({:frame, _outputs, _info}), do: true
|
defp wrapper?({:frame, _outputs, _info}), do: true
|
||||||
|
|
|
@ -11,7 +11,7 @@ defmodule Livebook.Runtime.Evaluator.IOProxyTest do
|
||||||
start_supervised({Evaluator, [send_to: self(), object_tracker: object_tracker]})
|
start_supervised({Evaluator, [send_to: self(), object_tracker: object_tracker]})
|
||||||
|
|
||||||
io = Process.info(evaluator.pid)[:group_leader]
|
io = Process.info(evaluator.pid)[:group_leader]
|
||||||
IOProxy.configure(io, :ref)
|
IOProxy.configure(io, :ref, "cell")
|
||||||
%{io: io}
|
%{io: io}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ defmodule Livebook.Runtime.Evaluator.IOProxyTest do
|
||||||
test "clear_input_cache/1 clears all cached input information", %{io: io} do
|
test "clear_input_cache/1 clears all cached input information", %{io: io} do
|
||||||
pid =
|
pid =
|
||||||
spawn_link(fn ->
|
spawn_link(fn ->
|
||||||
IOProxy.configure(io, :ref)
|
IOProxy.configure(io, :ref, "cell")
|
||||||
assert livebook_get_input_value(io, "input1") == {:ok, :value1}
|
assert livebook_get_input_value(io, "input1") == {:ok, :value1}
|
||||||
IOProxy.clear_input_cache(io)
|
IOProxy.clear_input_cache(io)
|
||||||
assert livebook_get_input_value(io, "input1") == {:ok, :value2}
|
assert livebook_get_input_value(io, "input1") == {:ok, :value2}
|
||||||
|
@ -106,25 +106,25 @@ defmodule Livebook.Runtime.Evaluator.IOProxyTest do
|
||||||
|
|
||||||
describe "token requests" do
|
describe "token requests" do
|
||||||
test "returns different tokens for subsequent calls", %{io: io} do
|
test "returns different tokens for subsequent calls", %{io: io} do
|
||||||
IOProxy.configure(io, :ref1)
|
IOProxy.configure(io, :ref1, "cell1")
|
||||||
token1 = livebook_generate_token(io)
|
token1 = livebook_generate_token(io)
|
||||||
token2 = livebook_generate_token(io)
|
token2 = livebook_generate_token(io)
|
||||||
assert token1 != token2
|
assert token1 != token2
|
||||||
end
|
end
|
||||||
|
|
||||||
test "returns different tokens for different refs", %{io: io} do
|
test "returns different tokens for different refs", %{io: io} do
|
||||||
IOProxy.configure(io, :ref1)
|
IOProxy.configure(io, :ref1, "cell1")
|
||||||
token1 = livebook_generate_token(io)
|
token1 = livebook_generate_token(io)
|
||||||
IOProxy.configure(io, :ref2)
|
IOProxy.configure(io, :ref2, "cell2")
|
||||||
token2 = livebook_generate_token(io)
|
token2 = livebook_generate_token(io)
|
||||||
assert token1 != token2
|
assert token1 != token2
|
||||||
end
|
end
|
||||||
|
|
||||||
test "returns same tokens for the same ref", %{io: io} do
|
test "returns same tokens for the same ref", %{io: io} do
|
||||||
IOProxy.configure(io, :ref)
|
IOProxy.configure(io, :ref, "cell")
|
||||||
token1 = livebook_generate_token(io)
|
token1 = livebook_generate_token(io)
|
||||||
token2 = livebook_generate_token(io)
|
token2 = livebook_generate_token(io)
|
||||||
IOProxy.configure(io, :ref)
|
IOProxy.configure(io, :ref, "cell")
|
||||||
token3 = livebook_generate_token(io)
|
token3 = livebook_generate_token(io)
|
||||||
token4 = livebook_generate_token(io)
|
token4 = livebook_generate_token(io)
|
||||||
assert token1 == token3
|
assert token1 == token3
|
||||||
|
@ -132,6 +132,13 @@ defmodule Livebook.Runtime.Evaluator.IOProxyTest do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "evaluation file requests" do
|
||||||
|
test "returns the configured file", %{io: io} do
|
||||||
|
IOProxy.configure(io, :ref1, "cell1")
|
||||||
|
assert livebook_get_evaluation_file(io) == "cell1"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Helpers
|
# Helpers
|
||||||
|
|
||||||
defp reply_to_input_request(_ref, _input_id, _reply, 0), do: :ok
|
defp reply_to_input_request(_ref, _input_id, _reply, 0), do: :ok
|
||||||
|
@ -156,6 +163,10 @@ defmodule Livebook.Runtime.Evaluator.IOProxyTest do
|
||||||
io_request(io, :livebook_generate_token)
|
io_request(io, :livebook_generate_token)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp livebook_get_evaluation_file(io) do
|
||||||
|
io_request(io, :livebook_get_evaluation_file)
|
||||||
|
end
|
||||||
|
|
||||||
defp io_request(io, request) do
|
defp io_request(io, request) do
|
||||||
ref = make_ref()
|
ref = make_ref()
|
||||||
send(io, {:io_request, self(), ref, request})
|
send(io, {:io_request, self(), ref, request})
|
||||||
|
|
Loading…
Add table
Reference in a new issue