Packages
kino
0.12.2
0.19.0
0.18.0
0.17.0
0.16.1
0.16.0
0.15.3
0.15.2
0.15.1
0.15.0
0.14.2
0.14.1
0.14.0
0.13.2
0.13.1
0.13.0
0.12.3
0.12.2
0.12.1
0.12.0
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.1
0.8.0
0.7.0
0.6.2
0.6.1
0.6.0
retired
0.5.2
0.5.1
0.5.0
0.4.1
0.4.0
0.3.1
0.3.0
0.2.3
0.2.2
0.2.1
0.2.0
0.1.3
0.1.2
0.1.1
0.1.0
Interactive widgets for Livebook
Current section
Files
Jump to
Current section
Files
lib/kino/fs.ex
defmodule Kino.FS do
@moduledoc """
Provides access to notebook files.
"""
defmodule ForbiddenError do
@moduledoc """
Exception raised when access to a notebook file is forbidden.
"""
defexception [:name]
@impl true
def message(exception) do
"forbidden access to file #{inspect(exception.name)}"
end
end
@doc """
Accesses notebook file with the given name and returns a local path
to read its contents from.
This invocation may take a while, in case the file is downloaded
from a URL and is not in the cache.
> #### File operations {: .info}
>
> You should treat the file as read-only. To avoid unnecessary
> copies the path may potentially be pointing to the original file,
> in which case any write operations would be persisted. This
> behaviour is not always the case, so you should not rely on it
> either.
"""
@spec file_path(String.t()) :: String.t()
def file_path(name) when is_binary(name) do
case Kino.Bridge.get_file_entry_path(name) do
{:ok, path} ->
path
{:error, :forbidden} ->
raise ForbiddenError, name: name
{:error, message} when is_binary(message) ->
raise message
{:error, reason} when is_atom(reason) ->
raise "failed to access file path, reason: #{inspect(reason)}"
end
end
@doc """
Accesses notebook file with the given name and returns a specification
of the file location.
This does not copy any files and moves the responsibility of reading
the file to the caller. If you need to read a file directly, use
`file_path/1`.
"""
@spec file_spec(String.t()) :: FSS.entry()
def file_spec(name) do
case Kino.Bridge.get_file_entry_spec(name) do
{:ok, spec} ->
file_spec_to_fss(spec)
{:error, :forbidden} ->
raise ForbiddenError, name: name
{:error, message} when is_binary(message) ->
raise message
{:error, reason} when is_atom(reason) ->
raise "failed to access file spec, reason: #{inspect(reason)}"
end
end
defp file_spec_to_fss(%{type: :local} = file_spec) do
FSS.Local.from_path(file_spec.path)
end
defp file_spec_to_fss(%{type: :url} = file_spec) do
case FSS.HTTP.parse(file_spec.url) do
{:ok, entry} -> entry
{:error, error} -> raise error
end
end
defp file_spec_to_fss(%{type: :s3} = file_spec) do
case FSS.S3.parse("s3:///" <> file_spec.key,
config: [
region: file_spec.region,
endpoint: file_spec.bucket_url,
access_key_id: file_spec.access_key_id,
secret_access_key: file_spec.secret_access_key,
# Token field is only available on Livebook v0.12 onwards
token: Map.get(file_spec, :token)
]
) do
{:ok, entry} -> entry
{:error, error} -> raise error
end
end
end