mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-10-08 20:46:16 +08:00
Set proper file in env when the notebook is persisted (#95)
* Set proper file in env when the notebook is persisted * Fix typo
This commit is contained in:
parent
e2cd992b78
commit
5e20541774
10 changed files with 104 additions and 23 deletions
|
@ -64,10 +64,16 @@ defmodule Livebook.Evaluator do
|
||||||
|
|
||||||
Evaluation response is sent to the process identified by `send_to` as `{:evaluation_response, ref, response}`.
|
Evaluation response is sent to the process identified by `send_to` as `{:evaluation_response, ref, response}`.
|
||||||
Note that response is transformed with the configured formatter (identity by default).
|
Note that response is transformed with the configured formatter (identity by default).
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
* `:file` - file to which the evaluated code belongs. Most importantly,
|
||||||
|
this has an impact on the value of `__DIR__`.
|
||||||
"""
|
"""
|
||||||
@spec evaluate_code(t(), pid(), String.t(), ref(), ref()) :: :ok
|
@spec evaluate_code(t(), pid(), String.t(), ref(), ref(), keyword()) :: :ok
|
||||||
def evaluate_code(evaluator, send_to, code, ref, prev_ref \\ :initial) when ref != :initial do
|
def evaluate_code(evaluator, send_to, code, ref, prev_ref \\ :initial, opts \\ [])
|
||||||
GenServer.cast(evaluator, {:evaluate_code, send_to, code, ref, prev_ref})
|
when ref != :initial do
|
||||||
|
GenServer.cast(evaluator, {:evaluate_code, send_to, code, ref, prev_ref, opts})
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
@ -107,11 +113,14 @@ defmodule Livebook.Evaluator do
|
||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def handle_cast({:evaluate_code, send_to, code, ref, prev_ref}, state) do
|
def handle_cast({:evaluate_code, send_to, code, ref, prev_ref, opts}, state) do
|
||||||
Evaluator.IOProxy.configure(state.io_proxy, send_to, ref)
|
Evaluator.IOProxy.configure(state.io_proxy, send_to, ref)
|
||||||
|
|
||||||
context = Map.get(state.contexts, prev_ref, state.contexts.initial)
|
context = Map.get(state.contexts, prev_ref, state.contexts.initial)
|
||||||
|
|
||||||
|
file = Keyword.get(opts, :file, "nofile")
|
||||||
|
context = put_in(context.env.file, file)
|
||||||
|
|
||||||
case eval(code, context.binding, context.env) do
|
case eval(code, context.binding, context.env) do
|
||||||
{:ok, result, binding, env} ->
|
{:ok, result, binding, env} ->
|
||||||
result_context = %{binding: binding, env: env}
|
result_context = %{binding: binding, env: env}
|
||||||
|
|
|
@ -41,9 +41,21 @@ defprotocol Livebook.Runtime do
|
||||||
|
|
||||||
* `{:evaluation_stdout, ref, string}` - output captured during evaluation
|
* `{:evaluation_stdout, ref, string}` - output captured during evaluation
|
||||||
* `{:evaluation_response, ref, response}` - final result of the evaluation
|
* `{:evaluation_response, ref, response}` - final result of the evaluation
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
* `:file` - file to which the evaluated code belongs. Most importantly,
|
||||||
|
this has an impact on the value of `__DIR__`.
|
||||||
"""
|
"""
|
||||||
@spec evaluate_code(t(), String.t(), ref(), ref(), ref()) :: :ok
|
@spec evaluate_code(t(), String.t(), ref(), ref(), ref(), keyword()) :: :ok
|
||||||
def evaluate_code(runtime, code, container_ref, evaluation_ref, prev_evaluation_ref \\ :initial)
|
def evaluate_code(
|
||||||
|
runtime,
|
||||||
|
code,
|
||||||
|
container_ref,
|
||||||
|
evaluation_ref,
|
||||||
|
prev_evaluation_ref \\ :initial,
|
||||||
|
opts \\ []
|
||||||
|
)
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Disposes of evaluation identified by the given ref.
|
Disposes of evaluation identified by the given ref.
|
||||||
|
|
|
@ -49,13 +49,21 @@ defimpl Livebook.Runtime, for: Livebook.Runtime.Attached do
|
||||||
ErlDist.Manager.stop(runtime.node)
|
ErlDist.Manager.stop(runtime.node)
|
||||||
end
|
end
|
||||||
|
|
||||||
def evaluate_code(runtime, code, container_ref, evaluation_ref, prev_evaluation_ref \\ :initial) do
|
def evaluate_code(
|
||||||
|
runtime,
|
||||||
|
code,
|
||||||
|
container_ref,
|
||||||
|
evaluation_ref,
|
||||||
|
prev_evaluation_ref \\ :initial,
|
||||||
|
opts \\ []
|
||||||
|
) do
|
||||||
ErlDist.Manager.evaluate_code(
|
ErlDist.Manager.evaluate_code(
|
||||||
runtime.node,
|
runtime.node,
|
||||||
code,
|
code,
|
||||||
container_ref,
|
container_ref,
|
||||||
evaluation_ref,
|
evaluation_ref,
|
||||||
prev_evaluation_ref
|
prev_evaluation_ref,
|
||||||
|
opts
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -73,13 +73,21 @@ defimpl Livebook.Runtime, for: Livebook.Runtime.ElixirStandalone do
|
||||||
ErlDist.Manager.stop(runtime.node)
|
ErlDist.Manager.stop(runtime.node)
|
||||||
end
|
end
|
||||||
|
|
||||||
def evaluate_code(runtime, code, container_ref, evaluation_ref, prev_evaluation_ref \\ :initial) do
|
def evaluate_code(
|
||||||
|
runtime,
|
||||||
|
code,
|
||||||
|
container_ref,
|
||||||
|
evaluation_ref,
|
||||||
|
prev_evaluation_ref \\ :initial,
|
||||||
|
opts \\ []
|
||||||
|
) do
|
||||||
ErlDist.Manager.evaluate_code(
|
ErlDist.Manager.evaluate_code(
|
||||||
runtime.node,
|
runtime.node,
|
||||||
code,
|
code,
|
||||||
container_ref,
|
container_ref,
|
||||||
evaluation_ref,
|
evaluation_ref,
|
||||||
prev_evaluation_ref
|
prev_evaluation_ref,
|
||||||
|
opts
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -49,12 +49,25 @@ defmodule Livebook.Runtime.ErlDist.Manager do
|
||||||
|
|
||||||
See `Evaluator` for more details.
|
See `Evaluator` for more details.
|
||||||
"""
|
"""
|
||||||
@spec evaluate_code(node(), String.t(), Evaluator.ref(), Evaluator.ref(), Evaluator.ref()) ::
|
@spec evaluate_code(
|
||||||
:ok
|
node(),
|
||||||
def evaluate_code(node, code, container_ref, evaluation_ref, prev_evaluation_ref \\ :initial) do
|
String.t(),
|
||||||
|
Evaluator.ref(),
|
||||||
|
Evaluator.ref(),
|
||||||
|
Evaluator.ref(),
|
||||||
|
keyword()
|
||||||
|
) :: :ok
|
||||||
|
def evaluate_code(
|
||||||
|
node,
|
||||||
|
code,
|
||||||
|
container_ref,
|
||||||
|
evaluation_ref,
|
||||||
|
prev_evaluation_ref \\ :initial,
|
||||||
|
opts \\ []
|
||||||
|
) do
|
||||||
GenServer.cast(
|
GenServer.cast(
|
||||||
{@name, node},
|
{@name, node},
|
||||||
{:evaluate_code, code, container_ref, evaluation_ref, prev_evaluation_ref}
|
{:evaluate_code, code, container_ref, evaluation_ref, prev_evaluation_ref, opts}
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -153,7 +166,7 @@ defmodule Livebook.Runtime.ErlDist.Manager do
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_cast(
|
def handle_cast(
|
||||||
{:evaluate_code, code, container_ref, evaluation_ref, prev_evaluation_ref},
|
{:evaluate_code, code, container_ref, evaluation_ref, prev_evaluation_ref, opts},
|
||||||
state
|
state
|
||||||
) do
|
) do
|
||||||
state = ensure_evaluator(state, container_ref)
|
state = ensure_evaluator(state, container_ref)
|
||||||
|
@ -163,7 +176,8 @@ defmodule Livebook.Runtime.ErlDist.Manager do
|
||||||
state.owner,
|
state.owner,
|
||||||
code,
|
code,
|
||||||
evaluation_ref,
|
evaluation_ref,
|
||||||
prev_evaluation_ref
|
prev_evaluation_ref,
|
||||||
|
opts
|
||||||
)
|
)
|
||||||
|
|
||||||
{:noreply, state}
|
{:noreply, state}
|
||||||
|
|
|
@ -109,13 +109,21 @@ defimpl Livebook.Runtime, for: Livebook.Runtime.MixStandalone do
|
||||||
ErlDist.Manager.stop(runtime.node)
|
ErlDist.Manager.stop(runtime.node)
|
||||||
end
|
end
|
||||||
|
|
||||||
def evaluate_code(runtime, code, container_ref, evaluation_ref, prev_evaluation_ref \\ :initial) do
|
def evaluate_code(
|
||||||
|
runtime,
|
||||||
|
code,
|
||||||
|
container_ref,
|
||||||
|
evaluation_ref,
|
||||||
|
prev_evaluation_ref \\ :initial,
|
||||||
|
opts \\ []
|
||||||
|
) do
|
||||||
ErlDist.Manager.evaluate_code(
|
ErlDist.Manager.evaluate_code(
|
||||||
runtime.node,
|
runtime.node,
|
||||||
code,
|
code,
|
||||||
container_ref,
|
container_ref,
|
||||||
evaluation_ref,
|
evaluation_ref,
|
||||||
prev_evaluation_ref
|
prev_evaluation_ref,
|
||||||
|
opts
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -546,7 +546,10 @@ defmodule Livebook.Session do
|
||||||
[] -> :initial
|
[] -> :initial
|
||||||
end
|
end
|
||||||
|
|
||||||
Runtime.evaluate_code(state.data.runtime, cell.source, :main, cell.id, prev_ref)
|
file = (state.data.path || "") <> "#cell"
|
||||||
|
opts = [file: file]
|
||||||
|
|
||||||
|
Runtime.evaluate_code(state.data.runtime, cell.source, :main, cell.id, prev_ref, opts)
|
||||||
|
|
||||||
state
|
state
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,7 +8,7 @@ defmodule Livebook.EvaluatorTest do
|
||||||
%{evaluator: evaluator}
|
%{evaluator: evaluator}
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "evaluate_code/4" do
|
describe "evaluate_code/6" do
|
||||||
test "given a valid code returns evaluation result", %{evaluator: evaluator} do
|
test "given a valid code returns evaluation result", %{evaluator: evaluator} do
|
||||||
code = """
|
code = """
|
||||||
x = 1
|
x = 1
|
||||||
|
@ -107,6 +107,17 @@ defmodule Livebook.EvaluatorTest do
|
||||||
1000
|
1000
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "given file option sets it in evaluation environment", %{evaluator: evaluator} do
|
||||||
|
code = """
|
||||||
|
__DIR__
|
||||||
|
"""
|
||||||
|
|
||||||
|
opts = [file: "/path/dir/file"]
|
||||||
|
Evaluator.evaluate_code(evaluator, self(), code, :code_1, :initial, opts)
|
||||||
|
|
||||||
|
assert_receive {:evaluation_response, :code_1, {:ok, "/path/dir"}}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "forget_evaluation/2" do
|
describe "forget_evaluation/2" do
|
||||||
|
|
|
@ -28,7 +28,7 @@ defmodule Livebook.Runtime.ErlDist.ManagerTest do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "evaluate_code/2" do
|
describe "evaluate_code/6" do
|
||||||
test "spawns a new evaluator when necessary" do
|
test "spawns a new evaluator when necessary" do
|
||||||
Manager.start()
|
Manager.start()
|
||||||
Manager.set_owner(node(), self())
|
Manager.set_owner(node(), self())
|
||||||
|
|
|
@ -30,9 +30,17 @@ defimpl Livebook.Runtime, for: LivebookTest.Runtime.SingleEvaluator do
|
||||||
code,
|
code,
|
||||||
_container_ref,
|
_container_ref,
|
||||||
evaluation_ref,
|
evaluation_ref,
|
||||||
prev_evaluation_ref \\ :initial
|
prev_evaluation_ref \\ :initial,
|
||||||
|
opts \\ []
|
||||||
) do
|
) do
|
||||||
Evaluator.evaluate_code(runtime.evaluator, self(), code, evaluation_ref, prev_evaluation_ref)
|
Evaluator.evaluate_code(
|
||||||
|
runtime.evaluator,
|
||||||
|
self(),
|
||||||
|
code,
|
||||||
|
evaluation_ref,
|
||||||
|
prev_evaluation_ref,
|
||||||
|
opts
|
||||||
|
)
|
||||||
|
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Reference in a new issue