Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python support #24

Merged
merged 8 commits into from
Jul 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions .dialyzer_ignore.exs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
[
{"deps/type_check/lib/type_check/spec.ex", "The pattern can never match the type {:ok, [], _}."},
{"deps/type_check/lib/type_check/spec.ex",
"The pattern can never match the type {:ok, [], _}."},
{"lib/plugin.ex", "Function usage_tuples/0 has no local return."},
{"lib/plugin.ex", "Function job_result/0 has no local return."},
{"lib/plugin.ex", "Function plugin_job_result/0 has no local return."},
{"lib/plugin.ex", "The guard clause can never succeed."},
{"lib/services/discord.ex", "Function vips/0 has no local return."},
{"lib/services/dummy.ex", "@spec for ask_bot has more types than are returned by the function."},
{"lib/services/dummy.ex",
"@spec for ask_bot has more types than are returned by the function."},
{"lib/services/dummy.ex", "Function dummy_channel_id/0 has no local return."},
{"lib/services/dummy.ex", "Function msg_content/0 has no local return."},
{"lib/services/dummy.ex", "Function msg_reference/0 has no local return."},
Expand All @@ -18,20 +20,25 @@
{"lib/site_config.ex", "Function cfg_list/0 has no local return."},
{"lib/stampede.ex", "Function dm_tuple/0 has no local return."},
{"lib/stampede.ex", "Function server_id/0 has no local return."},
{"lib/stampede.ex", "Function log_level/0 has no local return."},
{"lib/stampede.ex", "Function log_msg/0 has no local return."},
{"lib/stampede.ex", "Function prefix/0 has no local return."},
{"lib/stampede.ex", "Function module_function_args/0 has no local return."},
{"lib/stampede.ex", "Function str_list/0 has no local return."},
{"lib/stampede.ex", "Function enabled_plugs/0 has no local return."},
{"lib/stampede.ex", "Function channel_lock_action/0 has no local return."},
{"lib/stampede.ex", "Function channel_lock_status/0 has no local return."},
{"lib/stampede.ex", "Function timestamp/0 has no local return."},
{"lib/stampede.ex", "Function bot_invoked_status/0 has no local return."},
{"lib/stampede.ex", "Function module_function_args/0 has no local return."},
{"lib/stampede.ex", "Function log_level/0 has no local return."},
{"lib/stampede.ex", "Function log_msg/0 has no local return."},
{"lib/stampede.ex", "Function kwlist/1 has no local return."},
{"lib/stampede.ex", "Function kwlist/0 has no local return."},
{"lib/stampede.ex", "Function str_list/0 has no local return."},
{"lib/stampede.ex", "Function throw_internal_error/0 has no local return."},
{"lib/stampede.ex", "Function throw_internal_error/1 only terminates with explicit exception."},
{"lib/stampede/cfg_table.ex", "Function vips/0 has no local return."},
{"lib/stampede/cfg_table.ex", "Function table_object/0 has no local return."},
{"lib/stampede/external/python.ex", "The pattern can never match the type true."},
{"lib/stampede/external/python.ex",
"Function do_dumb_down_elixir_term/1 will never be called."},
{"lib/stampede/logger.ex", "Function logger_state/0 has no local return."},
{"lib/stampede/tables/channel_locks.ex", "The guard clause can never succeed."},
{"lib/stampede/tables/interactions.ex", "The guard clause can never succeed."},
Expand Down
4 changes: 4 additions & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ config :ex_unit,
# By default, Nostrum requires ffmpeg to use voice.
config :nostrum, :ffmpeg, false

config :stampede,
python_exe: System.fetch_env!("FLAKE_PYTHON"),
python_plugin_dirs: ["./lib_py"]

for config <- "./*.secret.exs" |> Path.expand(__DIR__) |> Path.wildcard() do
import_config config
end
20 changes: 10 additions & 10 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 33 additions & 10 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@
erl = with pkgs; beam.packages.erlang_26;
ex = erl.elixir_1_16;

########################
# Python versions
python = pkgs.python312;
mkPyPkg = name: python.withPackages (ps: [(builtins.getAttr name ps)]);

########################
# Git pre-push checks
pc-hooks = git-hooks.lib.${system}.run {
Expand Down Expand Up @@ -68,16 +73,27 @@
pass_filenames = false;
require_serial = true;
};
custom-mix-format = {
enable = true;
name = "mix-format";
entry = "${ex}/bin/mix format --check-formatted";
files = "\\.exs?$";
types = ["text"];
pass_filenames = false;
require_serial = true;
stages = ["manual" "push" "pre-merge-commit" "pre-commit"];
};
custom-mix-format =
enable_on_commit
// {
name = "mix-format";
entry = "${ex}/bin/mix format --check-formatted";
files = "\\.exs?$";
types = ["text"];
pass_filenames = false;
require_serial = true;
};

