commit: 5d215fd81f529b639db9096ca71d4e7f0a6ed386
parent: 8f9ee694ed47709231ffc852d2e82a06468cba06
Author: feld <feld@feld.me>
Date: Mon, 13 Jul 2020 15:45:25 +0000
Merge branch 'config-behaviours-runtime' into 'develop'
Config/Docs: Expand behaviour suggestions modules at runtime
Closes #1941
See merge request pleroma/pleroma!2755
Diffstat:
7 files changed, 47 insertions(+), 41 deletions(-)
diff --git a/config/description.exs b/config/description.exs
@@ -23,18 +23,14 @@ config :pleroma, :config_description, [
key: :uploader,
type: :module,
description: "Module which will be used for uploads",
- suggestions: [Pleroma.Uploaders.Local, Pleroma.Uploaders.S3]
+ suggestions: {:list_behaviour_implementations, Pleroma.Uploaders.Uploader}
},
%{
key: :filters,
type: {:list, :module},
description:
"List of filter modules for uploads. Module names are shortened (removed leading `Pleroma.Upload.Filter.` part), but on adding custom module you need to use full name.",
- suggestions:
- Generator.list_modules_in_dir(
- "lib/pleroma/upload/filter",
- "Elixir.Pleroma.Upload.Filter."
- )
+ suggestions: {:list_behaviour_implementations, Pleroma.Upload.Filter}
},
%{
key: :link_name,
@@ -1405,11 +1401,7 @@ config :pleroma, :config_description, [
type: [:module, {:list, :module}],
description:
"A list of MRF policies enabled. Module names are shortened (removed leading `Pleroma.Web.ActivityPub.MRF.` part), but on adding custom module you need to use full name.",
- suggestions:
- Generator.list_modules_in_dir(
- "lib/pleroma/web/activity_pub/mrf",
- "Elixir.Pleroma.Web.ActivityPub.MRF."
- )
+ suggestions: {:list_behaviour_implementations, Pleroma.Web.ActivityPub.MRF}
},
%{
key: :transparency,
diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex
@@ -42,6 +42,7 @@ defmodule Pleroma.Application do
Pleroma.ApplicationRequirements.verify!()
setup_instrumenters()
load_custom_modules()
+ Pleroma.Docs.JSON.compile()
adapter = Application.get_env(:tesla, :adapter)
diff --git a/lib/pleroma/docs/generator.ex b/lib/pleroma/docs/generator.ex
@@ -6,16 +6,21 @@ defmodule Pleroma.Docs.Generator do
implementation.process(descriptions)
end
- @spec list_modules_in_dir(String.t(), String.t()) :: [module()]
- def list_modules_in_dir(dir, start) do
- with {:ok, files} <- File.ls(dir) do
- files
- |> Enum.filter(&String.ends_with?(&1, ".ex"))
- |> Enum.map(fn filename ->
- module = filename |> String.trim_trailing(".ex") |> Macro.camelize()
- String.to_atom(start <> module)
- end)
- end
+ @spec list_behaviour_implementations(behaviour :: module()) :: [module()]
+ def list_behaviour_implementations(behaviour) do
+ :code.all_loaded()
+ |> Enum.filter(fn {module, _} ->
+ # This shouldn't be needed as all modules are expected to have module_info/1,
+ # but in test enviroments some transient modules `:elixir_compiler_XX`
+ # are loaded for some reason (where XX is a random integer).
+ if function_exported?(module, :module_info, 1) do
+ module.module_info(:attributes)
+ |> Keyword.get_values(:behaviour)
+ |> List.flatten()
+ |> Enum.member?(behaviour)
+ end
+ end)
+ |> Enum.map(fn {module, _} -> module end)
end
@doc """
@@ -87,6 +92,12 @@ defmodule Pleroma.Docs.Generator do
else: string
end
+ defp format_suggestions({:list_behaviour_implementations, behaviour}) do
+ behaviour
+ |> list_behaviour_implementations()
+ |> format_suggestions()
+ end
+
defp format_suggestions([]), do: []
defp format_suggestions([suggestion | tail]) do
diff --git a/lib/pleroma/docs/json.ex b/lib/pleroma/docs/json.ex
@@ -1,5 +1,19 @@
defmodule Pleroma.Docs.JSON do
@behaviour Pleroma.Docs.Generator
+ @external_resource "config/description.exs"
+ @raw_config Pleroma.Config.Loader.read("config/description.exs")
+ @raw_descriptions @raw_config[:pleroma][:config_description]
+ @term __MODULE__.Compiled
+
+ @spec compile :: :ok
+ def compile do
+ :persistent_term.put(@term, Pleroma.Docs.Generator.convert_to_strings(@raw_descriptions))
+ end
+
+ @spec compiled_descriptions :: Map.t()
+ def compiled_descriptions do
+ :persistent_term.get(@term)
+ end
@spec process(keyword()) :: {:ok, String.t()}
def process(descriptions) do
@@ -13,11 +27,4 @@ defmodule Pleroma.Docs.JSON do
{:ok, path}
end
end
-
- def compile do
- with config <- Pleroma.Config.Loader.read("config/description.exs") do
- config[:pleroma][:config_description]
- |> Pleroma.Docs.Generator.convert_to_strings()
- end
- end
end
diff --git a/lib/pleroma/docs/markdown.ex b/lib/pleroma/docs/markdown.ex
@@ -68,6 +68,11 @@ defmodule Pleroma.Docs.Markdown do
IO.write(file, " #{list_mark}`#{inspect(suggestion)}`\n")
end
+ defp print_suggestions(file, {:list_behaviour_implementations, behaviour}) do
+ suggestions = Pleroma.Docs.Generator.list_behaviour_implementations(behaviour)
+ print_suggestions(file, suggestions)
+ end
+
defp print_suggestions(_file, nil), do: nil
defp print_suggestions(_file, ""), do: nil
diff --git a/lib/pleroma/web/admin_api/controllers/config_controller.ex b/lib/pleroma/web/admin_api/controllers/config_controller.ex
@@ -9,8 +9,6 @@ defmodule Pleroma.Web.AdminAPI.ConfigController do
alias Pleroma.ConfigDB
alias Pleroma.Plugs.OAuthScopesPlug
- @descriptions Pleroma.Docs.JSON.compile()
-
plug(Pleroma.Web.ApiSpec.CastAndValidate)
plug(OAuthScopesPlug, %{scopes: ["write"], admin: true} when action == :update)
@@ -25,7 +23,7 @@ defmodule Pleroma.Web.AdminAPI.ConfigController do
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.ConfigOperation
def descriptions(conn, _params) do
- descriptions = Enum.filter(@descriptions, &whitelisted_config?/1)
+ descriptions = Enum.filter(Pleroma.Docs.JSON.compiled_descriptions(), &whitelisted_config?/1)
json(conn, descriptions)
end
diff --git a/test/docs/generator_test.exs b/test/docs/generator_test.exs
@@ -13,21 +13,13 @@ defmodule Pleroma.Docs.GeneratorTest do
key: :uploader,
type: :module,
description: "",
- suggestions:
- Generator.list_modules_in_dir(
- "lib/pleroma/upload/filter",
- "Elixir.Pleroma.Upload.Filter."
- )
+ suggestions: {:list_behaviour_implementations, Pleroma.Upload.Filter}
},
%{
key: :filters,
type: {:list, :module},
description: "",
- suggestions:
- Generator.list_modules_in_dir(
- "lib/pleroma/web/activity_pub/mrf",
- "Elixir.Pleroma.Web.ActivityPub.MRF."
- )
+ suggestions: {:list_behaviour_implementations, Pleroma.Web.ActivityPub.MRF}
},
%{
key: Pleroma.Upload,