From 8de3a11c8a4f1e60a82e8a4d36959568a0950b68 Mon Sep 17 00:00:00 2001 From: Guilherme Andrade Date: Sat, 28 Oct 2023 18:37:48 +0100 Subject: [PATCH] Add retrocompatibility with as far as Elixir 1.7 and OTP 21.3 Beyond that, the cost becomes too high (no __STACKTRACE__, no persistent term, etc.) Besides, with Elixir 1.7 having been released in 2018, I think this is a very nice addition already. --- .github/workflows/ci.yml | 13 +++++-- .../elixir_version_to_otp_version.json | 5 +++ README.md | 3 +- lib/sqids/alphabet.ex | 15 ++++---- lib/sqids/blocklist.ex | 26 +++++++------- mix.exs | 23 ++++++++++-- scripts/update_blocklist.exs | 36 +++++++++---------- test/sqids_test.exs | 5 +++ 8 files changed, 80 insertions(+), 46 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f0ac5a..79d0418 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,8 @@ on: workflow_dispatch: # enables "click to run" button env: - HIGHEST_ELIXIR_VERSION_IN_MATRIX: '1.15' + ELIXIR_VERSION_ON_WHICH_TO_CHECK_STYLE: '1.15' # Should be highest in matrix + ELIXIR_VERSIONS_ON_WHICH_TO_RUN_DIALYZER: "['1.12', '1.13', '1.14', '1.15']" jobs: ci: @@ -23,6 +24,11 @@ jobs: strategy: matrix: elixir_vsn: [ + '1.7', + '1.8', + '1.9', + '1.10', + '1.11', '1.12', '1.13', '1.14', @@ -77,17 +83,18 @@ jobs: run: mix do deps.get, deps.clean --unused - name: Assert code is formatted - if: ${{matrix.elixir_vsn == env.HIGHEST_ELIXIR_VERSION_IN_MATRIX}} + if: ${{matrix.elixir_vsn == env.ELIXIR_VERSION_ON_WHICH_TO_CHECK_STYLE}} run: mix format --check-formatted - name: Run Credo - if: ${{matrix.elixir_vsn == env.HIGHEST_ELIXIR_VERSION_IN_MATRIX}} + if: ${{matrix.elixir_vsn == env.ELIXIR_VERSION_ON_WHICH_TO_CHECK_STYLE}} run: mix credo --strict - name: Run tests run: mix test --cover - name: Run Dialyzer + if: ${{contains(fromJson(env.ELIXIR_VERSIONS_ON_WHICH_TO_RUN_DIALYZER), matrix.elixir_vsn)}} run: MIX_ENV=test mix dialyzer - name: Save build artifacts to cache diff --git a/.github/workflows/elixir_version_to_otp_version.json b/.github/workflows/elixir_version_to_otp_version.json index 718cad7..aeb2800 100644 --- a/.github/workflows/elixir_version_to_otp_version.json +++ b/.github/workflows/elixir_version_to_otp_version.json @@ -1,4 +1,9 @@ { + "1.7": "21.3", + "1.8": "22.3", + "1.9": "22.3", + "1.10": "23.3", + "1.11": "24.3", "1.12": "24.3", "1.13": "25.3", "1.14": "26.1", diff --git a/README.md b/README.md index d64491e..1c0847e 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,8 @@ [![](https://img.shields.io/hexpm/v/sqids.svg?style=flat)](https://hex.pm/packages/sqids) [![](https://github.com/sqids/sqids-elixir/actions/workflows/ci.yml/badge.svg)](https://github.com/sqids/sqids-elixir/actions/workflows/ci.yml) -[![Elixir Versions](https://img.shields.io/badge/Compatible%20with%20Elixir-1.12%20to%201.15-blue)](https://elixir-lang.org/) +[![Elixir Versions](https://img.shields.io/badge/Compatible%20with%20Elixir-1.7%20to%201.15-blue)](https://elixir-lang.org/) +[![Erlang Versions](https://img.shields.io/badge/Supported%20Erlang%2FOTP-21.3%20to%2026-blue)](https://www.erlang.org) [Sqids](https://sqids.org/elixir) (*pronounced "squids"*) for Elixir is a diff --git a/lib/sqids/alphabet.ex b/lib/sqids/alphabet.ex index ac6517b..7dcdfb1 100644 --- a/lib/sqids/alphabet.ex +++ b/lib/sqids/alphabet.ex @@ -1,6 +1,6 @@ defmodule Sqids.Alphabet do @moduledoc false - # import ExUnit.Assertions + import ExUnit.Assertions @min_alphabet_length 3 @@ -106,13 +106,12 @@ defmodule Sqids.Alphabet do @spec index_of!(t(), byte) :: index def index_of!(%{} = alphabet, char) do # It would be nice to optimize this. - alphabet - |> Enum.find_value(fn {index, byte} -> - byte == char and index - end) - |> then(fn index when index != nil -> - index - end) + + index = + Enum.find_value(alphabet, fn {index, byte} -> byte == char and index end) + + assert index !== nil + index end ## Internal diff --git a/lib/sqids/blocklist.ex b/lib/sqids/blocklist.ex index d811e5f..3f3f769 100644 --- a/lib/sqids/blocklist.ex +++ b/lib/sqids/blocklist.ex @@ -72,19 +72,19 @@ defmodule Sqids.Blocklist do alphabet_graphemes_downcased = alphabet_str |> String.downcase() |> String.graphemes() |> MapSet.new() sort_fun = fn word -> {String.length(word), word} end - words - |> Enum.uniq() - |> Enum.reduce( - _acc0 = %__MODULE__{min_word_length: min_word_length}, - &maybe_add_blocklist_entry(&1, &2, alphabet_graphemes_downcased) - ) - |> then(fn blocklist -> - %{ - blocklist - | prefixes_and_suffixes: Enum.sort_by(blocklist.prefixes_and_suffixes, sort_fun), - matches_anywhere: Enum.sort_by(blocklist.matches_anywhere, sort_fun) - } - end) + blocklist = + words + |> Enum.uniq() + |> Enum.reduce( + _acc0 = %__MODULE__{min_word_length: min_word_length}, + &maybe_add_blocklist_entry(&1, &2, alphabet_graphemes_downcased) + ) + + %{ + blocklist + | prefixes_and_suffixes: Enum.sort_by(blocklist.prefixes_and_suffixes, sort_fun), + matches_anywhere: Enum.sort_by(blocklist.matches_anywhere, sort_fun) + } end @spec maybe_add_blocklist_entry(String.t(), t(), MapSet.t(String.grapheme())) :: t() diff --git a/mix.exs b/mix.exs index 2582f4f..1edc6fb 100644 --- a/mix.exs +++ b/mix.exs @@ -7,7 +7,7 @@ defmodule Sqids.MixProject do [ app: :sqids, version: "0.1.0", - elixir: "~> 1.12", + elixir: "~> 1.7", start_permanent: Mix.env() == :prod, deps: deps(), elixirc_paths: elixirc_paths(Mix.env()), @@ -27,6 +27,7 @@ defmodule Sqids.MixProject do threshold: 94 ] ], + dialyzer: [plt_add_apps: [:ex_unit]], package: package() ] end @@ -34,16 +35,32 @@ defmodule Sqids.MixProject do # Run "mix help deps" to learn about dependencies. defp deps do List.flatten([ - {:credo, "~> 1.7", only: [:dev, :test], runtime: false}, - {:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false}, {:ex_doc, "~> 0.30", only: :dev, runtime: false}, {:recon, "~> 2.5", only: [:dev, :test], runtime: false}, {:sqids_blocklist, github: "sqids/sqids-blocklist", branch: "main", only: :dev, runtime: false, app: false, compile: false}, + maybe_credo_dep(), + maybe_dialyxir_dep(), maybe_styler_dep() ]) end + defp maybe_credo_dep do + if Version.match?(System.version(), "~> 1.12") do + {:credo, "~> 1.7", only: [:dev, :test], runtime: false} + else + [] + end + end + + defp maybe_dialyxir_dep do + if Version.match?(System.version(), "~> 1.12") do + {:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false} + else + [] + end + end + defp maybe_styler_dep do if Version.match?(System.version(), "~> 1.14") do {:styler, "~> 0.8", only: [:dev, :test], runtime: false} diff --git a/scripts/update_blocklist.exs b/scripts/update_blocklist.exs index 9c7265a..135270e 100755 --- a/scripts/update_blocklist.exs +++ b/scripts/update_blocklist.exs @@ -35,24 +35,24 @@ defmodule Sqids.BlocklistUpdater do defp convert_from_canonical_list do log_step("Converting canonical blocklist...") - @path_of_canonical_json - |> File.read!() - |> Jason.decode!() - |> :lists.usort() - |> Enum.reduce( - _acc0 = "", - fn word, acc -> - refute match?( - {true, _}, - {String.contains?(word, ["\n", "\r"]), word} - ) - - [acc, word, "\n"] - end - ) - |> then(fn blocklist -> - File.write!(@path_of_txt_copy, blocklist) - end) + blocklist = + @path_of_canonical_json + |> File.read!() + |> Jason.decode!() + |> :lists.usort() + |> Enum.reduce( + _acc0 = "", + fn word, acc -> + refute match?( + {true, _}, + {String.contains?(word, ["\n", "\r"]), word} + ) + + [acc, word, "\n"] + end + ) + + File.write!(@path_of_txt_copy, blocklist) end defp maybe_update_changelog do diff --git a/test/sqids_test.exs b/test/sqids_test.exs index 3b7b009..9c1cba9 100644 --- a/test/sqids_test.exs +++ b/test/sqids_test.exs @@ -1,10 +1,14 @@ defmodule SqidsTest do # doctest Sqids + require Bitwise + ## Shared between test cases defmodule Shared do + @moduledoc false defmodule UsingModule do + @moduledoc false use Sqids end @@ -53,6 +57,7 @@ defmodule SqidsTest do def assert_encode_and_back(sqids, numbers) do import ExUnit.Assertions + assert decode!(sqids, encode!(sqids, numbers)) === numbers end