mypy =
enable_on_commit
// {
package = mkPyPkg "mypy";
};
black =
enable_on_commit
// {
package = mkPyPkg "black";
};
};
};
in {
Expand All @@ -94,11 +110,18 @@

pkgs.libyaml
pkgs.libyaml.dev

python
(mkPyPkg "python-lsp-server")
(mkPyPkg "pylsp-mypy")
(mkPyPkg "python-lsp-black")
]
++ pc-hooks.enabledPackages;

# define shell startup command
sh-hook = ''
export FLAKE_PYTHON="${python}/bin/python3"

# this allows mix to work on the local directory
mkdir -p .nix-mix
mkdir -p .nix-hex
Expand Down
36 changes: 21 additions & 15 deletions lib/stampede.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ defmodule Stampede do
"""
@compile [:bin_opt_info, :recv_opt_info]
use TypeCheck

# Types used across Stampede
@type! service_name :: module()
@type! channel_id :: any()
@typedoc """
Expand All @@ -13,34 +15,38 @@ defmodule Stampede do
@type! server_id :: integer() | atom() | dm_tuple()
@type! user_id :: any()
@type! msg_id :: any()
@type! log_level ::
:emergency | :alert | :critical | :error | :warning | :warn | :notice | :info | :debug
@type! log_msg ::
{log_level(), identifier(), {Logger, String.t() | maybe_improper_list(), any(), any()}}
@type! prefix :: String.t() | Regex.t()
@type! module_function_args :: {module(), atom(), tuple() | list()}
# BUG: type_check issue #189, iolist()
# this stand-in isn't type complete but it'll do
@type! str_list ::
String.t()
| []
| nonempty_list(lazy(Stampede.str_list()))
@type! mapset(t) :: map(any(), t)
@type! mapset() :: mapset(any())

@type! enabled_plugs :: :all | [] | nonempty_list(module())
@type! channel_lock_action ::
false | {:lock, channel_id(), module_function_args()} | {:unlock, channel_id()}
@type! channel_lock_status ::
false | {module_function_args(), atom(), integer()}
@type! timestamp :: DateTime.t()
@type! interaction_id :: non_neg_integer()

@type! bot_invoked_status ::
nil
| :mentioned_from_service
| :prefixed

# Elixir-generic stuff that could/should be builtin types
@type! module_function_args :: {module(), atom(), tuple() | list()}
@type! log_level ::
:emergency | :alert | :critical | :error | :warning | :warn | :notice | :info | :debug
@type! log_msg ::
{log_level(), identifier(), {Logger, String.t() | maybe_improper_list(), any(), any()}}
@type! mapset(t) :: map(any(), t)
@type! mapset() :: mapset(any())
@type! kwlist(t) :: list({atom(), t})
@type! kwlist() :: kwlist(any())
# BUG: type_check issue #189, iolist()
# this stand-in isn't type complete but it'll do
# No improper lists allowed
# also VERY SLOW to check.
@type! str_list ::
String.t()
| []
| nonempty_list(lazy(Stampede.str_list()))

def confused_response(),
do: {:italics, "confused beeping"}

Expand Down
5 changes: 5 additions & 0 deletions lib/stampede/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ defmodule Stampede.Application do
required: true,
doc: "Services installed as part of the mix project. Passed in from mix.exs"
],
# installed_foreign_plugins: [
# type: {:or, [{:in, [[]]}, {:list, {:in, Map.values(S.services())}}]},
# required: true,
# doc: "Foreign Plugin sources installed as part of the mix project. Passed in from mix.exs"
# ],
services: [
type: {:or, [{:in, [:all]}, {:list, {:in, Map.keys(S.services())}}]},
default: :all,
Expand Down
21 changes: 17 additions & 4 deletions lib/stampede/events/response_to_post.ex
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,25 @@ defmodule Stampede.Events.ResponseToPost do
@doc "makes a new ResponseToPost but automatically tags the source module unless already being tagged"
defmacro new(keys) do
quote do
struct!(
unquote(__MODULE__),
Keyword.put_new(unquote(keys), :origin_plug, __MODULE__)
)
unquote(keys)
|> Keyword.put_new(:origin_plug, __MODULE__)
|> unquote(__MODULE__).new_bare()
end
end

def new_bare(keys) do
struct!(
__MODULE__,
keys
)
end

# friendly reminder to admire the macros from afar, they are charming but they have teeth and a taste for blood

# # TODO: logic for importing from Python/JSON/etc to actual elixir structs. this might just be too complex a task.
# def foreign_import(dict, overrides = []) do
# rules = [
# {:confidence, &(is_number(&1) || raise())}
# ]
# end
end
Loading