From 01e1f249650870b10c353ce290809a0f0f8eb366 Mon Sep 17 00:00:00 2001 From: Cristine Guadelupe Date: Sat, 20 Jan 2024 16:27:27 -0300 Subject: [PATCH] Explorer structs - initial support (#143) --- lib/kino/explorer.ex | 4 +- lib/kino_explorer/data_transform_cell.ex | 3 +- .../data_transform_cell_test.exs | 50 +++++++++++++++++++ 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/lib/kino/explorer.ex b/lib/kino/explorer.ex index c5652df..0bf9f29 100644 --- a/lib/kino/explorer.ex +++ b/lib/kino/explorer.ex @@ -131,6 +131,7 @@ defmodule Kino.Explorer do end defp value_to_string("list", value), do: inspect(value) + defp value_to_string("struct", value), do: inspect(value) defp value_to_string(_type, value), do: to_string(value) defp summaries(df, groups) do @@ -196,6 +197,7 @@ defmodule Kino.Explorer do defp type_of(:string, [data]), do: type_of_sample(data) defp type_of(:binary, _), do: "binary" defp type_of({:list, _}, _), do: "list" + defp type_of({:struct, _}, _), do: "struct" defp type_of(dtype, _), do: if(numeric_type?(dtype), do: "number", else: "text") defp type_of_sample("http" <> _rest), do: "uri" @@ -209,6 +211,6 @@ defmodule Kino.Explorer do defp lazy?(%DataFrame{data: %struct{}}), do: struct.lazy() == struct - defp build_top(top) when is_list(top), do: inspect(top) + defp build_top(top) when is_list(top) or is_map(top), do: inspect(top) defp build_top(top), do: to_string(top) end diff --git a/lib/kino_explorer/data_transform_cell.ex b/lib/kino_explorer/data_transform_cell.ex index ff9c00f..41d6937 100644 --- a/lib/kino_explorer/data_transform_cell.ex +++ b/lib/kino_explorer/data_transform_cell.ex @@ -994,6 +994,7 @@ defmodule KinoExplorer.DataTransformCell do {k, {:u, 32}} -> {k, "integer"} {k, {:u, 64}} -> {k, "integer"} {k, {:list, _}} -> {k, "list"} + {k, {:struct, _}} -> {k, "struct"} {k, v} -> {k, Atom.to_string(v)} end) |> Enum.into(%{}) @@ -1009,7 +1010,7 @@ defmodule KinoExplorer.DataTransformCell do end defp build_data_options(df) do - df |> DataFrame.dtypes() |> normalize_dtypes() + df |> DataFrame.dtypes() |> normalize_dtypes() |> Map.reject(fn {_k, v} -> v == "struct" end) end defp build_filter_for_list(column, "contains", value) do diff --git a/test/kino_explorer/data_transform_cell_test.exs b/test/kino_explorer/data_transform_cell_test.exs index 75e29e8..58dff86 100644 --- a/test/kino_explorer/data_transform_cell_test.exs +++ b/test/kino_explorer/data_transform_cell_test.exs @@ -150,6 +150,56 @@ defmodule KinoExplorer.DataTransformCellTest do }) end + test "removes struct-type columns from data options" do + {kino, _source} = start_smart_cell!(DataTransformCell, %{}) + + df = + Explorer.DataFrame.new( + [ + a: ["a", "b"], + b: [1, 2], + c: ["https://elixir-lang.org", "https://www.erlang.org"], + d: [<<110, 120>>, <<200, 210>>], + e: [[1, 2], [3, 4]], + f: [%{"a" => 42}, %{"a" => 51}] + ], + dtypes: [d: :binary] + ) + + env = Code.env_for_eval([]) + DataTransformCell.scan_binding(kino.pid, binding(), env) + + data_frame_variables = %{"df" => true} + + assert_broadcast_event(kino, "set_available_data", %{ + "data_frame_variables" => ^data_frame_variables, + "fields" => %{ + operations: [ + %{ + "active" => true, + "column" => nil, + "data_options" => + %{ + "a" => "string", + "b" => "integer", + "c" => "string", + "d" => "binary", + "e" => "list" + } = operation, + "datalist" => [], + "filter" => nil, + "operation_type" => "filters", + "type" => "string", + "value" => nil + } + ], + root_fields: %{"assign_to" => nil, "data_frame" => "df"} + } + }) + + refute Map.has_key?(operation, "f") + end + describe "code generation" do test "source for a data frame without operations" do attrs = build_attrs(%{})