mirror of
https://github.com/livebook-dev/livebook.git
synced 2024-09-20 10:05:57 +08:00
Rename project (#68)
* Rename references * Update file and directory names * Fix homepage tests
This commit is contained in:
parent
33409e7564
commit
dae6d5c9c3
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -20,7 +20,7 @@ erl_crash.dump
|
||||||
*.ez
|
*.ez
|
||||||
|
|
||||||
# Ignore package tarball (built via "mix hex.build").
|
# Ignore package tarball (built via "mix hex.build").
|
||||||
live_book-*.tar
|
livebook-*.tar
|
||||||
|
|
||||||
# If NPM crashes, it generates a log, let's ignore it too.
|
# If NPM crashes, it generates a log, let's ignore it too.
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# LiveBook
|
# Livebook
|
||||||
|
|
||||||
To start your Phoenix server:
|
To start your Phoenix server:
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* Delta is a format used to represent a set of changes introduced to a text document.
|
* Delta is a format used to represent a set of changes introduced to a text document.
|
||||||
*
|
*
|
||||||
* See `LiveBook.Delta` for more details.
|
* See `Livebook.Delta` for more details.
|
||||||
*
|
*
|
||||||
* Also see https://github.com/quilljs/delta
|
* Also see https://github.com/quilljs/delta
|
||||||
* for a complete implementation of the Delta specification.
|
* for a complete implementation of the Delta specification.
|
||||||
|
@ -47,7 +47,7 @@ export default class Delta {
|
||||||
/**
|
/**
|
||||||
* Appends the given operation.
|
* Appends the given operation.
|
||||||
*
|
*
|
||||||
* See `LiveBook.Delta.append/2` for more details.
|
* See `Livebook.Delta.append/2` for more details.
|
||||||
*/
|
*/
|
||||||
append(op) {
|
append(op) {
|
||||||
if (this.ops.length === 0) {
|
if (this.ops.length === 0) {
|
||||||
|
@ -122,7 +122,7 @@ export default class Delta {
|
||||||
* The method takes a `priority` argument indicates which delta
|
* The method takes a `priority` argument indicates which delta
|
||||||
* is considered to have happened first and is used for conflict resolution.
|
* is considered to have happened first and is used for conflict resolution.
|
||||||
*
|
*
|
||||||
* See `LiveBook.Delta.Transformation` for more details.
|
* See `Livebook.Delta.Transformation` for more details.
|
||||||
*/
|
*/
|
||||||
transform(other, priority) {
|
transform(other, priority) {
|
||||||
if (priority !== "left" && priority !== "right") {
|
if (priority !== "left" && priority !== "right") {
|
||||||
|
|
|
@ -8,10 +8,10 @@
|
||||||
import Config
|
import Config
|
||||||
|
|
||||||
# Configures the endpoint
|
# Configures the endpoint
|
||||||
config :live_book, LiveBookWeb.Endpoint,
|
config :livebook, LivebookWeb.Endpoint,
|
||||||
url: [host: "localhost"],
|
url: [host: "localhost"],
|
||||||
secret_key_base: "9hHHeOiAA8wrivUfuS//jQMurHxoMYUtF788BQMx2KO7mYUE8rVrGGG09djBNQq7",
|
secret_key_base: "9hHHeOiAA8wrivUfuS//jQMurHxoMYUtF788BQMx2KO7mYUE8rVrGGG09djBNQq7",
|
||||||
pubsub_server: LiveBook.PubSub,
|
pubsub_server: Livebook.PubSub,
|
||||||
live_view: [signing_salt: "mAPgPEM4"],
|
live_view: [signing_salt: "mAPgPEM4"],
|
||||||
# We are always in debug mode since we are executing code anyway
|
# We are always in debug mode since we are executing code anyway
|
||||||
debug_errors: true
|
debug_errors: true
|
||||||
|
@ -25,9 +25,9 @@ config :logger, :console,
|
||||||
config :phoenix, :json_library, Jason
|
config :phoenix, :json_library, Jason
|
||||||
|
|
||||||
# Configure the type of names used for distribution
|
# Configure the type of names used for distribution
|
||||||
# and the name of the main LiveBook node.
|
# and the name of the main Livebook node.
|
||||||
config :live_book, :node_name, {:shortnames, :live_book}
|
config :livebook, :node_name, {:shortnames, :livebook}
|
||||||
# config :live_book, :node_name, {:longnames, :"livebook@127.0.0.1"}
|
# config :livebook, :node_name, {:longnames, :"livebook@127.0.0.1"}
|
||||||
|
|
||||||
# Import environment specific config. This must remain at the bottom
|
# Import environment specific config. This must remain at the bottom
|
||||||
# of this file so it overrides the configuration defined above.
|
# of this file so it overrides the configuration defined above.
|
||||||
|
|
|
@ -5,7 +5,7 @@ import Config
|
||||||
# The watchers configuration can be used to run external
|
# The watchers configuration can be used to run external
|
||||||
# watchers to your application. For example, we use it
|
# watchers to your application. For example, we use it
|
||||||
# with webpack to recompile .js and .css sources.
|
# with webpack to recompile .js and .css sources.
|
||||||
config :live_book, LiveBookWeb.Endpoint,
|
config :livebook, LivebookWeb.Endpoint,
|
||||||
# Binding to loopback ipv4 address prevents access from other machines.
|
# Binding to loopback ipv4 address prevents access from other machines.
|
||||||
# Change to `ip: {0, 0, 0, 0}` to allow access from other machines.
|
# Change to `ip: {0, 0, 0, 0}` to allow access from other machines.
|
||||||
http: [ip: {127, 0, 0, 1}, port: 4000],
|
http: [ip: {127, 0, 0, 1}, port: 4000],
|
||||||
|
@ -46,12 +46,12 @@ config :live_book, LiveBookWeb.Endpoint,
|
||||||
# different ports.
|
# different ports.
|
||||||
|
|
||||||
# Watch static and templates for browser reloading.
|
# Watch static and templates for browser reloading.
|
||||||
config :live_book, LiveBookWeb.Endpoint,
|
config :livebook, LivebookWeb.Endpoint,
|
||||||
live_reload: [
|
live_reload: [
|
||||||
patterns: [
|
patterns: [
|
||||||
~r"priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$",
|
~r"priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$",
|
||||||
~r"lib/live_book_web/(live|views)/.*(ex)$",
|
~r"lib/livebook_web/(live|views)/.*(ex)$",
|
||||||
~r"lib/live_book_web/templates/.*(eex)$"
|
~r"lib/livebook_web/templates/.*(eex)$"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import Config
|
||||||
# manifest is generated by the `mix phx.digest` task,
|
# manifest is generated by the `mix phx.digest` task,
|
||||||
# which you should run after static files are built and
|
# which you should run after static files are built and
|
||||||
# before starting your production server.
|
# before starting your production server.
|
||||||
config :live_book, LiveBookWeb.Endpoint,
|
config :livebook, LivebookWeb.Endpoint,
|
||||||
url: [host: "example.com", port: 80],
|
url: [host: "example.com", port: 80],
|
||||||
cache_static_manifest: "priv/static/cache_manifest.json"
|
cache_static_manifest: "priv/static/cache_manifest.json"
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ config :logger, level: :info
|
||||||
# To get SSL working, you will need to add the `https` key
|
# To get SSL working, you will need to add the `https` key
|
||||||
# to the previous section and set your `:url` port to 443:
|
# to the previous section and set your `:url` port to 443:
|
||||||
#
|
#
|
||||||
# config :live_book, LiveBookWeb.Endpoint,
|
# config :livebook, LivebookWeb.Endpoint,
|
||||||
# ...
|
# ...
|
||||||
# url: [host: "example.com", port: 443],
|
# url: [host: "example.com", port: 443],
|
||||||
# https: [
|
# https: [
|
||||||
|
@ -45,7 +45,7 @@ config :logger, level: :info
|
||||||
# We also recommend setting `force_ssl` in your endpoint, ensuring
|
# We also recommend setting `force_ssl` in your endpoint, ensuring
|
||||||
# no data is ever sent via http, always redirecting to https:
|
# no data is ever sent via http, always redirecting to https:
|
||||||
#
|
#
|
||||||
# config :live_book, LiveBookWeb.Endpoint,
|
# config :livebook, LivebookWeb.Endpoint,
|
||||||
# force_ssl: [hsts: true]
|
# force_ssl: [hsts: true]
|
||||||
#
|
#
|
||||||
# Check `Plug.SSL` for all available options in `force_ssl`.
|
# Check `Plug.SSL` for all available options in `force_ssl`.
|
||||||
|
|
|
@ -8,7 +8,7 @@ if config_env() == :prod do
|
||||||
You can generate one by calling: mix phx.gen.secret
|
You can generate one by calling: mix phx.gen.secret
|
||||||
"""
|
"""
|
||||||
|
|
||||||
config :live_book, LiveBookWeb.Endpoint,
|
config :livebook, LivebookWeb.Endpoint,
|
||||||
http: [
|
http: [
|
||||||
# Enable IPv6 and bind on all interfaces.
|
# Enable IPv6 and bind on all interfaces.
|
||||||
# Set it to {0, 0, 0, 0, 0, 0, 0, 1} for local network only access.
|
# Set it to {0, 0, 0, 0, 0, 0, 0, 1} for local network only access.
|
||||||
|
@ -22,7 +22,7 @@ if config_env() == :prod do
|
||||||
# If you are doing OTP releases, you need to instruct Phoenix
|
# If you are doing OTP releases, you need to instruct Phoenix
|
||||||
# to start each relevant endpoint:
|
# to start each relevant endpoint:
|
||||||
#
|
#
|
||||||
# config :live_book, LiveBookWeb.Endpoint, server: true
|
# config :livebook, LivebookWeb.Endpoint, server: true
|
||||||
#
|
#
|
||||||
# Then you can assemble a release by calling `mix release`.
|
# Then you can assemble a release by calling `mix release`.
|
||||||
# See `mix help release` for more information.
|
# See `mix help release` for more information.
|
||||||
|
|
|
@ -2,7 +2,7 @@ import Config
|
||||||
|
|
||||||
# We don't run a server during test. If one is required,
|
# We don't run a server during test. If one is required,
|
||||||
# you can enable the server option below.
|
# you can enable the server option below.
|
||||||
config :live_book, LiveBookWeb.Endpoint,
|
config :livebook, LivebookWeb.Endpoint,
|
||||||
http: [port: 4002],
|
http: [port: 4002],
|
||||||
server: false
|
server: false
|
||||||
|
|
||||||
|
@ -11,4 +11,4 @@ config :logger, level: :warn
|
||||||
|
|
||||||
# Use a different node name for tests to avoid interfering
|
# Use a different node name for tests to avoid interfering
|
||||||
# with a running development node.
|
# with a running development node.
|
||||||
config :live_book, :node_name, {:shortnames, :live_book_test}
|
config :livebook, :node_name, {:shortnames, :livebook_test}
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
defmodule LiveBook do
|
|
||||||
@moduledoc """
|
|
||||||
LiveBook.
|
|
||||||
"""
|
|
||||||
end
|
|
|
@ -1,3 +0,0 @@
|
||||||
defmodule LiveBookWeb.LayoutView do
|
|
||||||
use LiveBookWeb, :view
|
|
||||||
end
|
|
5
lib/livebook.ex
Normal file
5
lib/livebook.ex
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
defmodule Livebook do
|
||||||
|
@moduledoc """
|
||||||
|
Livebook.
|
||||||
|
"""
|
||||||
|
end
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule LiveBook.Application do
|
defmodule Livebook.Application do
|
||||||
# See https://hexdocs.pm/elixir/Application.html
|
# See https://hexdocs.pm/elixir/Application.html
|
||||||
# for more information on OTP Applications
|
# for more information on OTP Applications
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
@ -10,34 +10,34 @@ defmodule LiveBook.Application do
|
||||||
|
|
||||||
children = [
|
children = [
|
||||||
# Start the Telemetry supervisor
|
# Start the Telemetry supervisor
|
||||||
LiveBookWeb.Telemetry,
|
LivebookWeb.Telemetry,
|
||||||
# Start the PubSub system
|
# Start the PubSub system
|
||||||
{Phoenix.PubSub, name: LiveBook.PubSub},
|
{Phoenix.PubSub, name: Livebook.PubSub},
|
||||||
# Start the supervisor dynamically managing sessions
|
# Start the supervisor dynamically managing sessions
|
||||||
LiveBook.SessionSupervisor,
|
Livebook.SessionSupervisor,
|
||||||
# Start the server responsible for associating files with sessions
|
# Start the server responsible for associating files with sessions
|
||||||
LiveBook.Session.FileGuard,
|
Livebook.Session.FileGuard,
|
||||||
# Start the Endpoint (http/https)
|
# Start the Endpoint (http/https)
|
||||||
LiveBookWeb.Endpoint
|
LivebookWeb.Endpoint
|
||||||
]
|
]
|
||||||
|
|
||||||
# See https://hexdocs.pm/elixir/Supervisor.html
|
# See https://hexdocs.pm/elixir/Supervisor.html
|
||||||
# for other strategies and supported options
|
# for other strategies and supported options
|
||||||
opts = [strategy: :one_for_one, name: LiveBook.Supervisor]
|
opts = [strategy: :one_for_one, name: Livebook.Supervisor]
|
||||||
Supervisor.start_link(children, opts)
|
Supervisor.start_link(children, opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Tell Phoenix to update the endpoint configuration
|
# Tell Phoenix to update the endpoint configuration
|
||||||
# whenever the application is updated.
|
# whenever the application is updated.
|
||||||
def config_change(changed, _new, removed) do
|
def config_change(changed, _new, removed) do
|
||||||
LiveBookWeb.Endpoint.config_change(changed, removed)
|
LivebookWeb.Endpoint.config_change(changed, removed)
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
|
|
||||||
defp ensure_distribution() do
|
defp ensure_distribution() do
|
||||||
unless Node.alive?() do
|
unless Node.alive?() do
|
||||||
System.cmd("epmd", ["-daemon"])
|
System.cmd("epmd", ["-daemon"])
|
||||||
{type, name} = Application.fetch_env!(:live_book, :node_name)
|
{type, name} = Application.fetch_env!(:livebook, :node_name)
|
||||||
Node.start(name, type)
|
Node.start(name, type)
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule LiveBook.Config do
|
defmodule Livebook.Config do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
@ -6,7 +6,7 @@ defmodule LiveBook.Config do
|
||||||
"""
|
"""
|
||||||
@spec shortnames?() :: boolean()
|
@spec shortnames?() :: boolean()
|
||||||
def shortnames?() do
|
def shortnames?() do
|
||||||
case Application.fetch_env!(:live_book, :node_name) do
|
case Application.fetch_env!(:livebook, :node_name) do
|
||||||
{:shortnames, _name} -> true
|
{:shortnames, _name} -> true
|
||||||
{:longnames, _name} -> false
|
{:longnames, _name} -> false
|
||||||
end
|
end
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule LiveBook.Delta do
|
defmodule Livebook.Delta do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
# Delta is a format used to represent a set of changes
|
# Delta is a format used to represent a set of changes
|
||||||
|
@ -11,15 +11,15 @@ defmodule LiveBook.Delta do
|
||||||
# and https://quilljs.com/guides/designing-the-delta-format.
|
# and https://quilljs.com/guides/designing-the-delta-format.
|
||||||
# The specification covers rich-text editing, while we only
|
# The specification covers rich-text editing, while we only
|
||||||
# need to work with plain-text, so we use a subset of the specification
|
# need to work with plain-text, so we use a subset of the specification
|
||||||
# with operations listed in `LiveBook.Delta.Operation`.
|
# with operations listed in `Livebook.Delta.Operation`.
|
||||||
#
|
#
|
||||||
# Also see https://hexdocs.pm/text_delta/TextDelta.html
|
# Also see https://hexdocs.pm/text_delta/TextDelta.html
|
||||||
# for a complete implementation of the Delta specification.
|
# for a complete implementation of the Delta specification.
|
||||||
|
|
||||||
defstruct ops: []
|
defstruct ops: []
|
||||||
|
|
||||||
alias LiveBook.Delta
|
alias Livebook.Delta
|
||||||
alias LiveBook.Delta.{Operation, Transformation}
|
alias Livebook.Delta.{Operation, Transformation}
|
||||||
|
|
||||||
@type t :: %Delta{ops: list(Operation.t())}
|
@type t :: %Delta{ops: list(Operation.t())}
|
||||||
|
|
||||||
|
@ -127,8 +127,8 @@ defmodule LiveBook.Delta do
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
iex> delta = %LiveBook.Delta{ops: [retain: 2, insert: "hey", delete: 3]}
|
iex> delta = %Livebook.Delta{ops: [retain: 2, insert: "hey", delete: 3]}
|
||||||
iex> LiveBook.Delta.to_compressed(delta)
|
iex> Livebook.Delta.to_compressed(delta)
|
||||||
[2, "hey", -3]
|
[2, "hey", -3]
|
||||||
"""
|
"""
|
||||||
@spec to_compressed(t()) :: list(Operation.compressed_t())
|
@spec to_compressed(t()) :: list(Operation.compressed_t())
|
||||||
|
@ -141,8 +141,8 @@ defmodule LiveBook.Delta do
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
iex> LiveBook.Delta.from_compressed([2, "hey", -3])
|
iex> Livebook.Delta.from_compressed([2, "hey", -3])
|
||||||
%LiveBook.Delta{ops: [retain: 2, insert: "hey", delete: 3]}
|
%Livebook.Delta{ops: [retain: 2, insert: "hey", delete: 3]}
|
||||||
"""
|
"""
|
||||||
@spec from_compressed(list(Operation.compressed_t())) :: t()
|
@spec from_compressed(list(Operation.compressed_t())) :: t()
|
||||||
def from_compressed(list) do
|
def from_compressed(list) do
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule LiveBook.Delta.Operation do
|
defmodule Livebook.Delta.Operation do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
# An peration represents an atomic change applicable to a text.
|
# An peration represents an atomic change applicable to a text.
|
||||||
|
@ -79,7 +79,7 @@ defmodule LiveBook.Delta.Operation do
|
||||||
|
|
||||||
iex> left = [{:insert, "cat"}]
|
iex> left = [{:insert, "cat"}]
|
||||||
iex> right = [{:retain, 2}, {:delete, 2}]
|
iex> right = [{:retain, 2}, {:delete, 2}]
|
||||||
iex> LiveBook.Delta.Operation.align_heads(left, right)
|
iex> Livebook.Delta.Operation.align_heads(left, right)
|
||||||
{
|
{
|
||||||
[{:insert, "ca"}, {:insert, "t"}],
|
[{:insert, "ca"}, {:insert, "t"}],
|
||||||
[{:retain, 2}, {:delete, 2}]
|
[{:retain, 2}, {:delete, 2}]
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule LiveBook.Delta.Transformation do
|
defmodule Livebook.Delta.Transformation do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
# Implementation of the Operational Transformation concept for deltas.
|
# Implementation of the Operational Transformation concept for deltas.
|
||||||
|
@ -18,8 +18,8 @@ defmodule LiveBook.Delta.Transformation do
|
||||||
# A reasonable solution is to have a server process where all
|
# A reasonable solution is to have a server process where all
|
||||||
# the clients send deltas, as it naturally imposes the necessary ordering.
|
# the clients send deltas, as it naturally imposes the necessary ordering.
|
||||||
|
|
||||||
alias LiveBook.Delta
|
alias Livebook.Delta
|
||||||
alias LiveBook.Delta.Operation
|
alias Livebook.Delta.Operation
|
||||||
|
|
||||||
@type priority :: :left | :right
|
@type priority :: :left | :right
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule LiveBook.Evaluator do
|
defmodule Livebook.Evaluator do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
# A process responsible for evaluating notebook code.
|
# A process responsible for evaluating notebook code.
|
||||||
|
@ -13,7 +13,7 @@ defmodule LiveBook.Evaluator do
|
||||||
|
|
||||||
use GenServer, restart: :temporary
|
use GenServer, restart: :temporary
|
||||||
|
|
||||||
alias LiveBook.Evaluator
|
alias Livebook.Evaluator
|
||||||
|
|
||||||
@type t :: GenServer.server()
|
@type t :: GenServer.server()
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ defmodule LiveBook.Evaluator do
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
|
|
||||||
* `formatter` - a module implementing the `LiveBook.Evaluator.Formatter` behaviour,
|
* `formatter` - a module implementing the `Livebook.Evaluator.Formatter` behaviour,
|
||||||
used for transforming evaluation response before it's sent to the client
|
used for transforming evaluation response before it's sent to the client
|
||||||
"""
|
"""
|
||||||
def start_link(opts \\ []) do
|
def start_link(opts \\ []) do
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule LiveBook.Evaluator.Formatter do
|
defmodule Livebook.Evaluator.Formatter do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
# Behaviour defining how evaluation results are transformed.
|
# Behaviour defining how evaluation results are transformed.
|
||||||
|
@ -10,7 +10,7 @@ defmodule LiveBook.Evaluator.Formatter do
|
||||||
# By defining a custom formatter the client can instruct
|
# By defining a custom formatter the client can instruct
|
||||||
# the `Evaluator` to send already transformed data.
|
# the `Evaluator` to send already transformed data.
|
||||||
|
|
||||||
alias LiveBook.Evaluator
|
alias Livebook.Evaluator
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Transforms the evaluation response.
|
Transforms the evaluation response.
|
|
@ -1,9 +1,9 @@
|
||||||
defmodule LiveBook.Evaluator.IdentityFormatter do
|
defmodule Livebook.Evaluator.IdentityFormatter do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
# The default formatter leaving the response unchanged.
|
# The default formatter leaving the response unchanged.
|
||||||
|
|
||||||
@behaviour LiveBook.Evaluator.Formatter
|
@behaviour Livebook.Evaluator.Formatter
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def format(evaluation_response), do: evaluation_response
|
def format(evaluation_response), do: evaluation_response
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule LiveBook.Evaluator.IOProxy do
|
defmodule Livebook.Evaluator.IOProxy do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
# An IO device process used by `Evaluator` as its `:stdio`.
|
# An IO device process used by `Evaluator` as its `:stdio`.
|
||||||
|
@ -15,7 +15,7 @@ defmodule LiveBook.Evaluator.IOProxy do
|
||||||
|
|
||||||
use GenServer
|
use GenServer
|
||||||
|
|
||||||
alias LiveBook.Evaluator
|
alias Livebook.Evaluator
|
||||||
|
|
||||||
## API
|
## API
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
defmodule LiveBook.Evaluator.StringFormatter do
|
defmodule Livebook.Evaluator.StringFormatter do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
# The formatter used by LiveBook for rendering the results.
|
# The formatter used by Livebook for rendering the results.
|
||||||
|
|
||||||
@behaviour LiveBook.Evaluator.Formatter
|
@behaviour Livebook.Evaluator.Formatter
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def format({:ok, value}) do
|
def format({:ok, value}) do
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule LiveBook.JSInterop do
|
defmodule Livebook.JSInterop do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
alias LiveBook.Delta
|
alias Livebook.Delta
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Returns the result of applying `delta` to `string`.
|
Returns the result of applying `delta` to `string`.
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule LiveBook.LiveMarkdown do
|
defmodule Livebook.LiveMarkdown do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
# Notebook file format used by LiveBook.
|
# Notebook file format used by Livebook.
|
||||||
#
|
#
|
||||||
# The format is based off of Markdown and preserves compatibility,
|
# The format is based off of Markdown and preserves compatibility,
|
||||||
# in the sense that every LiveMarkdown file is a valid Markdown file.
|
# in the sense that every LiveMarkdown file is a valid Markdown file.
|
|
@ -1,6 +1,6 @@
|
||||||
defmodule LiveBook.LiveMarkdown.Export do
|
defmodule Livebook.LiveMarkdown.Export do
|
||||||
alias LiveBook.Notebook
|
alias Livebook.Notebook
|
||||||
alias LiveBook.LiveMarkdown.MarkdownHelpers
|
alias Livebook.LiveMarkdown.MarkdownHelpers
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Converts the given notebook into a Markdown document.
|
Converts the given notebook into a Markdown document.
|
|
@ -1,6 +1,6 @@
|
||||||
defmodule LiveBook.LiveMarkdown.Import do
|
defmodule Livebook.LiveMarkdown.Import do
|
||||||
alias LiveBook.Notebook
|
alias Livebook.Notebook
|
||||||
alias LiveBook.LiveMarkdown.MarkdownHelpers
|
alias Livebook.LiveMarkdown.MarkdownHelpers
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Converts the given Markdown document into a notebook data structure.
|
Converts the given Markdown document into a notebook data structure.
|
||||||
|
@ -39,7 +39,7 @@ defmodule LiveBook.LiveMarkdown.Import do
|
||||||
|
|
||||||
# There should be only one h1 tag indicating notebook name,
|
# There should be only one h1 tag indicating notebook name,
|
||||||
# if there are many we downgrade all headings.
|
# if there are many we downgrade all headings.
|
||||||
# This doesn't apply to documents exported from LiveBook,
|
# This doesn't apply to documents exported from Livebook,
|
||||||
# but may be the case for an arbitrary markdown file,
|
# but may be the case for an arbitrary markdown file,
|
||||||
# so we do our best to preserve the intent.
|
# so we do our best to preserve the intent.
|
||||||
defp rewrite_multiple_primary_headings(ast) do
|
defp rewrite_multiple_primary_headings(ast) do
|
||||||
|
@ -94,7 +94,7 @@ defmodule LiveBook.LiveMarkdown.Import do
|
||||||
end
|
end
|
||||||
|
|
||||||
# Trims one-line comments to allow nice pattern matching
|
# Trims one-line comments to allow nice pattern matching
|
||||||
# on LiveBook-specific annotations with no regard to surrounding whitespace.
|
# on Livebook-specific annotations with no regard to surrounding whitespace.
|
||||||
defp trim_comments(ast) do
|
defp trim_comments(ast) do
|
||||||
Enum.map(ast, fn
|
Enum.map(ast, fn
|
||||||
{:comment, attrs, [line], %{comment: true}} ->
|
{:comment, attrs, [line], %{comment: true}} ->
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule LiveBook.LiveMarkdown.MarkdownHelpers do
|
defmodule Livebook.LiveMarkdown.MarkdownHelpers do
|
||||||
@doc """
|
@doc """
|
||||||
Reformats the given markdown document.
|
Reformats the given markdown document.
|
||||||
"""
|
"""
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule LiveBook.Notebook do
|
defmodule Livebook.Notebook do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
# Data structure representing a notebook.
|
# Data structure representing a notebook.
|
||||||
|
@ -13,7 +13,7 @@ defmodule LiveBook.Notebook do
|
||||||
|
|
||||||
defstruct [:name, :version, :sections, :metadata]
|
defstruct [:name, :version, :sections, :metadata]
|
||||||
|
|
||||||
alias LiveBook.Notebook.{Section, Cell}
|
alias Livebook.Notebook.{Section, Cell}
|
||||||
|
|
||||||
@type metadata :: %{String.t() => term()}
|
@type metadata :: %{String.t() => term()}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule LiveBook.Notebook.Cell do
|
defmodule Livebook.Notebook.Cell do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
# Data structure representing a single cell in a notebook.
|
# Data structure representing a single cell in a notebook.
|
||||||
|
@ -9,7 +9,7 @@ defmodule LiveBook.Notebook.Cell do
|
||||||
|
|
||||||
defstruct [:id, :type, :source, :outputs, :metadata]
|
defstruct [:id, :type, :source, :outputs, :metadata]
|
||||||
|
|
||||||
alias LiveBook.Utils
|
alias Livebook.Utils
|
||||||
|
|
||||||
@type id :: Utils.id()
|
@type id :: Utils.id()
|
||||||
@type type :: :markdown | :elixir
|
@type type :: :markdown | :elixir
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule LiveBook.Notebook.Section do
|
defmodule Livebook.Notebook.Section do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
# Data structure representing a single section in a notebook.
|
# Data structure representing a single section in a notebook.
|
||||||
|
@ -8,8 +8,8 @@ defmodule LiveBook.Notebook.Section do
|
||||||
|
|
||||||
defstruct [:id, :name, :cells, :metadata]
|
defstruct [:id, :name, :cells, :metadata]
|
||||||
|
|
||||||
alias LiveBook.Notebook.Cell
|
alias Livebook.Notebook.Cell
|
||||||
alias LiveBook.Utils
|
alias Livebook.Utils
|
||||||
|
|
||||||
@type id :: Utils.id()
|
@type id :: Utils.id()
|
||||||
@type metadata :: %{String.t() => term()}
|
@type metadata :: %{String.t() => term()}
|
|
@ -1,4 +1,4 @@
|
||||||
defprotocol LiveBook.Runtime do
|
defprotocol Livebook.Runtime do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
# This protocol defines an interface for evaluation backends.
|
# This protocol defines an interface for evaluation backends.
|
|
@ -1,10 +1,10 @@
|
||||||
defmodule LiveBook.Runtime.Attached do
|
defmodule Livebook.Runtime.Attached do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
# A runtime backed by an Elixir node managed externally.
|
# A runtime backed by an Elixir node managed externally.
|
||||||
#
|
#
|
||||||
# Such node must be already started and available,
|
# Such node must be already started and available,
|
||||||
# LiveBook doesn't manage its lifetime in any way
|
# Livebook doesn't manage its lifetime in any way
|
||||||
# and only loads/unloads the necessary elements.
|
# and only loads/unloads the necessary elements.
|
||||||
# The node can be an oridinary Elixir runtime,
|
# The node can be an oridinary Elixir runtime,
|
||||||
# a Mix project shell, a running release or anything else.
|
# a Mix project shell, a running release or anything else.
|
||||||
|
@ -17,13 +17,13 @@ defmodule LiveBook.Runtime.Attached do
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Checks if the given node is available for use and initializes
|
Checks if the given node is available for use and initializes
|
||||||
it with LiveBook-specific modules and processes.
|
it with Livebook-specific modules and processes.
|
||||||
"""
|
"""
|
||||||
@spec init(node()) :: {:ok, t()} | {:error, :unreachable | :already_in_use}
|
@spec init(node()) :: {:ok, t()} | {:error, :unreachable | :already_in_use}
|
||||||
def init(node) do
|
def init(node) do
|
||||||
case Node.ping(node) do
|
case Node.ping(node) do
|
||||||
:pong ->
|
:pong ->
|
||||||
case LiveBook.Runtime.ErlDist.initialize(node) do
|
case Livebook.Runtime.ErlDist.initialize(node) do
|
||||||
:ok ->
|
:ok ->
|
||||||
{:ok, %__MODULE__{node: node}}
|
{:ok, %__MODULE__{node: node}}
|
||||||
|
|
||||||
|
@ -37,8 +37,8 @@ defmodule LiveBook.Runtime.Attached do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defimpl LiveBook.Runtime, for: LiveBook.Runtime.Attached do
|
defimpl Livebook.Runtime, for: Livebook.Runtime.Attached do
|
||||||
alias LiveBook.Runtime.ErlDist
|
alias Livebook.Runtime.ErlDist
|
||||||
|
|
||||||
def connect(runtime) do
|
def connect(runtime) do
|
||||||
ErlDist.Manager.set_owner(runtime.node, self())
|
ErlDist.Manager.set_owner(runtime.node, self())
|
|
@ -1,15 +1,15 @@
|
||||||
defmodule LiveBook.Runtime.ElixirStandalone do
|
defmodule Livebook.Runtime.ElixirStandalone do
|
||||||
defstruct [:node, :primary_pid]
|
defstruct [:node, :primary_pid]
|
||||||
|
|
||||||
# A runtime backed by a standalone Elixir node managed by LiveBook.
|
# A runtime backed by a standalone Elixir node managed by Livebook.
|
||||||
#
|
#
|
||||||
# LiveBook is responsible for starting and terminating the node.
|
# Livebook is responsible for starting and terminating the node.
|
||||||
# Most importantly we have to make sure the started node doesn't
|
# Most importantly we have to make sure the started node doesn't
|
||||||
# stay in the system when the session or the entire LiveBook terminates.
|
# stay in the system when the session or the entire Livebook terminates.
|
||||||
|
|
||||||
import LiveBook.Runtime.StandaloneInit
|
import Livebook.Runtime.StandaloneInit
|
||||||
|
|
||||||
alias LiveBook.Utils
|
alias Livebook.Utils
|
||||||
|
|
||||||
@type t :: %__MODULE__{
|
@type t :: %__MODULE__{
|
||||||
node: node(),
|
node: node(),
|
||||||
|
@ -18,7 +18,7 @@ defmodule LiveBook.Runtime.ElixirStandalone do
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Starts a new Elixir node (i.e. a system process) and initializes
|
Starts a new Elixir node (i.e. a system process) and initializes
|
||||||
it with LiveBook-specific modules and processes.
|
it with Livebook-specific modules and processes.
|
||||||
|
|
||||||
If no process calls `Runtime.connect/1` for a period of time,
|
If no process calls `Runtime.connect/1` for a period of time,
|
||||||
the node automatically terminates. Whoever connects, becomes the owner
|
the node automatically terminates. Whoever connects, becomes the owner
|
||||||
|
@ -61,8 +61,8 @@ defmodule LiveBook.Runtime.ElixirStandalone do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defimpl LiveBook.Runtime, for: LiveBook.Runtime.ElixirStandalone do
|
defimpl Livebook.Runtime, for: Livebook.Runtime.ElixirStandalone do
|
||||||
alias LiveBook.Runtime.ErlDist
|
alias Livebook.Runtime.ErlDist
|
||||||
|
|
||||||
def connect(runtime) do
|
def connect(runtime) do
|
||||||
ErlDist.Manager.set_owner(runtime.node, self())
|
ErlDist.Manager.set_owner(runtime.node, self())
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule LiveBook.Runtime.ErlDist do
|
defmodule Livebook.Runtime.ErlDist do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
# This module allows for initializing nodes connected using
|
# This module allows for initializing nodes connected using
|
||||||
|
@ -7,29 +7,29 @@ defmodule LiveBook.Runtime.ErlDist do
|
||||||
# To ensure proper isolation between sessions,
|
# To ensure proper isolation between sessions,
|
||||||
# code evaluation may take place in a separate Elixir runtime,
|
# code evaluation may take place in a separate Elixir runtime,
|
||||||
# which also makes it easy to terminate the whole
|
# which also makes it easy to terminate the whole
|
||||||
# evaluation environment without stopping LiveBook.
|
# evaluation environment without stopping Livebook.
|
||||||
# This is what both `Runtime.ElixirStandalone` and `Runtime.Attached` do
|
# This is what both `Runtime.ElixirStandalone` and `Runtime.Attached` do
|
||||||
# and this module containes the shared functionality they need.
|
# and this module containes the shared functionality they need.
|
||||||
#
|
#
|
||||||
# To work with a separate node, we have to inject the necessary
|
# To work with a separate node, we have to inject the necessary
|
||||||
# LiveBook modules there and also start the relevant processes
|
# Livebook modules there and also start the relevant processes
|
||||||
# related to evaluation. Fortunately Erlang allows us to send modules
|
# related to evaluation. Fortunately Erlang allows us to send modules
|
||||||
# binary representation to the other node and load them dynamically.
|
# binary representation to the other node and load them dynamically.
|
||||||
|
|
||||||
# Modules to load into the connected node.
|
# Modules to load into the connected node.
|
||||||
@required_modules [
|
@required_modules [
|
||||||
LiveBook.Evaluator,
|
Livebook.Evaluator,
|
||||||
LiveBook.Evaluator.IOProxy,
|
Livebook.Evaluator.IOProxy,
|
||||||
LiveBook.Evaluator.StringFormatter,
|
Livebook.Evaluator.StringFormatter,
|
||||||
LiveBook.Runtime.ErlDist,
|
Livebook.Runtime.ErlDist,
|
||||||
LiveBook.Runtime.ErlDist.Manager,
|
Livebook.Runtime.ErlDist.Manager,
|
||||||
LiveBook.Runtime.ErlDist.EvaluatorSupervisor,
|
Livebook.Runtime.ErlDist.EvaluatorSupervisor,
|
||||||
LiveBook.Runtime.ErlDist.IOForwardGL
|
Livebook.Runtime.ErlDist.IOForwardGL
|
||||||
]
|
]
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Loads the necessary modules into the given node
|
Loads the necessary modules into the given node
|
||||||
and starts the primary LiveBook remote process.
|
and starts the primary Livebook remote process.
|
||||||
|
|
||||||
The initialization may be invoked only once on the given
|
The initialization may be invoked only once on the given
|
||||||
node until its disconnected.
|
node until its disconnected.
|
||||||
|
@ -54,18 +54,18 @@ defmodule LiveBook.Runtime.ErlDist do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp start_manager(node) do
|
defp start_manager(node) do
|
||||||
:rpc.call(node, LiveBook.Runtime.ErlDist.Manager, :start, [])
|
:rpc.call(node, Livebook.Runtime.ErlDist.Manager, :start, [])
|
||||||
end
|
end
|
||||||
|
|
||||||
defp initialized?(node) do
|
defp initialized?(node) do
|
||||||
case :rpc.call(node, Process, :whereis, [LiveBook.Runtime.ErlDist.Manager]) do
|
case :rpc.call(node, Process, :whereis, [Livebook.Runtime.ErlDist.Manager]) do
|
||||||
nil -> false
|
nil -> false
|
||||||
_pid -> true
|
_pid -> true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Unloads the previously loaded LiveBook modules from the caller node.
|
Unloads the previously loaded Livebook modules from the caller node.
|
||||||
"""
|
"""
|
||||||
def unload_required_modules() do
|
def unload_required_modules() do
|
||||||
for module <- @required_modules do
|
for module <- @required_modules do
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule LiveBook.Runtime.ErlDist.EvaluatorSupervisor do
|
defmodule Livebook.Runtime.ErlDist.EvaluatorSupervisor do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
# Supervisor responsible for dynamically spawning
|
# Supervisor responsible for dynamically spawning
|
||||||
|
@ -6,7 +6,7 @@ defmodule LiveBook.Runtime.ErlDist.EvaluatorSupervisor do
|
||||||
|
|
||||||
use DynamicSupervisor
|
use DynamicSupervisor
|
||||||
|
|
||||||
alias LiveBook.Evaluator
|
alias Livebook.Evaluator
|
||||||
|
|
||||||
@name __MODULE__
|
@name __MODULE__
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule LiveBook.Runtime.ErlDist.IOForwardGL do
|
defmodule Livebook.Runtime.ErlDist.IOForwardGL do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
# An IO device process forwarding all requests to sender's group leader.
|
# An IO device process forwarding all requests to sender's group leader.
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule LiveBook.Runtime.ErlDist.Manager do
|
defmodule Livebook.Runtime.ErlDist.Manager do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
# The primary LiveBook process started on a remote node.
|
# The primary Livebook process started on a remote node.
|
||||||
#
|
#
|
||||||
# This process is responsible for monitoring the owner
|
# This process is responsible for monitoring the owner
|
||||||
# process on the main node and cleaning up if it terminates.
|
# process on the main node and cleaning up if it terminates.
|
||||||
|
@ -10,8 +10,8 @@ defmodule LiveBook.Runtime.ErlDist.Manager do
|
||||||
|
|
||||||
use GenServer
|
use GenServer
|
||||||
|
|
||||||
alias LiveBook.Evaluator
|
alias Livebook.Evaluator
|
||||||
alias LiveBook.Runtime.ErlDist
|
alias Livebook.Runtime.ErlDist
|
||||||
|
|
||||||
@name __MODULE__
|
@name __MODULE__
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ defmodule LiveBook.Runtime.ErlDist.Manager do
|
||||||
@doc """
|
@doc """
|
||||||
Stops the manager.
|
Stops the manager.
|
||||||
|
|
||||||
This results in all LiveBook-related modules being unloaded from this node.
|
This results in all Livebook-related modules being unloaded from this node.
|
||||||
"""
|
"""
|
||||||
@spec stop(node()) :: :ok
|
@spec stop(node()) :: :ok
|
||||||
def stop(node) do
|
def stop(node) do
|
||||||
|
@ -95,7 +95,7 @@ defmodule LiveBook.Runtime.ErlDist.Manager do
|
||||||
Process.flag(:trap_exit, true)
|
Process.flag(:trap_exit, true)
|
||||||
|
|
||||||
{:ok, _} = ErlDist.EvaluatorSupervisor.start_link()
|
{:ok, _} = ErlDist.EvaluatorSupervisor.start_link()
|
||||||
{:ok, io_forward_gl_pid} = LiveBook.Runtime.ErlDist.IOForwardGL.start_link()
|
{:ok, io_forward_gl_pid} = Livebook.Runtime.ErlDist.IOForwardGL.start_link()
|
||||||
|
|
||||||
# Set `ignore_module_conflict` only for the Manager lifetime.
|
# Set `ignore_module_conflict` only for the Manager lifetime.
|
||||||
initial_ignore_module_conflict = Code.compiler_options()[:ignore_module_conflict]
|
initial_ignore_module_conflict = Code.compiler_options()[:ignore_module_conflict]
|
|
@ -1,15 +1,15 @@
|
||||||
defmodule LiveBook.Runtime.MixStandalone do
|
defmodule Livebook.Runtime.MixStandalone do
|
||||||
defstruct [:node, :primary_pid, :project_path]
|
defstruct [:node, :primary_pid, :project_path]
|
||||||
|
|
||||||
# A runtime backed by a standalone Elixir node managed by LiveBook.
|
# A runtime backed by a standalone Elixir node managed by Livebook.
|
||||||
#
|
#
|
||||||
# This runtime is similar to `LiveBook.Runtime.ElixirStandalone`,
|
# This runtime is similar to `Livebook.Runtime.ElixirStandalone`,
|
||||||
# but the node is started in the context of a Mix project.
|
# but the node is started in the context of a Mix project.
|
||||||
|
|
||||||
import LiveBook.Runtime.StandaloneInit
|
import Livebook.Runtime.StandaloneInit
|
||||||
|
|
||||||
alias LiveBook.Utils
|
alias Livebook.Utils
|
||||||
alias LiveBook.Utils.Emitter
|
alias Livebook.Utils.Emitter
|
||||||
|
|
||||||
@type t :: %__MODULE__{
|
@type t :: %__MODULE__{
|
||||||
node: node(),
|
node: node(),
|
||||||
|
@ -19,7 +19,7 @@ defmodule LiveBook.Runtime.MixStandalone do
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Starts a new Elixir node (i.e. a system process) and initializes
|
Starts a new Elixir node (i.e. a system process) and initializes
|
||||||
it with LiveBook-specific modules and processes.
|
it with Livebook-specific modules and processes.
|
||||||
|
|
||||||
The node is started together with a Mix environment appropriate
|
The node is started together with a Mix environment appropriate
|
||||||
for the given `project_path`. The setup may involve
|
for the given `project_path`. The setup may involve
|
||||||
|
@ -97,8 +97,8 @@ defmodule LiveBook.Runtime.MixStandalone do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defimpl LiveBook.Runtime, for: LiveBook.Runtime.MixStandalone do
|
defimpl Livebook.Runtime, for: Livebook.Runtime.MixStandalone do
|
||||||
alias LiveBook.Runtime.ErlDist
|
alias Livebook.Runtime.ErlDist
|
||||||
|
|
||||||
def connect(runtime) do
|
def connect(runtime) do
|
||||||
ErlDist.Manager.set_owner(runtime.node, self())
|
ErlDist.Manager.set_owner(runtime.node, self())
|
|
@ -1,19 +1,19 @@
|
||||||
defmodule LiveBook.Runtime.StandaloneInit do
|
defmodule Livebook.Runtime.StandaloneInit do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
# Generic functionality related to starting and setting up
|
# Generic functionality related to starting and setting up
|
||||||
# a new Elixir system process. It's used by both ElixirStandalone
|
# a new Elixir system process. It's used by both ElixirStandalone
|
||||||
# and MixStandalone runtimes.
|
# and MixStandalone runtimes.
|
||||||
|
|
||||||
alias LiveBook.Utils
|
alias Livebook.Utils
|
||||||
alias LiveBook.Utils.Emitter
|
alias Livebook.Utils.Emitter
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Returns a random name for a dynamically spawned node.
|
Returns a random name for a dynamically spawned node.
|
||||||
"""
|
"""
|
||||||
@spec random_node_name() :: atom()
|
@spec random_node_name() :: atom()
|
||||||
def random_node_name() do
|
def random_node_name() do
|
||||||
Utils.node_from_name("live_book_runtime_#{Utils.random_short_id()}")
|
Utils.node_from_name("livebook_runtime_#{Utils.random_short_id()}")
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
@ -26,7 +26,7 @@ defmodule LiveBook.Runtime.StandaloneInit do
|
||||||
"""
|
"""
|
||||||
@spec random_process_name() :: atom()
|
@spec random_process_name() :: atom()
|
||||||
def random_process_name() do
|
def random_process_name() do
|
||||||
:"live_book_parent_process_name_#{Utils.random_short_id()}"
|
:"livebook_parent_process_name_#{Utils.random_short_id()}"
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
@ -46,7 +46,7 @@ defmodule LiveBook.Runtime.StandaloneInit do
|
||||||
@spec elixir_flags(node()) :: list()
|
@spec elixir_flags(node()) :: list()
|
||||||
def elixir_flags(node_name) do
|
def elixir_flags(node_name) do
|
||||||
[
|
[
|
||||||
if(LiveBook.Config.shortnames?(), do: "--sname", else: "--name"),
|
if(Livebook.Config.shortnames?(), do: "--sname", else: "--name"),
|
||||||
to_string(node_name),
|
to_string(node_name),
|
||||||
"--erl",
|
"--erl",
|
||||||
# Minimize shedulers busy wait threshold,
|
# Minimize shedulers busy wait threshold,
|
||||||
|
@ -97,7 +97,7 @@ defmodule LiveBook.Runtime.StandaloneInit do
|
||||||
Port.demonitor(port_ref)
|
Port.demonitor(port_ref)
|
||||||
|
|
||||||
# We've just created the node, so it is surely not in use
|
# We've just created the node, so it is surely not in use
|
||||||
:ok = LiveBook.Runtime.ErlDist.initialize(child_node)
|
:ok = Livebook.Runtime.ErlDist.initialize(child_node)
|
||||||
|
|
||||||
send(primary_pid, {:node_initialized, init_ref})
|
send(primary_pid, {:node_initialized, init_ref})
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ defmodule LiveBook.Runtime.StandaloneInit do
|
||||||
|
|
||||||
receive do
|
receive do
|
||||||
{:node_initialized, ^init_ref} ->
|
{:node_initialized, ^init_ref} ->
|
||||||
manager_ref = Process.monitor(LiveBook.Runtime.ErlDist.Manager)
|
manager_ref = Process.monitor(Livebook.Runtime.ErlDist.Manager)
|
||||||
|
|
||||||
# Wait until the Manager process terminates.
|
# Wait until the Manager process terminates.
|
||||||
receive do
|
receive do
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule LiveBook.Session do
|
defmodule Livebook.Session do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
# Server corresponding to a single notebook session.
|
# Server corresponding to a single notebook session.
|
||||||
|
@ -14,9 +14,9 @@ defmodule LiveBook.Session do
|
||||||
|
|
||||||
use GenServer, restart: :temporary
|
use GenServer, restart: :temporary
|
||||||
|
|
||||||
alias LiveBook.Session.{Data, FileGuard}
|
alias Livebook.Session.{Data, FileGuard}
|
||||||
alias LiveBook.{Utils, Notebook, Delta, Runtime, LiveMarkdown}
|
alias Livebook.{Utils, Notebook, Delta, Runtime, LiveMarkdown}
|
||||||
alias LiveBook.Notebook.{Cell, Section}
|
alias Livebook.Notebook.{Cell, Section}
|
||||||
|
|
||||||
@type state :: %{
|
@type state :: %{
|
||||||
session_id: id(),
|
session_id: id(),
|
||||||
|
@ -536,7 +536,7 @@ defmodule LiveBook.Session do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp broadcast_message(session_id, message) do
|
defp broadcast_message(session_id, message) do
|
||||||
Phoenix.PubSub.broadcast(LiveBook.PubSub, "sessions:#{session_id}", message)
|
Phoenix.PubSub.broadcast(Livebook.PubSub, "sessions:#{session_id}", message)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp start_evaluation(state, cell, section) do
|
defp start_evaluation(state, cell, section) do
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule LiveBook.Session.Data do
|
defmodule Livebook.Session.Data do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
# A structure with shared session data.
|
# A structure with shared session data.
|
||||||
|
@ -26,8 +26,8 @@ defmodule LiveBook.Session.Data do
|
||||||
:client_pids
|
:client_pids
|
||||||
]
|
]
|
||||||
|
|
||||||
alias LiveBook.{Notebook, Evaluator, Delta, Runtime, JSInterop}
|
alias Livebook.{Notebook, Evaluator, Delta, Runtime, JSInterop}
|
||||||
alias LiveBook.Notebook.{Cell, Section}
|
alias Livebook.Notebook.{Cell, Section}
|
||||||
|
|
||||||
@type t :: %__MODULE__{
|
@type t :: %__MODULE__{
|
||||||
notebook: Notebook.t(),
|
notebook: Notebook.t(),
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule LiveBook.Session.FileGuard do
|
defmodule Livebook.Session.FileGuard do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
# Serves as a locking mechanism for notebook files.
|
# Serves as a locking mechanism for notebook files.
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule LiveBook.SessionSupervisor do
|
defmodule Livebook.SessionSupervisor do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
# Supervisor responsible for managing running notebook sessions.
|
# Supervisor responsible for managing running notebook sessions.
|
||||||
|
@ -8,7 +8,7 @@ defmodule LiveBook.SessionSupervisor do
|
||||||
|
|
||||||
use DynamicSupervisor
|
use DynamicSupervisor
|
||||||
|
|
||||||
alias LiveBook.{Session, Utils}
|
alias Livebook.{Session, Utils}
|
||||||
|
|
||||||
@name __MODULE__
|
@name __MODULE__
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ defmodule LiveBook.SessionSupervisor do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp broadcast_sessions_message(message) do
|
defp broadcast_sessions_message(message) do
|
||||||
Phoenix.PubSub.broadcast(LiveBook.PubSub, "sessions", message)
|
Phoenix.PubSub.broadcast(Livebook.PubSub, "sessions", message)
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule LiveBook.Utils do
|
defmodule Livebook.Utils do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
@type id :: binary()
|
@type id :: binary()
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule LiveBook.Utils.Emitter do
|
defmodule Livebook.Utils.Emitter do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
# A wrapper struct for sending messages to the specified process.
|
# A wrapper struct for sending messages to the specified process.
|
||||||
|
@ -45,8 +45,8 @@ defmodule LiveBook.Utils.Emitter do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defimpl Collectable, for: LiveBook.Utils.Emitter do
|
defimpl Collectable, for: Livebook.Utils.Emitter do
|
||||||
alias LiveBook.Utils.Emitter
|
alias Livebook.Utils.Emitter
|
||||||
|
|
||||||
def into(emitter) do
|
def into(emitter) do
|
||||||
collector_fun = fn
|
collector_fun = fn
|
|
@ -1,20 +1,20 @@
|
||||||
defmodule LiveBookWeb do
|
defmodule LivebookWeb do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
def controller do
|
def controller do
|
||||||
quote do
|
quote do
|
||||||
use Phoenix.Controller, namespace: LiveBookWeb
|
use Phoenix.Controller, namespace: LivebookWeb
|
||||||
|
|
||||||
import Plug.Conn
|
import Plug.Conn
|
||||||
alias LiveBookWeb.Router.Helpers, as: Routes
|
alias LivebookWeb.Router.Helpers, as: Routes
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def view do
|
def view do
|
||||||
quote do
|
quote do
|
||||||
use Phoenix.View,
|
use Phoenix.View,
|
||||||
root: "lib/live_book_web/templates",
|
root: "lib/livebook_web/templates",
|
||||||
namespace: LiveBookWeb
|
namespace: LivebookWeb
|
||||||
|
|
||||||
# Import convenience functions from controllers
|
# Import convenience functions from controllers
|
||||||
import Phoenix.Controller,
|
import Phoenix.Controller,
|
||||||
|
@ -28,7 +28,7 @@ defmodule LiveBookWeb do
|
||||||
def live_view do
|
def live_view do
|
||||||
quote do
|
quote do
|
||||||
use Phoenix.LiveView,
|
use Phoenix.LiveView,
|
||||||
layout: {LiveBookWeb.LayoutView, "live.html"}
|
layout: {LivebookWeb.LayoutView, "live.html"}
|
||||||
|
|
||||||
unquote(view_helpers())
|
unquote(view_helpers())
|
||||||
end
|
end
|
||||||
|
@ -62,11 +62,11 @@ defmodule LiveBookWeb do
|
||||||
|
|
||||||
# Import basic rendering functionality (render, render_layout, etc)
|
# Import basic rendering functionality (render, render_layout, etc)
|
||||||
import Phoenix.View
|
import Phoenix.View
|
||||||
alias LiveBookWeb.Router.Helpers, as: Routes
|
alias LivebookWeb.Router.Helpers, as: Routes
|
||||||
|
|
||||||
# Custom helpers
|
# Custom helpers
|
||||||
import LiveBookWeb.Helpers
|
import LivebookWeb.Helpers
|
||||||
alias LiveBookWeb.Icons
|
alias LivebookWeb.Icons
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule LiveBook.ANSI.Modifier do
|
defmodule Livebook.ANSI.Modifier do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
defmacro defmodifier(modifier, code, terminator \\ "m") do
|
defmacro defmodifier(modifier, code, terminator \\ "m") do
|
||||||
|
@ -10,10 +10,10 @@ defmodule LiveBook.ANSI.Modifier do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defmodule LiveBookWeb.ANSI do
|
defmodule LivebookWeb.ANSI do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
import LiveBook.ANSI.Modifier
|
import Livebook.ANSI.Modifier
|
||||||
|
|
||||||
# modifier ::
|
# modifier ::
|
||||||
# :reset
|
# :reset
|
|
@ -1,12 +1,12 @@
|
||||||
defmodule LiveBookWeb.Endpoint do
|
defmodule LivebookWeb.Endpoint do
|
||||||
use Phoenix.Endpoint, otp_app: :live_book
|
use Phoenix.Endpoint, otp_app: :livebook
|
||||||
|
|
||||||
# The session will be stored in the cookie and signed,
|
# The session will be stored in the cookie and signed,
|
||||||
# this means its contents can be read but not tampered with.
|
# this means its contents can be read but not tampered with.
|
||||||
# Set :encryption_salt if you would also like to encrypt it.
|
# Set :encryption_salt if you would also like to encrypt it.
|
||||||
@session_options [
|
@session_options [
|
||||||
store: :cookie,
|
store: :cookie,
|
||||||
key: "_live_book_key",
|
key: "_livebook_key",
|
||||||
signing_salt: "SqUy8vWM"
|
signing_salt: "SqUy8vWM"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ defmodule LiveBookWeb.Endpoint do
|
||||||
# when deploying your static files in production.
|
# when deploying your static files in production.
|
||||||
plug Plug.Static,
|
plug Plug.Static,
|
||||||
at: "/",
|
at: "/",
|
||||||
from: :live_book,
|
from: :livebook,
|
||||||
gzip: false,
|
gzip: false,
|
||||||
only: ~w(css fonts images js favicon.ico robots.txt)
|
only: ~w(css fonts images js favicon.ico robots.txt)
|
||||||
|
|
||||||
|
@ -42,5 +42,5 @@ defmodule LiveBookWeb.Endpoint do
|
||||||
plug Plug.MethodOverride
|
plug Plug.MethodOverride
|
||||||
plug Plug.Head
|
plug Plug.Head
|
||||||
plug Plug.Session, @session_options
|
plug Plug.Session, @session_options
|
||||||
plug LiveBookWeb.Router
|
plug LivebookWeb.Router
|
||||||
end
|
end
|
|
@ -1,8 +1,8 @@
|
||||||
defmodule LiveBookWeb.Helpers do
|
defmodule LivebookWeb.Helpers do
|
||||||
import Phoenix.LiveView.Helpers
|
import Phoenix.LiveView.Helpers
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Renders a component inside the `LiveBook.ModalComponent` component.
|
Renders a component inside the `Livebook.ModalComponent` component.
|
||||||
|
|
||||||
The rendered modal receives a `:return_to` option to properly update
|
The rendered modal receives a `:return_to` option to properly update
|
||||||
the URL when the modal is closed.
|
the URL when the modal is closed.
|
||||||
|
@ -10,7 +10,7 @@ defmodule LiveBookWeb.Helpers do
|
||||||
def live_modal(socket, component, opts) do
|
def live_modal(socket, component, opts) do
|
||||||
path = Keyword.fetch!(opts, :return_to)
|
path = Keyword.fetch!(opts, :return_to)
|
||||||
modal_opts = [id: :modal, return_to: path, component: component, opts: opts]
|
modal_opts = [id: :modal, return_to: path, component: component, opts: opts]
|
||||||
live_component(socket, LiveBookWeb.ModalComponent, modal_opts)
|
live_component(socket, LivebookWeb.ModalComponent, modal_opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
@ -30,5 +30,5 @@ defmodule LiveBookWeb.Helpers do
|
||||||
defp mac?(user_agent), do: String.match?(user_agent, ~r/Mac OS X/)
|
defp mac?(user_agent), do: String.match?(user_agent, ~r/Mac OS X/)
|
||||||
defp windows?(user_agent), do: String.match?(user_agent, ~r/Windows/)
|
defp windows?(user_agent), do: String.match?(user_agent, ~r/Windows/)
|
||||||
|
|
||||||
defdelegate ansi_string_to_html(string), to: LiveBookWeb.ANSI
|
defdelegate ansi_string_to_html(string), to: LivebookWeb.ANSI
|
||||||
end
|
end
|
|
@ -1,5 +1,5 @@
|
||||||
defmodule LiveBookWeb.CellComponent do
|
defmodule LivebookWeb.CellComponent do
|
||||||
use LiveBookWeb, :live_component
|
use LivebookWeb, :live_component
|
||||||
|
|
||||||
def render(assigns) do
|
def render(assigns) do
|
||||||
~L"""
|
~L"""
|
|
@ -1,12 +1,12 @@
|
||||||
defmodule LiveBookWeb.HomeLive do
|
defmodule LivebookWeb.HomeLive do
|
||||||
use LiveBookWeb, :live_view
|
use LivebookWeb, :live_view
|
||||||
|
|
||||||
alias LiveBook.{SessionSupervisor, Session, LiveMarkdown}
|
alias Livebook.{SessionSupervisor, Session, LiveMarkdown}
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def mount(_params, _session, socket) do
|
def mount(_params, _session, socket) do
|
||||||
if connected?(socket) do
|
if connected?(socket) do
|
||||||
Phoenix.PubSub.subscribe(LiveBook.PubSub, "sessions")
|
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions")
|
||||||
end
|
end
|
||||||
|
|
||||||
session_summaries = sort_session_summaries(SessionSupervisor.get_session_summaries())
|
session_summaries = sort_session_summaries(SessionSupervisor.get_session_summaries())
|
||||||
|
@ -28,7 +28,7 @@ defmodule LiveBookWeb.HomeLive do
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="container flex flex-col space-y-4">
|
<div class="container flex flex-col space-y-4">
|
||||||
<%= live_component @socket, LiveBookWeb.PathSelectComponent,
|
<%= live_component @socket, LivebookWeb.PathSelectComponent,
|
||||||
id: "path_select",
|
id: "path_select",
|
||||||
path: @path,
|
path: @path,
|
||||||
extnames: [LiveMarkdown.extension()],
|
extnames: [LiveMarkdown.extension()],
|
||||||
|
@ -59,7 +59,7 @@ defmodule LiveBookWeb.HomeLive do
|
||||||
No sessions currently running, you can create one above.
|
No sessions currently running, you can create one above.
|
||||||
</div>
|
</div>
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= live_component @socket, LiveBookWeb.SessionsComponent,
|
<%= live_component @socket, LivebookWeb.SessionsComponent,
|
||||||
id: "sessions_list",
|
id: "sessions_list",
|
||||||
session_summaries: @session_summaries %>
|
session_summaries: @session_summaries %>
|
||||||
<% end %>
|
<% end %>
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule LiveBookWeb.Icons do
|
defmodule LivebookWeb.Icons do
|
||||||
import Phoenix.HTML.Tag
|
import Phoenix.HTML.Tag
|
||||||
import Phoenix.LiveView.Helpers
|
import Phoenix.LiveView.Helpers
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
defmodule LiveBookWeb.InsertCellComponent do
|
defmodule LivebookWeb.InsertCellComponent do
|
||||||
use LiveBookWeb, :live_component
|
use LivebookWeb, :live_component
|
||||||
|
|
||||||
def render(assigns) do
|
def render(assigns) do
|
||||||
~L"""
|
~L"""
|
|
@ -1,5 +1,5 @@
|
||||||
defmodule LiveBookWeb.ModalComponent do
|
defmodule LivebookWeb.ModalComponent do
|
||||||
use LiveBookWeb, :live_component
|
use LivebookWeb, :live_component
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def render(assigns) do
|
def render(assigns) do
|
|
@ -1,5 +1,5 @@
|
||||||
defmodule LiveBookWeb.PathSelectComponent do
|
defmodule LivebookWeb.PathSelectComponent do
|
||||||
use LiveBookWeb, :live_component
|
use LivebookWeb, :live_component
|
||||||
|
|
||||||
# The component expects:
|
# The component expects:
|
||||||
#
|
#
|
|
@ -1,5 +1,5 @@
|
||||||
defmodule LiveBookWeb.SectionComponent do
|
defmodule LivebookWeb.SectionComponent do
|
||||||
use LiveBookWeb, :live_component
|
use LivebookWeb, :live_component
|
||||||
|
|
||||||
def render(assigns) do
|
def render(assigns) do
|
||||||
~L"""
|
~L"""
|
||||||
|
@ -25,20 +25,20 @@ defmodule LiveBookWeb.SectionComponent do
|
||||||
</div>
|
</div>
|
||||||
<div class="container py-2">
|
<div class="container py-2">
|
||||||
<div class="flex flex-col space-y-2 pb-80">
|
<div class="flex flex-col space-y-2 pb-80">
|
||||||
<%= live_component @socket, LiveBookWeb.InsertCellComponent,
|
<%= live_component @socket, LivebookWeb.InsertCellComponent,
|
||||||
id: "#{@section.id}:0",
|
id: "#{@section.id}:0",
|
||||||
section_id: @section.id,
|
section_id: @section.id,
|
||||||
index: 0,
|
index: 0,
|
||||||
persistent: @section.cells == [] %>
|
persistent: @section.cells == [] %>
|
||||||
<%= for {cell, index} <- Enum.with_index(@section.cells) do %>
|
<%= for {cell, index} <- Enum.with_index(@section.cells) do %>
|
||||||
<%= live_component @socket, LiveBookWeb.CellComponent,
|
<%= live_component @socket, LivebookWeb.CellComponent,
|
||||||
id: cell.id,
|
id: cell.id,
|
||||||
session_id: @session_id,
|
session_id: @session_id,
|
||||||
cell: cell,
|
cell: cell,
|
||||||
cell_info: @cell_infos[cell.id],
|
cell_info: @cell_infos[cell.id],
|
||||||
focused: @selected and cell.id == @focused_cell_id,
|
focused: @selected and cell.id == @focused_cell_id,
|
||||||
insert_mode: @insert_mode %>
|
insert_mode: @insert_mode %>
|
||||||
<%= live_component @socket, LiveBookWeb.InsertCellComponent,
|
<%= live_component @socket, LivebookWeb.InsertCellComponent,
|
||||||
id: "#{@section.id}:#{index + 1}",
|
id: "#{@section.id}:#{index + 1}",
|
||||||
section_id: @section.id,
|
section_id: @section.id,
|
||||||
index: index + 1,
|
index: index + 1,
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule LiveBookWeb.SessionLive do
|
defmodule LivebookWeb.SessionLive do
|
||||||
use LiveBookWeb, :live_view
|
use LivebookWeb, :live_view
|
||||||
|
|
||||||
alias LiveBook.{SessionSupervisor, Session, Delta, Notebook, Runtime}
|
alias Livebook.{SessionSupervisor, Session, Delta, Notebook, Runtime}
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def mount(%{"id" => session_id}, _session, socket) do
|
def mount(%{"id" => session_id}, _session, socket) do
|
||||||
|
@ -9,7 +9,7 @@ defmodule LiveBookWeb.SessionLive do
|
||||||
data =
|
data =
|
||||||
if connected?(socket) do
|
if connected?(socket) do
|
||||||
data = Session.register_client(session_id, self())
|
data = Session.register_client(session_id, self())
|
||||||
Phoenix.PubSub.subscribe(LiveBook.PubSub, "sessions:#{session_id}")
|
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions:#{session_id}")
|
||||||
|
|
||||||
data
|
data
|
||||||
else
|
else
|
||||||
|
@ -55,7 +55,7 @@ defmodule LiveBookWeb.SessionLive do
|
||||||
def render(assigns) do
|
def render(assigns) do
|
||||||
~L"""
|
~L"""
|
||||||
<%= if @live_action == :file do %>
|
<%= if @live_action == :file do %>
|
||||||
<%= live_modal @socket, LiveBookWeb.SessionLive.PersistenceComponent,
|
<%= live_modal @socket, LivebookWeb.SessionLive.PersistenceComponent,
|
||||||
id: :file_modal,
|
id: :file_modal,
|
||||||
return_to: Routes.session_path(@socket, :page, @session_id),
|
return_to: Routes.session_path(@socket, :page, @session_id),
|
||||||
session_id: @session_id,
|
session_id: @session_id,
|
||||||
|
@ -63,7 +63,7 @@ defmodule LiveBookWeb.SessionLive do
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%= if @live_action == :runtime do %>
|
<%= if @live_action == :runtime do %>
|
||||||
<%= live_modal @socket, LiveBookWeb.SessionLive.RuntimeComponent,
|
<%= live_modal @socket, LivebookWeb.SessionLive.RuntimeComponent,
|
||||||
id: :runtime_modal,
|
id: :runtime_modal,
|
||||||
return_to: Routes.session_path(@socket, :page, @session_id),
|
return_to: Routes.session_path(@socket, :page, @session_id),
|
||||||
session_id: @session_id,
|
session_id: @session_id,
|
||||||
|
@ -71,14 +71,14 @@ defmodule LiveBookWeb.SessionLive do
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%= if @live_action == :shortcuts do %>
|
<%= if @live_action == :shortcuts do %>
|
||||||
<%= live_modal @socket, LiveBookWeb.SessionLive.ShortcutsComponent,
|
<%= live_modal @socket, LivebookWeb.SessionLive.ShortcutsComponent,
|
||||||
id: :shortcuts_modal,
|
id: :shortcuts_modal,
|
||||||
platform: @platform,
|
platform: @platform,
|
||||||
return_to: Routes.session_path(@socket, :page, @session_id) %>
|
return_to: Routes.session_path(@socket, :page, @session_id) %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%= if @live_action == :cell_settings do %>
|
<%= if @live_action == :cell_settings do %>
|
||||||
<%= live_modal @socket, LiveBookWeb.SessionLive.CellSettingsComponent,
|
<%= live_modal @socket, LivebookWeb.SessionLive.CellSettingsComponent,
|
||||||
id: :cell_settings_modal,
|
id: :cell_settings_modal,
|
||||||
session_id: @session_id,
|
session_id: @session_id,
|
||||||
cell: @cell,
|
cell: @cell,
|
||||||
|
@ -154,7 +154,7 @@ defmodule LiveBookWeb.SessionLive do
|
||||||
<div class="flex-grow px-6 py-8 flex overflow-y-auto">
|
<div class="flex-grow px-6 py-8 flex overflow-y-auto">
|
||||||
<div class="max-w-screen-lg w-full mx-auto">
|
<div class="max-w-screen-lg w-full mx-auto">
|
||||||
<%= for section <- @data.notebook.sections do %>
|
<%= for section <- @data.notebook.sections do %>
|
||||||
<%= live_component @socket, LiveBookWeb.SectionComponent,
|
<%= live_component @socket, LivebookWeb.SectionComponent,
|
||||||
id: section.id,
|
id: section.id,
|
||||||
session_id: @session_id,
|
session_id: @session_id,
|
||||||
section: section,
|
section: section,
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule LiveBookWeb.SessionLive.AttachedLive do
|
defmodule LivebookWeb.SessionLive.AttachedLive do
|
||||||
use LiveBookWeb, :live_view
|
use LivebookWeb, :live_view
|
||||||
|
|
||||||
alias LiveBook.{Session, Runtime, Utils}
|
alias Livebook.{Session, Runtime, Utils}
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def mount(_params, %{"session_id" => session_id}, socket) do
|
def mount(_params, %{"session_id" => session_id}, socket) do
|
||||||
|
@ -25,7 +25,7 @@ defmodule LiveBookWeb.SessionLive.AttachedLive do
|
||||||
Make sure to give the node a name, for example:
|
Make sure to give the node a name, for example:
|
||||||
</p>
|
</p>
|
||||||
<div class="text-gray-500 markdown">
|
<div class="text-gray-500 markdown">
|
||||||
<%= if LiveBook.Config.shortnames? do %>
|
<%= if Livebook.Config.shortnames? do %>
|
||||||
<pre><code>iex --sname test</code></pre>
|
<pre><code>iex --sname test</code></pre>
|
||||||
<% else %>
|
<% else %>
|
||||||
<pre><code>iex --name test@127.0.0.1</code></pre>
|
<pre><code>iex --name test@127.0.0.1</code></pre>
|
||||||
|
@ -36,7 +36,7 @@ defmodule LiveBookWeb.SessionLive.AttachedLive do
|
||||||
</p>
|
</p>
|
||||||
<%= f = form_for :node, "#", phx_submit: "init" %>
|
<%= f = form_for :node, "#", phx_submit: "init" %>
|
||||||
<%= text_input f, :name, class: "input-base shadow",
|
<%= text_input f, :name, class: "input-base shadow",
|
||||||
placeholder: if(LiveBook.Config.shortnames?, do: "test", else: "test@127.0.0.1") %>
|
placeholder: if(Livebook.Config.shortnames?, do: "test", else: "test@127.0.0.1") %>
|
||||||
|
|
||||||
<%= submit "Connect", class: "mt-3 button-base button-sm" %>
|
<%= submit "Connect", class: "mt-3 button-base button-sm" %>
|
||||||
</form>
|
</form>
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule LiveBookWeb.SessionLive.CellSettingsComponent do
|
defmodule LivebookWeb.SessionLive.CellSettingsComponent do
|
||||||
use LiveBookWeb, :live_component
|
use LivebookWeb, :live_component
|
||||||
|
|
||||||
alias LiveBook.Session
|
alias Livebook.Session
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def update(assigns, socket) do
|
def update(assigns, socket) do
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule LiveBookWeb.SessionLive.ElixirStandaloneLive do
|
defmodule LivebookWeb.SessionLive.ElixirStandaloneLive do
|
||||||
use LiveBookWeb, :live_view
|
use LivebookWeb, :live_view
|
||||||
|
|
||||||
alias LiveBook.{Session, Runtime}
|
alias Livebook.{Session, Runtime}
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def mount(_params, %{"session_id" => session_id}, socket) do
|
def mount(_params, %{"session_id" => session_id}, socket) do
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule LiveBookWeb.SessionLive.MixStandaloneLive do
|
defmodule LivebookWeb.SessionLive.MixStandaloneLive do
|
||||||
use LiveBookWeb, :live_view
|
use LivebookWeb, :live_view
|
||||||
|
|
||||||
alias LiveBook.{Session, Runtime, Utils}
|
alias Livebook.{Session, Runtime, Utils}
|
||||||
|
|
||||||
@type status :: :initial | :initializing | :finished
|
@type status :: :initial | :initializing | :finished
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ defmodule LiveBookWeb.SessionLive.MixStandaloneLive do
|
||||||
within the notebook.
|
within the notebook.
|
||||||
</p>
|
</p>
|
||||||
<%= if @status == :initial do %>
|
<%= if @status == :initial do %>
|
||||||
<%= live_component @socket, LiveBookWeb.PathSelectComponent,
|
<%= live_component @socket, LivebookWeb.PathSelectComponent,
|
||||||
id: "path_select",
|
id: "path_select",
|
||||||
path: @path,
|
path: @path,
|
||||||
extnames: [],
|
extnames: [],
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule LiveBookWeb.SessionLive.PersistenceComponent do
|
defmodule LivebookWeb.SessionLive.PersistenceComponent do
|
||||||
use LiveBookWeb, :live_component
|
use LivebookWeb, :live_component
|
||||||
|
|
||||||
alias LiveBook.{Session, SessionSupervisor, LiveMarkdown}
|
alias Livebook.{Session, SessionSupervisor, LiveMarkdown}
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def mount(socket) do
|
def mount(socket) do
|
||||||
|
@ -36,7 +36,7 @@ defmodule LiveBookWeb.SessionLive.PersistenceComponent do
|
||||||
</div>
|
</div>
|
||||||
<%= if @path != nil do %>
|
<%= if @path != nil do %>
|
||||||
<div class="w-full container flex flex-col space-y-4">
|
<div class="w-full container flex flex-col space-y-4">
|
||||||
<%= live_component @socket, LiveBookWeb.PathSelectComponent,
|
<%= live_component @socket, LivebookWeb.PathSelectComponent,
|
||||||
id: "path_select",
|
id: "path_select",
|
||||||
path: @path,
|
path: @path,
|
||||||
extnames: [LiveMarkdown.extension()],
|
extnames: [LiveMarkdown.extension()],
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule LiveBookWeb.SessionLive.RuntimeComponent do
|
defmodule LivebookWeb.SessionLive.RuntimeComponent do
|
||||||
use LiveBookWeb, :live_component
|
use LivebookWeb, :live_component
|
||||||
|
|
||||||
alias LiveBook.{Session, Runtime}
|
alias Livebook.{Session, Runtime}
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def mount(socket) do
|
def mount(socket) do
|
||||||
|
@ -69,17 +69,17 @@ defmodule LiveBookWeb.SessionLive.RuntimeComponent do
|
||||||
</form>
|
</form>
|
||||||
<div>
|
<div>
|
||||||
<%= if @type == "elixir_standalone" do %>
|
<%= if @type == "elixir_standalone" do %>
|
||||||
<%= live_render @socket, LiveBookWeb.SessionLive.ElixirStandaloneLive,
|
<%= live_render @socket, LivebookWeb.SessionLive.ElixirStandaloneLive,
|
||||||
id: :elixir_standalone_runtime,
|
id: :elixir_standalone_runtime,
|
||||||
session: %{"session_id" => @session_id} %>
|
session: %{"session_id" => @session_id} %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= if @type == "mix_standalone" do %>
|
<%= if @type == "mix_standalone" do %>
|
||||||
<%= live_render @socket, LiveBookWeb.SessionLive.MixStandaloneLive,
|
<%= live_render @socket, LivebookWeb.SessionLive.MixStandaloneLive,
|
||||||
id: :mix_standalone_runtime,
|
id: :mix_standalone_runtime,
|
||||||
session: %{"session_id" => @session_id} %>
|
session: %{"session_id" => @session_id} %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= if @type == "attached" do %>
|
<%= if @type == "attached" do %>
|
||||||
<%= live_render @socket, LiveBookWeb.SessionLive.AttachedLive,
|
<%= live_render @socket, LivebookWeb.SessionLive.AttachedLive,
|
||||||
id: :attached_runtime,
|
id: :attached_runtime,
|
||||||
session: %{"session_id" => @session_id} %>
|
session: %{"session_id" => @session_id} %>
|
||||||
<% end %>
|
<% end %>
|
|
@ -1,5 +1,5 @@
|
||||||
defmodule LiveBookWeb.SessionLive.ShortcutsComponent do
|
defmodule LivebookWeb.SessionLive.ShortcutsComponent do
|
||||||
use LiveBookWeb, :live_component
|
use LivebookWeb, :live_component
|
||||||
|
|
||||||
@shortcuts %{
|
@shortcuts %{
|
||||||
insert_mode: [
|
insert_mode: [
|
||||||
|
@ -38,7 +38,7 @@ defmodule LiveBookWeb.SessionLive.ShortcutsComponent do
|
||||||
Keyboard shortcuts
|
Keyboard shortcuts
|
||||||
</h3>
|
</h3>
|
||||||
<p class="text-gray-500">
|
<p class="text-gray-500">
|
||||||
LiveBook highly embraces keyboard navigation to improve your productivity.
|
Livebook highly embraces keyboard navigation to improve your productivity.
|
||||||
It operates in one of two modes similarly to the Vim text editor.
|
It operates in one of two modes similarly to the Vim text editor.
|
||||||
In <span class="font-semibold">navigation mode</span> you move around
|
In <span class="font-semibold">navigation mode</span> you move around
|
||||||
the notebook and execute commands, whereas in the <span class="font-semibold">insert mode</span>
|
the notebook and execute commands, whereas in the <span class="font-semibold">insert mode</span>
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule LiveBookWeb.SessionsComponent do
|
defmodule LivebookWeb.SessionsComponent do
|
||||||
use LiveBookWeb, :live_component
|
use LivebookWeb, :live_component
|
||||||
|
|
||||||
alias LiveBook.SessionSupervisor
|
alias Livebook.SessionSupervisor
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def render(assigns) do
|
def render(assigns) do
|
|
@ -1,11 +1,11 @@
|
||||||
defmodule LiveBookWeb.Router do
|
defmodule LivebookWeb.Router do
|
||||||
use LiveBookWeb, :router
|
use LivebookWeb, :router
|
||||||
|
|
||||||
pipeline :browser do
|
pipeline :browser do
|
||||||
plug :accepts, ["html"]
|
plug :accepts, ["html"]
|
||||||
plug :fetch_session
|
plug :fetch_session
|
||||||
plug :fetch_live_flash
|
plug :fetch_live_flash
|
||||||
plug :put_root_layout, {LiveBookWeb.LayoutView, :root}
|
plug :put_root_layout, {LivebookWeb.LayoutView, :root}
|
||||||
plug :protect_from_forgery
|
plug :protect_from_forgery
|
||||||
plug :put_secure_browser_headers
|
plug :put_secure_browser_headers
|
||||||
end
|
end
|
||||||
|
@ -14,7 +14,7 @@ defmodule LiveBookWeb.Router do
|
||||||
plug :accepts, ["json"]
|
plug :accepts, ["json"]
|
||||||
end
|
end
|
||||||
|
|
||||||
scope "/", LiveBookWeb do
|
scope "/", LivebookWeb do
|
||||||
pipe_through :browser
|
pipe_through :browser
|
||||||
|
|
||||||
live "/", HomeLive, :page
|
live "/", HomeLive, :page
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule LiveBookWeb.Telemetry do
|
defmodule LivebookWeb.Telemetry do
|
||||||
use Supervisor
|
use Supervisor
|
||||||
import Telemetry.Metrics
|
import Telemetry.Metrics
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ defmodule LiveBookWeb.Telemetry do
|
||||||
[
|
[
|
||||||
# A module, function and arguments to be invoked periodically.
|
# A module, function and arguments to be invoked periodically.
|
||||||
# This function must call :telemetry.execute/3 and a metric must be added above.
|
# This function must call :telemetry.execute/3 and a metric must be added above.
|
||||||
# {LiveBookWeb, :count_users, []}
|
# {LivebookWeb, :count_users, []}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
3
lib/livebook_web/views/layout_view.ex
Normal file
3
lib/livebook_web/views/layout_view.ex
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
defmodule LivebookWeb.LayoutView do
|
||||||
|
use LivebookWeb, :view
|
||||||
|
end
|
6
mix.exs
6
mix.exs
|
@ -1,9 +1,9 @@
|
||||||
defmodule LiveBook.MixProject do
|
defmodule Livebook.MixProject do
|
||||||
use Mix.Project
|
use Mix.Project
|
||||||
|
|
||||||
def project do
|
def project do
|
||||||
[
|
[
|
||||||
app: :live_book,
|
app: :livebook,
|
||||||
version: "0.1.0",
|
version: "0.1.0",
|
||||||
elixir: "~> 1.11",
|
elixir: "~> 1.11",
|
||||||
elixirc_paths: elixirc_paths(Mix.env()),
|
elixirc_paths: elixirc_paths(Mix.env()),
|
||||||
|
@ -19,7 +19,7 @@ defmodule LiveBook.MixProject do
|
||||||
# Type `mix help compile.app` for more information.
|
# Type `mix help compile.app` for more information.
|
||||||
def application do
|
def application do
|
||||||
[
|
[
|
||||||
mod: {LiveBook.Application, []},
|
mod: {Livebook.Application, []},
|
||||||
extra_applications: [:logger, :runtime_tools]
|
extra_applications: [:logger, :runtime_tools]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule LiveBook.Delta.TransformationText do
|
defmodule Livebook.Delta.TransformationText do
|
||||||
use ExUnit.Case, async: true
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
alias LiveBook.Delta
|
alias Livebook.Delta
|
||||||
|
|
||||||
describe "transform" do
|
describe "transform" do
|
||||||
test "insert against insert" do
|
test "insert against insert" do
|
|
@ -1,8 +1,8 @@
|
||||||
defmodule LiveBook.DeltaTest do
|
defmodule Livebook.DeltaTest do
|
||||||
use ExUnit.Case, async: true
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
alias LiveBook.Delta
|
alias Livebook.Delta
|
||||||
alias LiveBook.Delta.Operation
|
alias Livebook.Delta.Operation
|
||||||
|
|
||||||
doctest Delta
|
doctest Delta
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule LiveBook.Evaluator.IOProxyTest do
|
defmodule Livebook.Evaluator.IOProxyTest do
|
||||||
use ExUnit.Case, async: true
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
alias LiveBook.Evaluator.IOProxy
|
alias Livebook.Evaluator.IOProxy
|
||||||
|
|
||||||
setup do
|
setup do
|
||||||
{:ok, io} = IOProxy.start_link()
|
{:ok, io} = IOProxy.start_link()
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule LiveBook.EvaluatorTest do
|
defmodule Livebook.EvaluatorTest do
|
||||||
use ExUnit.Case, async: true
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
alias LiveBook.Evaluator
|
alias Livebook.Evaluator
|
||||||
|
|
||||||
setup do
|
setup do
|
||||||
{:ok, evaluator} = Evaluator.start_link()
|
{:ok, evaluator} = Evaluator.start_link()
|
||||||
|
@ -76,29 +76,29 @@ defmodule LiveBook.EvaluatorTest do
|
||||||
evaluator: evaluator
|
evaluator: evaluator
|
||||||
} do
|
} do
|
||||||
code = """
|
code = """
|
||||||
defmodule LiveBook.EvaluatorTest.Stacktrace.Math do
|
defmodule Livebook.EvaluatorTest.Stacktrace.Math do
|
||||||
def bad_math do
|
def bad_math do
|
||||||
result = 1 / 0
|
result = 1 / 0
|
||||||
{:ok, result}
|
{:ok, result}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defmodule LiveBook.EvaluatorTest.Stacktrace.Cat do
|
defmodule Livebook.EvaluatorTest.Stacktrace.Cat do
|
||||||
def meow do
|
def meow do
|
||||||
LiveBook.EvaluatorTest.Stacktrace.Math.bad_math()
|
Livebook.EvaluatorTest.Stacktrace.Math.bad_math()
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
LiveBook.EvaluatorTest.Stacktrace.Cat.meow()
|
Livebook.EvaluatorTest.Stacktrace.Cat.meow()
|
||||||
"""
|
"""
|
||||||
|
|
||||||
ignore_warnings(fn ->
|
ignore_warnings(fn ->
|
||||||
Evaluator.evaluate_code(evaluator, self(), code, :code_1)
|
Evaluator.evaluate_code(evaluator, self(), code, :code_1)
|
||||||
|
|
||||||
expected_stacktrace = [
|
expected_stacktrace = [
|
||||||
{LiveBook.EvaluatorTest.Stacktrace.Math, :bad_math, 0, [file: 'nofile', line: 3]},
|
{Livebook.EvaluatorTest.Stacktrace.Math, :bad_math, 0, [file: 'nofile', line: 3]},
|
||||||
{LiveBook.EvaluatorTest.Stacktrace.Cat, :meow, 0, [file: 'nofile', line: 10]}
|
{Livebook.EvaluatorTest.Stacktrace.Cat, :meow, 0, [file: 'nofile', line: 10]}
|
||||||
]
|
]
|
||||||
|
|
||||||
# Note: evaluating module definitions is relatively slow, so we use a higher wait timeout.
|
# Note: evaluating module definitions is relatively slow, so we use a higher wait timeout.
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule LiveBook.JSInteropTest do
|
defmodule Livebook.JSInteropTest do
|
||||||
use ExUnit.Case, async: true
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
alias LiveBook.{JSInterop, Delta}
|
alias Livebook.{JSInterop, Delta}
|
||||||
|
|
||||||
describe "apply_delta_to_string/2" do
|
describe "apply_delta_to_string/2" do
|
||||||
test "prepend" do
|
test "prepend" do
|
|
@ -1,8 +1,8 @@
|
||||||
defmodule LiveBook.LiveMarkdown.ExportTest do
|
defmodule Livebook.LiveMarkdown.ExportTest do
|
||||||
use ExUnit.Case, async: true
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
alias LiveBook.LiveMarkdown.Export
|
alias Livebook.LiveMarkdown.Export
|
||||||
alias LiveBook.Notebook
|
alias Livebook.Notebook
|
||||||
|
|
||||||
test "acceptance" do
|
test "acceptance" do
|
||||||
notebook = %{
|
notebook = %{
|
|
@ -1,8 +1,8 @@
|
||||||
defmodule LiveBook.LiveMarkdown.ImportTest do
|
defmodule Livebook.LiveMarkdown.ImportTest do
|
||||||
use ExUnit.Case, async: true
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
alias LiveBook.LiveMarkdown.Import
|
alias Livebook.LiveMarkdown.Import
|
||||||
alias LiveBook.Notebook
|
alias Livebook.Notebook
|
||||||
|
|
||||||
test "acceptance" do
|
test "acceptance" do
|
||||||
markdown = """
|
markdown = """
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule LiveBook.LiveMarkdown.MarkdownHelpersTest do
|
defmodule Livebook.LiveMarkdown.MarkdownHelpersTest do
|
||||||
use ExUnit.Case, async: true
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
alias LiveBook.LiveMarkdown.MarkdownHelpers
|
alias Livebook.LiveMarkdown.MarkdownHelpers
|
||||||
|
|
||||||
describe "markdown_from_ast/1" do
|
describe "markdown_from_ast/1" do
|
||||||
test "emphasis" do
|
test "emphasis" do
|
|
@ -1,8 +1,8 @@
|
||||||
defmodule LiveBook.NotebookTest do
|
defmodule Livebook.NotebookTest do
|
||||||
use ExUnit.Case, async: true
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
alias LiveBook.Notebook
|
alias Livebook.Notebook
|
||||||
alias LiveBook.Notebook.{Section, Cell}
|
alias Livebook.Notebook.{Section, Cell}
|
||||||
|
|
||||||
describe "fetch_cell_sibling/3" do
|
describe "fetch_cell_sibling/3" do
|
||||||
test "returns error given invalid cell id" do
|
test "returns error given invalid cell id" do
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule LiveBook.Runtime.AttachedTest do
|
defmodule Livebook.Runtime.AttachedTest do
|
||||||
use ExUnit.Case, async: true
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
alias LiveBook.Runtime
|
alias Livebook.Runtime
|
||||||
|
|
||||||
describe "init/1" do
|
describe "init/1" do
|
||||||
test "given an invalid node returns an error" do
|
test "given an invalid node returns an error" do
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule LiveBook.Runtime.ElixirStandaloneTest do
|
defmodule Livebook.Runtime.ElixirStandaloneTest do
|
||||||
use ExUnit.Case, async: true
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
alias LiveBook.Runtime
|
alias Livebook.Runtime
|
||||||
|
|
||||||
describe "init/1" do
|
describe "init/1" do
|
||||||
test "starts a new Elixir runtime in distribution mode and ties its lifetime to the Manager process" do
|
test "starts a new Elixir runtime in distribution mode and ties its lifetime to the Manager process" do
|
||||||
|
@ -13,7 +13,7 @@ defmodule LiveBook.Runtime.ElixirStandaloneTest do
|
||||||
assert :pong = Node.ping(node)
|
assert :pong = Node.ping(node)
|
||||||
|
|
||||||
# Tell the owner process to stop.
|
# Tell the owner process to stop.
|
||||||
LiveBook.Runtime.ErlDist.Manager.stop(node)
|
Livebook.Runtime.ErlDist.Manager.stop(node)
|
||||||
|
|
||||||
# Once Manager terminates, the node should terminate as well.
|
# Once Manager terminates, the node should terminate as well.
|
||||||
assert_receive {:nodedown, ^node}
|
assert_receive {:nodedown, ^node}
|
||||||
|
@ -42,10 +42,10 @@ defmodule LiveBook.Runtime.ElixirStandaloneTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp evaluator_module_loaded?(node) do
|
defp evaluator_module_loaded?(node) do
|
||||||
:rpc.call(node, :code, :is_loaded, [LiveBook.Evaluator]) != false
|
:rpc.call(node, :code, :is_loaded, [Livebook.Evaluator]) != false
|
||||||
end
|
end
|
||||||
|
|
||||||
defp manager_started?(node) do
|
defp manager_started?(node) do
|
||||||
:rpc.call(node, Process, :whereis, [LiveBook.Runtime.ErlDist.Manager]) != nil
|
:rpc.call(node, Process, :whereis, [Livebook.Runtime.ErlDist.Manager]) != nil
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule LiveBook.Runtime.ErlDist.IOForwardGLTest do
|
defmodule Livebook.Runtime.ErlDist.IOForwardGLTest do
|
||||||
use ExUnit.Case, async: true
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
alias LiveBook.Runtime.ErlDist.IOForwardGL
|
alias Livebook.Runtime.ErlDist.IOForwardGL
|
||||||
|
|
||||||
test "forwards requests to sender's group leader" do
|
test "forwards requests to sender's group leader" do
|
||||||
{:ok, pid} = IOForwardGL.start_link()
|
{:ok, pid} = IOForwardGL.start_link()
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule LiveBook.Runtime.ErlDist.ManagerTest do
|
defmodule Livebook.Runtime.ErlDist.ManagerTest do
|
||||||
use ExUnit.Case, async: false
|
use ExUnit.Case, async: false
|
||||||
|
|
||||||
alias LiveBook.Runtime.ErlDist.Manager
|
alias Livebook.Runtime.ErlDist.Manager
|
||||||
|
|
||||||
describe "set_owner/2" do
|
describe "set_owner/2" do
|
||||||
test "starts watching the given process and terminates as soon as it terminates" do
|
test "starts watching the given process and terminates as soon as it terminates" do
|
||||||
|
@ -17,8 +17,8 @@ defmodule LiveBook.Runtime.ErlDist.ManagerTest do
|
||||||
Manager.set_owner(node(), owner)
|
Manager.set_owner(node(), owner)
|
||||||
|
|
||||||
# Make sure the node is running.
|
# Make sure the node is running.
|
||||||
assert Process.whereis(LiveBook.Runtime.ErlDist.Manager) != nil
|
assert Process.whereis(Livebook.Runtime.ErlDist.Manager) != nil
|
||||||
ref = Process.monitor(LiveBook.Runtime.ErlDist.Manager)
|
ref = Process.monitor(Livebook.Runtime.ErlDist.Manager)
|
||||||
|
|
||||||
# Tell the owner process to stop.
|
# Tell the owner process to stop.
|
||||||
send(owner, :stop)
|
send(owner, :stop)
|
|
@ -1,8 +1,8 @@
|
||||||
defmodule LiveBook.Session.DataTest do
|
defmodule Livebook.Session.DataTest do
|
||||||
use ExUnit.Case, async: true
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
alias LiveBook.Session.Data
|
alias Livebook.Session.Data
|
||||||
alias LiveBook.{Delta, Notebook}
|
alias Livebook.{Delta, Notebook}
|
||||||
|
|
||||||
describe "new/1" do
|
describe "new/1" do
|
||||||
test "called with no arguments defaults to a blank notebook" do
|
test "called with no arguments defaults to a blank notebook" do
|
||||||
|
@ -1084,7 +1084,7 @@ defmodule LiveBook.Session.DataTest do
|
||||||
test "updates data with the given runtime" do
|
test "updates data with the given runtime" do
|
||||||
data = Data.new()
|
data = Data.new()
|
||||||
|
|
||||||
{:ok, runtime} = LiveBookTest.Runtime.SingleEvaluator.init()
|
{:ok, runtime} = LivebookTest.Runtime.SingleEvaluator.init()
|
||||||
|
|
||||||
operation = {:set_runtime, self(), runtime}
|
operation = {:set_runtime, self(), runtime}
|
||||||
|
|
||||||
|
@ -1108,7 +1108,7 @@ defmodule LiveBook.Session.DataTest do
|
||||||
{:queue_cell_evaluation, self(), "c4"}
|
{:queue_cell_evaluation, self(), "c4"}
|
||||||
])
|
])
|
||||||
|
|
||||||
{:ok, runtime} = LiveBookTest.Runtime.SingleEvaluator.init()
|
{:ok, runtime} = LivebookTest.Runtime.SingleEvaluator.init()
|
||||||
|
|
||||||
operation = {:set_runtime, self(), runtime}
|
operation = {:set_runtime, self(), runtime}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule LiveBook.Session.FileGuardTest do
|
defmodule Livebook.Session.FileGuardTest do
|
||||||
use ExUnit.Case, async: false
|
use ExUnit.Case, async: false
|
||||||
|
|
||||||
alias LiveBook.Session.FileGuard
|
alias Livebook.Session.FileGuard
|
||||||
|
|
||||||
test "lock/2 returns an error if the given path is already locked" do
|
test "lock/2 returns an error if the given path is already locked" do
|
||||||
assert :ok = FileGuard.lock("/some/path", self())
|
assert :ok = FileGuard.lock("/some/path", self())
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule LiveBook.SessionSupervisorTest do
|
defmodule Livebook.SessionSupervisorTest do
|
||||||
use ExUnit.Case
|
use ExUnit.Case
|
||||||
|
|
||||||
alias LiveBook.SessionSupervisor
|
alias Livebook.SessionSupervisor
|
||||||
|
|
||||||
describe "create_session/0" do
|
describe "create_session/0" do
|
||||||
test "creates a new session process and returns its id" do
|
test "creates a new session process and returns its id" do
|
||||||
|
@ -12,7 +12,7 @@ defmodule LiveBook.SessionSupervisorTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "broadcasts a message" do
|
test "broadcasts a message" do
|
||||||
Phoenix.PubSub.subscribe(LiveBook.PubSub, "sessions")
|
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions")
|
||||||
{:ok, id} = SessionSupervisor.create_session()
|
{:ok, id} = SessionSupervisor.create_session()
|
||||||
|
|
||||||
assert_receive {:session_created, ^id}
|
assert_receive {:session_created, ^id}
|
||||||
|
@ -32,7 +32,7 @@ defmodule LiveBook.SessionSupervisorTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "broadcasts a message" do
|
test "broadcasts a message" do
|
||||||
Phoenix.PubSub.subscribe(LiveBook.PubSub, "sessions")
|
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions")
|
||||||
{:ok, id} = SessionSupervisor.create_session()
|
{:ok, id} = SessionSupervisor.create_session()
|
||||||
|
|
||||||
SessionSupervisor.delete_session(id)
|
SessionSupervisor.delete_session(id)
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule LiveBook.SessionTest do
|
defmodule Livebook.SessionTest do
|
||||||
use ExUnit.Case, async: true
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
alias LiveBook.{Session, Delta, Runtime, Utils}
|
alias Livebook.{Session, Delta, Runtime, Utils}
|
||||||
|
|
||||||
setup do
|
setup do
|
||||||
session_id = start_session()
|
session_id = start_session()
|
||||||
|
@ -10,7 +10,7 @@ defmodule LiveBook.SessionTest do
|
||||||
|
|
||||||
describe "insert_section/2" do
|
describe "insert_section/2" do
|
||||||
test "sends an insert opreation to subscribers", %{session_id: session_id} do
|
test "sends an insert opreation to subscribers", %{session_id: session_id} do
|
||||||
Phoenix.PubSub.subscribe(LiveBook.PubSub, "sessions:#{session_id}")
|
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions:#{session_id}")
|
||||||
pid = self()
|
pid = self()
|
||||||
|
|
||||||
Session.insert_section(session_id, 0)
|
Session.insert_section(session_id, 0)
|
||||||
|
@ -20,7 +20,7 @@ defmodule LiveBook.SessionTest do
|
||||||
|
|
||||||
describe "insert_cell/4" do
|
describe "insert_cell/4" do
|
||||||
test "sends an insert opreation to subscribers", %{session_id: session_id} do
|
test "sends an insert opreation to subscribers", %{session_id: session_id} do
|
||||||
Phoenix.PubSub.subscribe(LiveBook.PubSub, "sessions:#{session_id}")
|
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions:#{session_id}")
|
||||||
pid = self()
|
pid = self()
|
||||||
|
|
||||||
Session.insert_section(session_id, 0)
|
Session.insert_section(session_id, 0)
|
||||||
|
@ -33,7 +33,7 @@ defmodule LiveBook.SessionTest do
|
||||||
|
|
||||||
describe "delete_section/2" do
|
describe "delete_section/2" do
|
||||||
test "sends a delete opreation to subscribers", %{session_id: session_id} do
|
test "sends a delete opreation to subscribers", %{session_id: session_id} do
|
||||||
Phoenix.PubSub.subscribe(LiveBook.PubSub, "sessions:#{session_id}")
|
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions:#{session_id}")
|
||||||
pid = self()
|
pid = self()
|
||||||
|
|
||||||
{section_id, _cell_id} = insert_section_and_cell(session_id)
|
{section_id, _cell_id} = insert_section_and_cell(session_id)
|
||||||
|
@ -45,7 +45,7 @@ defmodule LiveBook.SessionTest do
|
||||||
|
|
||||||
describe "delete_cell/2" do
|
describe "delete_cell/2" do
|
||||||
test "sends a delete opreation to subscribers", %{session_id: session_id} do
|
test "sends a delete opreation to subscribers", %{session_id: session_id} do
|
||||||
Phoenix.PubSub.subscribe(LiveBook.PubSub, "sessions:#{session_id}")
|
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions:#{session_id}")
|
||||||
pid = self()
|
pid = self()
|
||||||
|
|
||||||
{_section_id, cell_id} = insert_section_and_cell(session_id)
|
{_section_id, cell_id} = insert_section_and_cell(session_id)
|
||||||
|
@ -57,7 +57,7 @@ defmodule LiveBook.SessionTest do
|
||||||
|
|
||||||
describe "queue_cell_evaluation/2" do
|
describe "queue_cell_evaluation/2" do
|
||||||
test "sends a queue evaluation operation to subscribers", %{session_id: session_id} do
|
test "sends a queue evaluation operation to subscribers", %{session_id: session_id} do
|
||||||
Phoenix.PubSub.subscribe(LiveBook.PubSub, "sessions:#{session_id}")
|
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions:#{session_id}")
|
||||||
pid = self()
|
pid = self()
|
||||||
|
|
||||||
{_section_id, cell_id} = insert_section_and_cell(session_id)
|
{_section_id, cell_id} = insert_section_and_cell(session_id)
|
||||||
|
@ -68,7 +68,7 @@ defmodule LiveBook.SessionTest do
|
||||||
|
|
||||||
test "triggers evaluation and sends update operation once it finishes",
|
test "triggers evaluation and sends update operation once it finishes",
|
||||||
%{session_id: session_id} do
|
%{session_id: session_id} do
|
||||||
Phoenix.PubSub.subscribe(LiveBook.PubSub, "sessions:#{session_id}")
|
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions:#{session_id}")
|
||||||
|
|
||||||
{_section_id, cell_id} = insert_section_and_cell(session_id)
|
{_section_id, cell_id} = insert_section_and_cell(session_id)
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ defmodule LiveBook.SessionTest do
|
||||||
|
|
||||||
describe "cancel_cell_evaluation/2" do
|
describe "cancel_cell_evaluation/2" do
|
||||||
test "sends a cancel evaluation operation to subscribers", %{session_id: session_id} do
|
test "sends a cancel evaluation operation to subscribers", %{session_id: session_id} do
|
||||||
Phoenix.PubSub.subscribe(LiveBook.PubSub, "sessions:#{session_id}")
|
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions:#{session_id}")
|
||||||
pid = self()
|
pid = self()
|
||||||
|
|
||||||
{_section_id, cell_id} = insert_section_and_cell(session_id)
|
{_section_id, cell_id} = insert_section_and_cell(session_id)
|
||||||
|
@ -92,7 +92,7 @@ defmodule LiveBook.SessionTest do
|
||||||
|
|
||||||
describe "set_notebook_name/2" do
|
describe "set_notebook_name/2" do
|
||||||
test "sends a notebook name update operation to subscribers", %{session_id: session_id} do
|
test "sends a notebook name update operation to subscribers", %{session_id: session_id} do
|
||||||
Phoenix.PubSub.subscribe(LiveBook.PubSub, "sessions:#{session_id}")
|
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions:#{session_id}")
|
||||||
pid = self()
|
pid = self()
|
||||||
|
|
||||||
Session.set_notebook_name(session_id, "Cat's guide to life")
|
Session.set_notebook_name(session_id, "Cat's guide to life")
|
||||||
|
@ -102,7 +102,7 @@ defmodule LiveBook.SessionTest do
|
||||||
|
|
||||||
describe "set_section_name/3" do
|
describe "set_section_name/3" do
|
||||||
test "sends a section name update operation to subscribers", %{session_id: session_id} do
|
test "sends a section name update operation to subscribers", %{session_id: session_id} do
|
||||||
Phoenix.PubSub.subscribe(LiveBook.PubSub, "sessions:#{session_id}")
|
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions:#{session_id}")
|
||||||
pid = self()
|
pid = self()
|
||||||
|
|
||||||
{section_id, _cell_id} = insert_section_and_cell(session_id)
|
{section_id, _cell_id} = insert_section_and_cell(session_id)
|
||||||
|
@ -114,7 +114,7 @@ defmodule LiveBook.SessionTest do
|
||||||
|
|
||||||
describe "apply_cell_delta/4" do
|
describe "apply_cell_delta/4" do
|
||||||
test "sends a cell delta operation to subscribers", %{session_id: session_id} do
|
test "sends a cell delta operation to subscribers", %{session_id: session_id} do
|
||||||
Phoenix.PubSub.subscribe(LiveBook.PubSub, "sessions:#{session_id}")
|
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions:#{session_id}")
|
||||||
pid = self()
|
pid = self()
|
||||||
|
|
||||||
{_section_id, cell_id} = insert_section_and_cell(session_id)
|
{_section_id, cell_id} = insert_section_and_cell(session_id)
|
||||||
|
@ -129,7 +129,7 @@ defmodule LiveBook.SessionTest do
|
||||||
|
|
||||||
describe "report_cell_revision/3" do
|
describe "report_cell_revision/3" do
|
||||||
test "sends a revision report operation to subscribers", %{session_id: session_id} do
|
test "sends a revision report operation to subscribers", %{session_id: session_id} do
|
||||||
Phoenix.PubSub.subscribe(LiveBook.PubSub, "sessions:#{session_id}")
|
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions:#{session_id}")
|
||||||
pid = self()
|
pid = self()
|
||||||
|
|
||||||
{_section_id, cell_id} = insert_section_and_cell(session_id)
|
{_section_id, cell_id} = insert_section_and_cell(session_id)
|
||||||
|
@ -142,7 +142,7 @@ defmodule LiveBook.SessionTest do
|
||||||
|
|
||||||
describe "set_cell_metadata/3" do
|
describe "set_cell_metadata/3" do
|
||||||
test "sends a metadata update operation to subscribers", %{session_id: session_id} do
|
test "sends a metadata update operation to subscribers", %{session_id: session_id} do
|
||||||
Phoenix.PubSub.subscribe(LiveBook.PubSub, "sessions:#{session_id}")
|
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions:#{session_id}")
|
||||||
pid = self()
|
pid = self()
|
||||||
|
|
||||||
{_section_id, cell_id} = insert_section_and_cell(session_id)
|
{_section_id, cell_id} = insert_section_and_cell(session_id)
|
||||||
|
@ -155,10 +155,10 @@ defmodule LiveBook.SessionTest do
|
||||||
|
|
||||||
describe "connect_runtime/2" do
|
describe "connect_runtime/2" do
|
||||||
test "sends a runtime update operation to subscribers", %{session_id: session_id} do
|
test "sends a runtime update operation to subscribers", %{session_id: session_id} do
|
||||||
Phoenix.PubSub.subscribe(LiveBook.PubSub, "sessions:#{session_id}")
|
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions:#{session_id}")
|
||||||
pid = self()
|
pid = self()
|
||||||
|
|
||||||
{:ok, runtime} = LiveBookTest.Runtime.SingleEvaluator.init()
|
{:ok, runtime} = LivebookTest.Runtime.SingleEvaluator.init()
|
||||||
Session.connect_runtime(session_id, runtime)
|
Session.connect_runtime(session_id, runtime)
|
||||||
|
|
||||||
assert_receive {:operation, {:set_runtime, ^pid, ^runtime}}
|
assert_receive {:operation, {:set_runtime, ^pid, ^runtime}}
|
||||||
|
@ -167,7 +167,7 @@ defmodule LiveBook.SessionTest do
|
||||||
|
|
||||||
describe "disconnect_runtime/1" do
|
describe "disconnect_runtime/1" do
|
||||||
test "sends a runtime update operation to subscribers", %{session_id: session_id} do
|
test "sends a runtime update operation to subscribers", %{session_id: session_id} do
|
||||||
Phoenix.PubSub.subscribe(LiveBook.PubSub, "sessions:#{session_id}")
|
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions:#{session_id}")
|
||||||
pid = self()
|
pid = self()
|
||||||
|
|
||||||
Session.disconnect_runtime(session_id)
|
Session.disconnect_runtime(session_id)
|
||||||
|
@ -180,7 +180,7 @@ defmodule LiveBook.SessionTest do
|
||||||
@tag :tmp_dir
|
@tag :tmp_dir
|
||||||
test "sends a path update operation to subscribers",
|
test "sends a path update operation to subscribers",
|
||||||
%{session_id: session_id, tmp_dir: tmp_dir} do
|
%{session_id: session_id, tmp_dir: tmp_dir} do
|
||||||
Phoenix.PubSub.subscribe(LiveBook.PubSub, "sessions:#{session_id}")
|
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions:#{session_id}")
|
||||||
pid = self()
|
pid = self()
|
||||||
|
|
||||||
path = Path.join(tmp_dir, "notebook.livemd")
|
path = Path.join(tmp_dir, "notebook.livemd")
|
||||||
|
@ -195,7 +195,7 @@ defmodule LiveBook.SessionTest do
|
||||||
path = Path.join(tmp_dir, "notebook.livemd")
|
path = Path.join(tmp_dir, "notebook.livemd")
|
||||||
start_session(path: path)
|
start_session(path: path)
|
||||||
|
|
||||||
Phoenix.PubSub.subscribe(LiveBook.PubSub, "sessions:#{session_id}")
|
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions:#{session_id}")
|
||||||
|
|
||||||
Session.set_path(session_id, path)
|
Session.set_path(session_id, path)
|
||||||
|
|
||||||
|
@ -212,7 +212,7 @@ defmodule LiveBook.SessionTest do
|
||||||
# Perform a change, so the notebook is dirty
|
# Perform a change, so the notebook is dirty
|
||||||
Session.set_notebook_name(session_id, "My notebook")
|
Session.set_notebook_name(session_id, "My notebook")
|
||||||
|
|
||||||
Phoenix.PubSub.subscribe(LiveBook.PubSub, "sessions:#{session_id}")
|
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions:#{session_id}")
|
||||||
|
|
||||||
refute File.exists?(path)
|
refute File.exists?(path)
|
||||||
|
|
||||||
|
@ -233,7 +233,7 @@ defmodule LiveBook.SessionTest do
|
||||||
# Perform a change, so the notebook is dirty
|
# Perform a change, so the notebook is dirty
|
||||||
Session.set_notebook_name(session_id, "My notebook")
|
Session.set_notebook_name(session_id, "My notebook")
|
||||||
|
|
||||||
Phoenix.PubSub.subscribe(LiveBook.PubSub, "sessions:#{session_id}")
|
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions:#{session_id}")
|
||||||
|
|
||||||
refute File.exists?(path)
|
refute File.exists?(path)
|
||||||
|
|
||||||
|
@ -265,7 +265,7 @@ defmodule LiveBook.SessionTest do
|
||||||
session_id = Utils.random_id()
|
session_id = Utils.random_id()
|
||||||
{:ok, _} = Session.start_link(id: session_id)
|
{:ok, _} = Session.start_link(id: session_id)
|
||||||
|
|
||||||
Phoenix.PubSub.subscribe(LiveBook.PubSub, "sessions:#{session_id}")
|
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions:#{session_id}")
|
||||||
|
|
||||||
{_section_id, cell_id} = insert_section_and_cell(session_id)
|
{_section_id, cell_id} = insert_section_and_cell(session_id)
|
||||||
|
|
||||||
|
@ -279,7 +279,7 @@ defmodule LiveBook.SessionTest do
|
||||||
{:ok, _} = Session.start_link(id: session_id)
|
{:ok, _} = Session.start_link(id: session_id)
|
||||||
{:ok, runtime} = Runtime.ElixirStandalone.init()
|
{:ok, runtime} = Runtime.ElixirStandalone.init()
|
||||||
|
|
||||||
Phoenix.PubSub.subscribe(LiveBook.PubSub, "sessions:#{session_id}")
|
Phoenix.PubSub.subscribe(Livebook.PubSub, "sessions:#{session_id}")
|
||||||
|
|
||||||
# Wait for the runtime to be set
|
# Wait for the runtime to be set
|
||||||
Session.connect_runtime(session_id, runtime)
|
Session.connect_runtime(session_id, runtime)
|
||||||
|
@ -297,7 +297,7 @@ defmodule LiveBook.SessionTest do
|
||||||
{:ok, _} = Session.start_link(Keyword.merge(opts, id: session_id))
|
{:ok, _} = Session.start_link(Keyword.merge(opts, id: session_id))
|
||||||
# By default, use the current node for evaluation,
|
# By default, use the current node for evaluation,
|
||||||
# rather than starting a standalone one.
|
# rather than starting a standalone one.
|
||||||
{:ok, runtime} = LiveBookTest.Runtime.SingleEvaluator.init()
|
{:ok, runtime} = LivebookTest.Runtime.SingleEvaluator.init()
|
||||||
Session.connect_runtime(session_id, runtime)
|
Session.connect_runtime(session_id, runtime)
|
||||||
session_id
|
session_id
|
||||||
end
|
end
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule LiveBook.Utils.EmitterTest do
|
defmodule Livebook.Utils.EmitterTest do
|
||||||
use ExUnit.Case, async: true
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
alias LiveBook.Utils.Emitter
|
alias Livebook.Utils.Emitter
|
||||||
|
|
||||||
describe "emit/2" do
|
describe "emit/2" do
|
||||||
test "sends the item as a message to the specified process" do
|
test "sends the item as a message to the specified process" do
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule LiveBookWeb.ANSITest do
|
defmodule LivebookWeb.ANSITest do
|
||||||
use ExUnit.Case, async: true
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
alias LiveBookWeb.ANSI
|
alias LivebookWeb.ANSI
|
||||||
|
|
||||||
describe "ansi_string_to_html/1" do
|
describe "ansi_string_to_html/1" do
|
||||||
test "converts ANSI escape codes to span tags" do
|
test "converts ANSI escape codes to span tags" do
|
|
@ -1,9 +1,9 @@
|
||||||
defmodule LiveBookWeb.HomeLiveTest do
|
defmodule LivebookWeb.HomeLiveTest do
|
||||||
use LiveBookWeb.ConnCase
|
use LivebookWeb.ConnCase
|
||||||
|
|
||||||
import Phoenix.LiveViewTest
|
import Phoenix.LiveViewTest
|
||||||
|
|
||||||
alias LiveBook.SessionSupervisor
|
alias Livebook.SessionSupervisor
|
||||||
|
|
||||||
test "disconnected and connected render", %{conn: conn} do
|
test "disconnected and connected render", %{conn: conn} do
|
||||||
{:ok, view, disconnected_html} = live(conn, "/")
|
{:ok, view, disconnected_html} = live(conn, "/")
|
||||||
|
@ -30,7 +30,7 @@ defmodule LiveBookWeb.HomeLiveTest do
|
||||||
|
|
||||||
assert view
|
assert view
|
||||||
|> element("form")
|
|> element("form")
|
||||||
|> render_change(%{path: path}) =~ "live_book_web"
|
|> render_change(%{path: path}) =~ "livebook_web"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "allows importing when a notebook file is selected", %{conn: conn} do
|
test "allows importing when a notebook file is selected", %{conn: conn} do
|
|
@ -1,9 +1,9 @@
|
||||||
defmodule LiveBookWeb.PathSelectComponentTest do
|
defmodule LivebookWeb.PathSelectComponentTest do
|
||||||
use LiveBookWeb.ConnCase
|
use LivebookWeb.ConnCase
|
||||||
|
|
||||||
import Phoenix.LiveViewTest
|
import Phoenix.LiveViewTest
|
||||||
|
|
||||||
alias LiveBookWeb.PathSelectComponent
|
alias LivebookWeb.PathSelectComponent
|
||||||
|
|
||||||
test "when the path has a trailing slash, lists that directory" do
|
test "when the path has a trailing slash, lists that directory" do
|
||||||
path = notebooks_path() <> "/"
|
path = notebooks_path() <> "/"
|
|
@ -1,9 +1,9 @@
|
||||||
defmodule LiveBookWeb.SessionLiveTest do
|
defmodule LivebookWeb.SessionLiveTest do
|
||||||
use LiveBookWeb.ConnCase
|
use LivebookWeb.ConnCase
|
||||||
|
|
||||||
import Phoenix.LiveViewTest
|
import Phoenix.LiveViewTest
|
||||||
|
|
||||||
alias LiveBook.{SessionSupervisor, Session, Delta}
|
alias Livebook.{SessionSupervisor, Session, Delta}
|
||||||
|
|
||||||
setup do
|
setup do
|
||||||
{:ok, session_id} = SessionSupervisor.create_session()
|
{:ok, session_id} = SessionSupervisor.create_session()
|
|
@ -1,5 +1,5 @@
|
||||||
defmodule LiveBookWeb.LayoutViewTest do
|
defmodule LivebookWeb.LayoutViewTest do
|
||||||
use LiveBookWeb.ConnCase, async: true
|
use LivebookWeb.ConnCase, async: true
|
||||||
|
|
||||||
# When testing helpers, you may want to import Phoenix.HTML and
|
# When testing helpers, you may want to import Phoenix.HTML and
|
||||||
# use functions such as safe_to_string() to convert the helper
|
# use functions such as safe_to_string() to convert the helper
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule LiveBookWeb.ConnCase do
|
defmodule LivebookWeb.ConnCase do
|
||||||
use ExUnit.CaseTemplate
|
use ExUnit.CaseTemplate
|
||||||
|
|
||||||
using do
|
using do
|
||||||
|
@ -6,12 +6,12 @@ defmodule LiveBookWeb.ConnCase do
|
||||||
# Import conveniences for testing with connections
|
# Import conveniences for testing with connections
|
||||||
import Plug.Conn
|
import Plug.Conn
|
||||||
import Phoenix.ConnTest
|
import Phoenix.ConnTest
|
||||||
import LiveBookWeb.ConnCase
|
import LivebookWeb.ConnCase
|
||||||
|
|
||||||
alias LiveBookWeb.Router.Helpers, as: Routes
|
alias LivebookWeb.Router.Helpers, as: Routes
|
||||||
|
|
||||||
# The default endpoint for testing
|
# The default endpoint for testing
|
||||||
@endpoint LiveBookWeb.Endpoint
|
@endpoint LivebookWeb.Endpoint
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule LiveBookTest.Runtime.SingleEvaluator do
|
defmodule LivebookTest.Runtime.SingleEvaluator do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
# A simple runtime backed by a single evaluator process
|
# A simple runtime backed by a single evaluator process
|
||||||
|
@ -10,14 +10,14 @@ defmodule LiveBookTest.Runtime.SingleEvaluator do
|
||||||
defstruct [:evaluator]
|
defstruct [:evaluator]
|
||||||
|
|
||||||
def init() do
|
def init() do
|
||||||
with {:ok, evaluator} <- LiveBook.Evaluator.start_link() do
|
with {:ok, evaluator} <- Livebook.Evaluator.start_link() do
|
||||||
{:ok, %__MODULE__{evaluator: evaluator}}
|
{:ok, %__MODULE__{evaluator: evaluator}}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defimpl LiveBook.Runtime, for: LiveBookTest.Runtime.SingleEvaluator do
|
defimpl Livebook.Runtime, for: LivebookTest.Runtime.SingleEvaluator do
|
||||||
alias LiveBook.Evaluator
|
alias Livebook.Evaluator
|
||||||
|
|
||||||
def connect(runtime) do
|
def connect(runtime) do
|
||||||
Process.monitor(runtime.evaluator)
|
Process.monitor(runtime.evaluator)
|
||||||
|
|
Loading…
Reference in a new issue