aboutsummaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorSoispha <soispha@vhack.eu>2023-12-09 18:20:18 +0100
committerSoispha <soispha@vhack.eu>2023-12-09 18:20:18 +0100
commitb6302ae731f9d438f4e59f62d04903df79d4c942 (patch)
tree1b49245fe4e755d2fa4708de5e02b04ee1064605 /sys
parentbuild(treewide): Update (diff)
downloadnixos-config-b6302ae731f9d438f4e59f62d04903df79d4c942.zip
feat(treewide): Specify nvim plugins in my flake
Diffstat (limited to 'sys')
-rw-r--r--sys/nixpkgs/default.nix3
-rw-r--r--sys/nixpkgs/pkgs/default.nix4
-rw-r--r--sys/nixpkgs/pkgs/plgs-pkgs/README.md94
-rw-r--r--sys/nixpkgs/pkgs/plgs-pkgs/check.nix37
-rw-r--r--sys/nixpkgs/pkgs/plgs-pkgs/default.nix15
-rw-r--r--sys/nixpkgs/pkgs/plgs-pkgs/overrides.nix251
-rw-r--r--sys/nixpkgs/pkgs/plgs-pkgs/plugins/.plugins.json6
-rw-r--r--sys/nixpkgs/pkgs/plgs-pkgs/plugins/blacklist.txt1
-rw-r--r--sys/nixpkgs/pkgs/plgs-pkgs/plugins/default.nix55
-rw-r--r--sys/nixpkgs/pkgs/plgs-pkgs/plugins/manifest.txt3
-rw-r--r--sys/nixpkgs/pkgs/plgs-pkgs/plugins/plugins.md7
-rw-r--r--sys/nixpkgs/pkgs/plgs-pkgs/plugins/whitelist.txt0
-rwxr-xr-xsys/nixpkgs/pkgs/plgs-pkgs/update_neovim_plugins26
-rw-r--r--sys/nixpkgs/pkgs/snap-sync-forked/default.nix4
-rwxr-xr-xsys/nixpkgs/pkgs/update_vim_plugins/check-duplicates.sh49
-rw-r--r--sys/nixpkgs/pkgs/update_vim_plugins/default.nix17
-rw-r--r--sys/nixpkgs/pkgs/update_vim_plugins/package.nix47
-rw-r--r--sys/nixpkgs/pkgs/update_vim_plugins/poetry.lock838
-rw-r--r--sys/nixpkgs/pkgs/update_vim_plugins/pyproject.toml45
-rw-r--r--sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/__init__.py0
-rw-r--r--sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/__main__.py15
-rw-r--r--sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/cleanup.py100
-rw-r--r--sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/helpers.py61
-rw-r--r--sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/nix.py121
-rw-r--r--sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/plugin.py182
-rw-r--r--sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/spec.py143
-rw-r--r--sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/tests/__init__.py0
-rw-r--r--sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/tests/fixtures.py44
-rw-r--r--sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/tests/test_nix.py34
-rw-r--r--sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/tests/test_plugin.py146
-rw-r--r--sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/tests/test_spec.py136
-rw-r--r--sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/update.py212
32 files changed, 2691 insertions, 5 deletions
diff --git a/sys/nixpkgs/default.nix b/sys/nixpkgs/default.nix
index da3a33e6..4fddbd20 100644
--- a/sys/nixpkgs/default.nix
+++ b/sys/nixpkgs/default.nix
@@ -12,8 +12,7 @@ in {
overlays = complete_overlays;
config = {
# TODO: this fails because of the root tempsize, which should be increased
-
- #contentAddressedByDefault = true;
+ # contentAddressedByDefault = true;
allowUnfreePredicate = pkg:
builtins.elem (lib.getName pkg) [
diff --git a/sys/nixpkgs/pkgs/default.nix b/sys/nixpkgs/pkgs/default.nix
index b057068c..8a0898f1 100644
--- a/sys/nixpkgs/pkgs/default.nix
+++ b/sys/nixpkgs/pkgs/default.nix
@@ -1,5 +1,7 @@
{sysLib}: let
snap-sync-forked = (import ./snap-sync-forked) {inherit sysLib;};
- overlays = [] ++ snap-sync-forked;
+ nvim_plugs = import ./plgs-pkgs;
+ update_vim_plugins = import ./update_vim_plugins;
+ overlays = [] ++ snap-sync-forked ++ nvim_plugs ++ update_vim_plugins;
in
overlays
diff --git a/sys/nixpkgs/pkgs/plgs-pkgs/README.md b/sys/nixpkgs/pkgs/plgs-pkgs/README.md
new file mode 100644
index 00000000..ed05f4b2
--- /dev/null
+++ b/sys/nixpkgs/pkgs/plgs-pkgs/README.md
@@ -0,0 +1,94 @@
+# Fork
+All files in this repository where forked form [here](https://github.com/NixNeovim/NixNeovimPlugins) on commit `5010b91eb03696574c3c293f072a090618227e87`.
+Below the original README. They were licensed under the MIT license.
+# All vim plugins, ready to go
+
+This repo auto generates nix packages for vim/neovim plugins.
+Packages are automatically updated twice per week using a GitHub Actions.
+Plugins are fetched from the `manifest.txt` and [awesome-neovim][0] repo.
+
+This is a fork of [this repo](https://github.com/m15a/nixpkgs-vim-extra-plugins); however, we fetch all additions from the original repo, so we will never have less plugins.
+Further, the original deletes plugins that are available in the nixpkgs. We, instead, try to assemble a list of all available plugins.
+Therefore, to access plugins you will never have to search in two places.
+
+This repo can be used as a stand-alone, by adding it to your inputs.
+However, we recommend to use [NixNeovim](https://github.com/NixNeovim/NixNeovim) modules instead, and use this only when you need a plugins, which does not have a module, yet.
+
+## Available plugins
+
+The [plugins.md](plugins.md) contains an auto-generated list of all available plugins.
+
+## Usage
+
+- We recommend using [NixNeovim](https://github.com/NixNeovim/NixNeovim), and only access the plugins directly when they do not have a module in NixNeovim.
+
+However, you can also use this repo without NixNeovim:
+To access the plugins, you need to add the overlay.
+The overlay adds extra Vim plugins to `pkgs.vimExtraPlugins`.
+First, add this repo to your inputs:
+
+```
+inputs.nixneovimplugins.url = github:jooooscha/nixpkgs-vim-extra-plugins
+```
+
+Next, apply the provided overlay:
+
+```
+nixpkgs.overlays = [
+ inputs.nixneovimplugins.overlays.default
+];
+```
+
+Finally, you can add the packages to your vim/neovim config. For example you can use [NixNeovim](https://github.com/NixNeovim/Nixneovim) or you can add the plugins directly:
+
+```
+ programs.neovim = {
+ plugins = [
+ pkgs.vimExtraPlugins.nvim-colorizer-lua
+ ];
+ }
+```
+
+More info on using neovim with nix can be found here: [NixOS Neovim](https://nixos.wiki/wiki/Neovim)
+
+[0]: https://github.com/rockerBOO/awesome-neovim
+[1]: https://nixos.org/manual/nix/stable/release-notes/rl-2.4.html?highlight=builtins.getFlake#other-features
+[2]: https://nur.nix-community.org/
+[3]: https://nur.nix-community.org/repos/m15a/
+
+
+## Contribution
+
+### How to add a new plugin
+
+#### 1. Add the plugin to manifest.txt:
+
+```
+# Examples
+
+haringsrob/nvim_context_vt
+sourcehut:henriquehbr/ataraxis.lua
+gitlab:yorickpeterse/nvim-pqf
+williamboman/mason.nvim:45b9a4da776d9fb017960b3ac7241161fb7bc578
+foo/bar::baz --> renamed to baz
+foo/bar:dev --> using dev branch
+```
+
+Supported are Github (default), SourceHut, and GitLab.
+
+#### 2. Create a Pull Request
+
+- Create a pull request with the changed manifest.txt (and blacklist.txt if neccessary).
+- A GitHub action will check your contribution and generate all neccessary nix code for your new plugin. It will also take care of sorting and cleaning the manifest.txt
+- After all checks have passed, I will merge your change.
+
+I am happy for any contribution. :)
+
+### How to remove a new plugin
+
+Copy the entry from manifest.txt to blacklist.txt and create a PR.
+The GitHub Actions will do the rest, including removing the entry from manifest.txt
+
+## Credits
+
+This is originally based on work by [m15a](https://github.com/m15a/nixpkgs-vim-extra-plugins)
diff --git a/sys/nixpkgs/pkgs/plgs-pkgs/check.nix b/sys/nixpkgs/pkgs/plgs-pkgs/check.nix
new file mode 100644
index 00000000..ad23e2c7
--- /dev/null
+++ b/sys/nixpkgs/pkgs/plgs-pkgs/check.nix
@@ -0,0 +1,37 @@
+{
+ pkgs,
+ lib,
+ ...
+}: let
+ # checks if a plugin has a license
+ hasLicense = _: pkg: let
+ warn = x: lib.warn x x;
+
+ msg =
+ if builtins.hasAttr "license" pkg.meta
+ then "${pkg.name} has license"
+ else warn "${pkg.name} has no license";
+
+ msg' = lib.replaceStrings [" "] ["-"] msg;
+ in
+ pkgs.runCommandNoCC msg' {} "echo : > $out ";
+
+ # function to check License for all packages
+ check-missing-licenses = let
+ buildInputs =
+ lib.mapAttrsToList
+ hasLicense
+ pkgs.vimExtraPlugins;
+ in
+ pkgs.runCommandNoCC
+ "check-missing-licenses"
+ {inherit buildInputs;}
+ "echo : > $out";
+in {
+ checks =
+ pkgs.vimExtraPlugins
+ // {
+ inherit check-missing-licenses;
+ inherit (pkgs) update-vim-plugins;
+ };
+}
diff --git a/sys/nixpkgs/pkgs/plgs-pkgs/default.nix b/sys/nixpkgs/pkgs/plgs-pkgs/default.nix
new file mode 100644
index 00000000..0f7cd485
--- /dev/null
+++ b/sys/nixpkgs/pkgs/plgs-pkgs/default.nix
@@ -0,0 +1,15 @@
+[
+ (final: prev:
+ prev.lib.composeManyExtensions [
+ (self: super: let
+ origin = import ./plugins {
+ inherit (super.vimUtils) buildVimPlugin;
+ inherit (super) lib fetchurl fetchgit;
+ };
+ in {
+ vimExtraPlugins = super.lib.makeExtensible (_: super.lib.recurseIntoAttrs origin);
+ })
+ ]
+ final
+ prev)
+]
diff --git a/sys/nixpkgs/pkgs/plgs-pkgs/overrides.nix b/sys/nixpkgs/pkgs/plgs-pkgs/overrides.nix
new file mode 100644
index 00000000..c4a32026
--- /dev/null
+++ b/sys/nixpkgs/pkgs/plgs-pkgs/overrides.nix
@@ -0,0 +1,251 @@
+final: prev: let
+ inherit (final) lib;
+
+ /*
+ * Mark broken packages here.
+ */
+ markBrokenPackages = self: super:
+ lib.mapAttrs (attrName: broken:
+ super.${attrName}.overrideAttrs (old: {
+ meta = old.meta // {inherit broken;};
+ }))
+ {
+ go-nvim = true;
+
+ highlight-current-n-nvim = true;
+
+ snippet-converter-nvim = true;
+
+ vacuumline-nvim = true;
+
+ vgit-nvim = true;
+
+ unruly-worker = true;
+ };
+
+ /*
+ * Add licenses if missing or incorrect in generated ./pkgs/vim-plugins.nix.
+ */
+ fixLicenses = self: super:
+ lib.mapAttrs (attrName: license:
+ super.${attrName}.overrideAttrs (old: {
+ meta = old.meta // {inherit license;};
+ })) (with lib.licenses; {
+ ariake-vim-colors = [mit];
+
+ bats-vim = [vim];
+
+ christmas-vim = [mit];
+
+ coc-tailwind-intellisense = [mit];
+
+ distant-nvim = [asl20 mit];
+
+ goimpl-nvim = [mit];
+
+ null-ls-nvim = [publicDomain];
+
+ nvim-base16-lua = [mit];
+
+ nvim-cartographer = [gpl3Plus];
+
+ nvim-deus = [gpl3Plus];
+
+ nvim-pqf = [mpl20];
+
+ nvim-remote-containers = [
+ rec {
+ shortName = fullName;
+ fullName = "jamestthompson3's modified MIT License";
+ url = "https://github.com/jamestthompson3/nvim-remote-containers/blob/master/LICENSE";
+ free = true;
+ redistributable = true;
+ deprecated = false;
+ }
+ ];
+
+ nvim-revJ-lua = [vim];
+
+ nvim-srcerite = [gpl3Plus];
+
+ nvim-window = [mpl20];
+
+ osc-nvim = [mit];
+
+ vim-emacscommandline = [vim];
+
+ vim-hy = [vim];
+
+ vim-textobj-indent = [mit];
+
+ vim-textobj-parameter = [mit];
+ });
+
+ # /*
+ # * Add dependencies to vim plugins if missing or incorrect in generated ./pkgs/vim-plugins.nix.
+ # */
+ # fixDependencies = self: super:
+ # lib.mapAttrs (attrName: dependencies: super.${attrName}.overrideAttrs (_: {
+ # inherit dependencies;
+ # })) (with final.vimPlugins;
+ # {
+ # apprentice-nvim = [ lush-nvim ];
+
+ # auto-pandoc-nvim = [ plenary-nvim ];
+
+ # code-runner-nvim = [ plenary-nvim ];
+
+ # codeschool-nvim = [ lush-nvim ];
+
+ # express-line-nvim = [ plenary-nvim ];
+
+ # follow-md-links-nvim = [ nvim-treesitter ];
+
+ # fuzzy-nvim = [ plenary-nvim ];
+
+ # github-colors = [ nvim-treesitter ];
+
+ # gloombuddy = [ colorbuddy-nvim ];
+
+ # go-nvim = [ nvim-treesitter ];
+
+ # goimpl-nvim = [ nvim-treesitter telescope-nvim ];
+
+ # gruvbuddy-nvim = [ colorbuddy-nvim ];
+
+ # gruvy = [ lush-nvim ];
+
+ # jester = [ nvim-treesitter ];
+
+ # lspactions = [ plenary-nvim popup-nvim ];
+
+ # lspactions-nvim06-compatible = [ plenary-nvim popup-nvim self.astronauta-nvim ];
+
+ # navigator-lua = [ nvim-lspconfig self.guihua-lua ];
+
+ # neogen = [ nvim-treesitter ];
+
+ # nlsp-settings-nvim = [ nvim-lspconfig ];
+
+ # nvim-comment-frame = [ nvim-treesitter ];
+
+ # nvim-go = [ plenary-nvim popup-nvim ];
+
+ # nvim-lsp-basics = [ nvim-lspconfig ];
+
+ # nvim-lspfuzzy = [ fzfWrapper ];
+
+ # nvim-lsp-installer = [ nvim-lspconfig ];
+
+ # nvim-lspupdate = [ nvim-lspconfig ];
+
+ # nvim-magic = [ plenary-nvim nui-nvim ];
+
+ # nvim-rdark = [ colorbuddy-nvim ];
+
+ # nvim-revJ-lua = [ self.vim-textobj-parameter ];
+
+ # nvim-spectre = [ plenary-nvim ];
+
+ # nvim-treesitter-textsubjects = [ nvim-treesitter ];
+
+ # nvim-treehopper = [ nvim-treesitter ];
+
+ # nvim-ts-context-commentstring = [ nvim-treesitter ];
+
+ # one-small-step-for-vimkind = [ nvim-dap ];
+
+ # onebuddy = [ colorbuddy-nvim ];
+
+ # reaper-nvim = [ self.osc-nvim ];
+
+ # sqls-nvim = [ nvim-lspconfig ];
+
+ # startup-nvim = [ telescope-nvim ];
+
+ # tabline-framework-nvim = [ nvim-web-devicons ];
+
+ # tabout-nvim = [ nvim-treesitter ];
+
+ # telescope-bibtex-nvim = [ telescope-nvim ];
+
+ # telescope-command-palette-nvim = [ telescope-nvim ];
+
+ # telescope-heading-nvim = [ telescope-nvim ];
+
+ # telescope-tmuxinator-nvim = [ telescope-nvim ];
+
+ # vacuumline-nvim = [ galaxyline-nvim ];
+
+ # vgit-nvim = [ plenary-nvim ];
+
+ # vim-textobj-parameter = [ vim-textobj-user ];
+
+ # virtual-types-nvim = [ nvim-lspconfig ];
+
+ # yabs-nvim = [ plenary-nvim ];
+
+ # zenbones-nvim = [ lush-nvim ];
+ # });
+
+ /*
+ * Add other overrides here.
+ */
+ otherOverrides = self: super: {
+ feline-nvim = super.feline-nvim.overrideAttrs (old: {
+ patches =
+ (old.patches or [])
+ ++ lib.optionals (lib.versionOlder old.version "2021-12-19") [
+ # https://github.com/famiu/feline.nvim/pull/179
+ (final.fetchpatch {
+ url = "https://github.com/zbirenbaum/feline.nvim/commit/d62d9ec923fe76da27f5ac7000b2a506b035740d.patch";
+ sha256 = "sha256-fLa6za0Srm/gnVPlPgs11+2cxhj7hitgUhlHu2jc2+s=";
+ })
+ ];
+ });
+
+ glow-nvim = super.glow-nvim.overrideAttrs (old: {
+ patches =
+ (old.patches or [])
+ ++ [
+ # https://github.com/ellisonleao/glow.nvim/pull/80
+ (final.fetchpatch {
+ url = "https://github.com/ellisonleao/glow.nvim/pull/80/commits/16a348ffa8022945f735caf708c2bd601b08272c.patch";
+ sha256 = "sha256-fljlBTHcoPjnavF37yoIs3zrZ3+iOX6oQ0e20AKtNI8=";
+ })
+ ];
+ });
+
+ guihua-lua = super.guihua-lua.overrideAttrs (old: {
+ buildPhase = ''
+ (
+ cd lua/fzy
+ make
+ )
+ '';
+ });
+
+ mdeval-nvim = super.mdeval-nvim.overrideAttrs (old: {
+ postPatch =
+ (old.postPatch or "")
+ + ''
+ sed -Ei lua/mdeval.lua \
+ -e 's@(get_command\(string\.format\(")mkdir@\1${final.coreutils}/bin/mkdir@' \
+ -e 's@(get_command\(string\.format\(")rm@\1${final.coreutils}/bin/rm@' \
+ -e 's@(2>&1; )echo@\1${final.coreutils}/bin/echo@'
+ '';
+ });
+
+ nvim-papadark = self.themer-lua;
+
+ feline-nvim-develop = self.feline-nvim;
+ };
+in {
+ vimExtraPlugins = prev.vimExtraPlugins.extend (lib.composeManyExtensions [
+ markBrokenPackages
+ fixLicenses
+ fixDependencies
+ # onceHereButNowOfficiallyMaintainedPlugins
+ otherOverrides
+ ]);
+}
diff --git a/sys/nixpkgs/pkgs/plgs-pkgs/plugins/.plugins.json b/sys/nixpkgs/pkgs/plgs-pkgs/plugins/.plugins.json
new file mode 100644
index 00000000..46df05f9
--- /dev/null
+++ b/sys/nixpkgs/pkgs/plgs-pkgs/plugins/.plugins.json
@@ -0,0 +1,6 @@
+{
+ "akinsho/toggleterm.nvim": "{\"description\": \"A neovim lua plugin to help easily manage multiple terminal windows\", \"homepage\": \"https://github.com/akinsho/toggleterm.nvim\", \"license\": {\"py/reduce\": [{\"py/type\": \"update_vim_plugins.nix.License\"}, {\"py/tuple\": [\"gpl3Only\"]}]}, \"name\": \"toggleterm-nvim\", \"owner\": \"akinsho\", \"py/object\": \"update_vim_plugins.plugin.GitHubPlugin\", \"source\": {\"py/object\": \"update_vim_plugins.nix.UrlSource\", \"sha256\": \"0nx69q9597vy7lzvvh58fnjyin23ns6apmyp532sgf547bw7mld6\", \"url\": \"https://github.com/akinsho/toggleterm.nvim/archive/cbd041d91b90cd3c02df03fe6133208888f8e008.tar.gz\"}, \"source_line\": \"akinsho/toggleterm.nvim\", \"version\": {\"__reduce__\": [{\"py/type\": \"datetime.date\"}, [\"B+cMBg==\"]], \"py/object\": \"datetime.date\"}}",
+ "andrewferrier/debugprint.nvim": "{\"description\": \"Debugging in NeoVim the print() way!\", \"homepage\": \"https://github.com/andrewferrier/debugprint.nvim\", \"license\": {\"py/reduce\": [{\"py/type\": \"update_vim_plugins.nix.License\"}, {\"py/tuple\": [\"\"]}]}, \"name\": \"debugprint-nvim\", \"owner\": \"andrewferrier\", \"py/object\": \"update_vim_plugins.plugin.GitHubPlugin\", \"source\": {\"py/object\": \"update_vim_plugins.nix.UrlSource\", \"sha256\": \"12xp4ziray4piynjgwbgdbylday20sdfxslq24h0c3ihdy8wf7ij\", \"url\": \"https://github.com/andrewferrier/debugprint.nvim/archive/8a6d66bd6162e9c49804e9286a7d4ceba60355d5.tar.gz\"}, \"source_line\": \"andrewferrier/debugprint.nvim\", \"version\": {\"__reduce__\": [{\"py/type\": \"datetime.date\"}, [\"B+cLHA==\"]], \"py/object\": \"datetime.date\"}}",
+ "lmburns/lf.nvim": "{\"description\": \"Lf file manager for Neovim (in Lua)\", \"homepage\": \"https://github.com/lmburns/lf.nvim\", \"license\": {\"py/reduce\": [{\"py/type\": \"update_vim_plugins.nix.License\"}, {\"py/tuple\": [\"mit\"]}]}, \"name\": \"lf-nvim\", \"owner\": \"lmburns\", \"py/object\": \"update_vim_plugins.plugin.GitHubPlugin\", \"source\": {\"py/object\": \"update_vim_plugins.nix.UrlSource\", \"sha256\": \"1nwf90bnzqhlgs007gg6xpx0vf4r1d19586nld78ipi1ch7nz4px\", \"url\": \"https://github.com/lmburns/lf.nvim/archive/69ab1efcffee6928bf68ac9bd0c016464d9b2c8b.tar.gz\"}, \"source_line\": \"lmburns/lf.nvim\", \"version\": {\"__reduce__\": [{\"py/type\": \"datetime.date\"}, [\"B+cKAw==\"]], \"py/object\": \"datetime.date\"}}",
+ "nvim-telescope/telescope-bibtex.nvim": "{\"description\": \"A telescope.nvim extension to search and paste bibtex entries into your TeX files.\", \"homepage\": \"https://github.com/nvim-telescope/telescope-bibtex.nvim\", \"license\": {\"py/reduce\": [{\"py/type\": \"update_vim_plugins.nix.License\"}, {\"py/tuple\": [\"mit\"]}]}, \"name\": \"telescope-bibtex-nvim\", \"owner\": \"nvim-telescope\", \"py/object\": \"update_vim_plugins.plugin.GitHubPlugin\", \"source\": {\"py/object\": \"update_vim_plugins.nix.UrlSource\", \"sha256\": \"1vllzdh9ammsfr76mg3brl540b3i6197v8bbgi0lj7s95qy9mj5y\", \"url\": \"https://github.com/nvim-telescope/telescope-bibtex.nvim/archive/b10ec78df938a1e06217f965b32fb1b960681cff.tar.gz\"}, \"source_line\": \"nvim-telescope/telescope-bibtex.nvim\", \"version\": {\"__reduce__\": [{\"py/type\": \"datetime.date\"}, [\"B+cLFA==\"]], \"py/object\": \"datetime.date\"}}"
+} \ No newline at end of file
diff --git a/sys/nixpkgs/pkgs/plgs-pkgs/plugins/blacklist.txt b/sys/nixpkgs/pkgs/plgs-pkgs/plugins/blacklist.txt
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/sys/nixpkgs/pkgs/plgs-pkgs/plugins/blacklist.txt
@@ -0,0 +1 @@
+
diff --git a/sys/nixpkgs/pkgs/plgs-pkgs/plugins/default.nix b/sys/nixpkgs/pkgs/plgs-pkgs/plugins/default.nix
new file mode 100644
index 00000000..0d798d3e
--- /dev/null
+++ b/sys/nixpkgs/pkgs/plgs-pkgs/plugins/default.nix
@@ -0,0 +1,55 @@
+{
+ lib,
+ buildVimPlugin,
+ fetchurl,
+ fetchgit,
+}: {
+ /*
+ Generated from: andrewferrier/debugprint.nvim
+ */
+ debugprint-nvim = buildVimPlugin {
+ pname = "debugprint-nvim";
+ version = "2023-11-28";
+ src = fetchurl {
+ url = "https://github.com/andrewferrier/debugprint.nvim/archive/8a6d66bd6162e9c49804e9286a7d4ceba60355d5.tar.gz";
+ sha256 = "12xp4ziray4piynjgwbgdbylday20sdfxslq24h0c3ihdy8wf7ij";
+ };
+ meta = with lib; {
+ description = "Debugging in NeoVim the print() way!";
+ homepage = "https://github.com/andrewferrier/debugprint.nvim";
+ license = with licenses; [];
+ };
+ };
+ /*
+ Generated from: lmburns/lf.nvim
+ */
+ lf-nvim = buildVimPlugin {
+ pname = "lf-nvim";
+ version = "2023-10-03";
+ src = fetchurl {
+ url = "https://github.com/lmburns/lf.nvim/archive/69ab1efcffee6928bf68ac9bd0c016464d9b2c8b.tar.gz";
+ sha256 = "1nwf90bnzqhlgs007gg6xpx0vf4r1d19586nld78ipi1ch7nz4px";
+ };
+ meta = with lib; {
+ description = "Lf file manager for Neovim (in Lua)";
+ homepage = "https://github.com/lmburns/lf.nvim";
+ license = with licenses; [mit];
+ };
+ };
+ /*
+ Generated from: nvim-telescope/telescope-bibtex.nvim
+ */
+ telescope-bibtex-nvim = buildVimPlugin {
+ pname = "telescope-bibtex-nvim";
+ version = "2023-11-20";
+ src = fetchurl {
+ url = "https://github.com/nvim-telescope/telescope-bibtex.nvim/archive/b10ec78df938a1e06217f965b32fb1b960681cff.tar.gz";
+ sha256 = "1vllzdh9ammsfr76mg3brl540b3i6197v8bbgi0lj7s95qy9mj5y";
+ };
+ meta = with lib; {
+ description = "A telescope.nvim extension to search and paste bibtex entries into your TeX files.";
+ homepage = "https://github.com/nvim-telescope/telescope-bibtex.nvim";
+ license = with licenses; [mit];
+ };
+ };
+}
diff --git a/sys/nixpkgs/pkgs/plgs-pkgs/plugins/manifest.txt b/sys/nixpkgs/pkgs/plgs-pkgs/plugins/manifest.txt
new file mode 100644
index 00000000..86df059f
--- /dev/null
+++ b/sys/nixpkgs/pkgs/plgs-pkgs/plugins/manifest.txt
@@ -0,0 +1,3 @@
+andrewferrier/debugprint.nvim
+lmburns/lf.nvim
+nvim-telescope/telescope-bibtex.nvim
diff --git a/sys/nixpkgs/pkgs/plgs-pkgs/plugins/plugins.md b/sys/nixpkgs/pkgs/plgs-pkgs/plugins/plugins.md
new file mode 100644
index 00000000..73653272
--- /dev/null
+++ b/sys/nixpkgs/pkgs/plgs-pkgs/plugins/plugins.md
@@ -0,0 +1,7 @@
+ - Plugin count: 3
+
+| Repo | Last Update | Nix package name | Last checked |
+|:---|:---|:---|:---|
+| [andrewferrier/debugprint.nvim](https://github.com/andrewferrier/debugprint.nvim) | 2023-11-28 | `debugprint-nvim` | 2023-12-09 |
+| [lmburns/lf.nvim](https://github.com/lmburns/lf.nvim) | 2023-10-03 | `lf-nvim` | 2023-12-09 |
+| [nvim-telescope/telescope-bibtex.nvim](https://github.com/nvim-telescope/telescope-bibtex.nvim) | 2023-11-20 | `telescope-bibtex-nvim` | 2023-12-09 |
diff --git a/sys/nixpkgs/pkgs/plgs-pkgs/plugins/whitelist.txt b/sys/nixpkgs/pkgs/plgs-pkgs/plugins/whitelist.txt
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/sys/nixpkgs/pkgs/plgs-pkgs/plugins/whitelist.txt
diff --git a/sys/nixpkgs/pkgs/plgs-pkgs/update_neovim_plugins b/sys/nixpkgs/pkgs/plgs-pkgs/update_neovim_plugins
new file mode 100755
index 00000000..ea71c6fa
--- /dev/null
+++ b/sys/nixpkgs/pkgs/plgs-pkgs/update_neovim_plugins
@@ -0,0 +1,26 @@
+#!/usr/bin/env sh
+
+BASE_DIR="$(readlink -f "$(dirname "$0")/plugins")"
+
+# Fetch plugins
+cd "$BASE_DIR" || (echo "BUG: No '$BASE_DIR'" && exit 1)
+
+# Cleanup manifest
+sort -o "$BASE_DIR/manifest.txt" "$BASE_DIR/manifest.txt"
+sort -o "$BASE_DIR/blacklist.txt" "$BASE_DIR/blacklist.txt"
+## Remove all plugins, which are on the blacklist
+echo "$(comm -23 "$BASE_DIR/manifest.txt" "$BASE_DIR/blacklist.txt")" > "$BASE_DIR/manifest.txt"
+
+# Backup vim-plugins.nix
+mv "$BASE_DIR/default.nix" "$BASE_DIR/default.nix.bak"
+echo "{...} : {}" > "$BASE_DIR/default.nix"
+
+# Generate derivations for new plugins (this binary is provided by the dev-environment)
+update-vim-plugins cleanup "$BASE_DIR"
+
+# Restore vim-plugins.nix
+mv "$BASE_DIR/default.nix.bak" "$BASE_DIR/default.nix"
+
+
+# Update new plugins
+update-vim-plugins update "$BASE_DIR" --all
diff --git a/sys/nixpkgs/pkgs/snap-sync-forked/default.nix b/sys/nixpkgs/pkgs/snap-sync-forked/default.nix
index 55e2bd27..f110a4fa 100644
--- a/sys/nixpkgs/pkgs/snap-sync-forked/default.nix
+++ b/sys/nixpkgs/pkgs/snap-sync-forked/default.nix
@@ -1,9 +1,9 @@
{sysLib}: [
- (self: super: {
+ (final: prev: {
snap-sync-forked = sysLib.writeShellScriptWithLibrary {
name = "snap-sync-forked";
src = ./snap-sync-forked;
- dependencies = with self; [
+ dependencies = with prev; [
bash
btrfs-progs
coreutils
diff --git a/sys/nixpkgs/pkgs/update_vim_plugins/check-duplicates.sh b/sys/nixpkgs/pkgs/update_vim_plugins/check-duplicates.sh
new file mode 100755
index 00000000..dcf8b46f
--- /dev/null
+++ b/sys/nixpkgs/pkgs/update_vim_plugins/check-duplicates.sh
@@ -0,0 +1,49 @@
+#!/usr/bin/env bash
+
+plugins="$(grep -E "^ [a-zA-Z-]+ =" ./pkgs/vim-plugins.nix | sed -E 's/^ ([a-zA-Z-]+) =.*$/\1/' | sort)"
+count=$(echo "$plugins" | uniq -d | wc -l)
+
+echo "duplicates count: $count"
+
+if [ "$count" -gt 0 ]
+then
+ filtered_plugins=$(echo "$plugins" | uniq -d)
+
+ if [ "$1" == "check-only" ]
+ then
+ echo "$filtered_plugins"
+ exit 1
+ else
+ known_issues=$(gh issue list --state "open" --label "bot" --json "body" | jq -r ".[].body")
+
+ echo "known_issues: $known_issues"
+
+ # iterate over plugins we found missing and
+ # compare them to all open issues.
+ # We no matching issue was found, we create a new one
+ for f in $filtered_plugins # do not add " " here. It would break the plugin
+ do
+ found=false
+
+ for k in $known_issues
+ do
+ if [[ "$f" == "$k" ]]
+ then
+ found=true
+ break
+ fi
+ done
+
+ # test if matching issue was found
+ if ! $found
+ then
+ echo "Did not find an issue for $f. Creating a new one ..."
+ gh issue create --title "Detected broken plugin: $f" --label "bot" --body "$f"
+ else
+ echo "Issue for $f already exists"
+ fi
+ done
+ fi
+else
+ echo "No duplicates found"
+fi
diff --git a/sys/nixpkgs/pkgs/update_vim_plugins/default.nix b/sys/nixpkgs/pkgs/update_vim_plugins/default.nix
new file mode 100644
index 00000000..7f0b3f0d
--- /dev/null
+++ b/sys/nixpkgs/pkgs/update_vim_plugins/default.nix
@@ -0,0 +1,17 @@
+[
+ (
+ final: prev: {
+ update-vim-plugins = import ./package.nix {
+ inherit
+ (prev)
+ python3
+ # dependencies
+
+ nix
+ alejandra
+ nix-prefetch-git
+ ;
+ };
+ }
+ )
+]
diff --git a/sys/nixpkgs/pkgs/update_vim_plugins/package.nix b/sys/nixpkgs/pkgs/update_vim_plugins/package.nix
new file mode 100644
index 00000000..e74a29b1
--- /dev/null
+++ b/sys/nixpkgs/pkgs/update_vim_plugins/package.nix
@@ -0,0 +1,47 @@
+{
+ python3,
+ # dependencies
+ nix,
+ alejandra,
+ nix-prefetch-git,
+}:
+python3.pkgs.buildPythonApplication {
+ pname = "update-vim-plugins";
+ version = "0.1.0";
+ format = "pyproject";
+
+ src = ./.;
+
+ # NOTE: The test are not really meant to work <2023-12-09>
+ doCheck = false;
+
+ nativeBuildInputs = [
+ python3.pkgs.poetry-core
+ ];
+ buildInputs = [
+ alejandra
+ nix-prefetch-git
+ nix
+ ];
+ propagatedBuildInputs = with python3.pkgs; [
+ requests
+ cleo
+ jsonpickle
+ dateparser
+ ];
+ nativeCheckInputs = with python3.pkgs; [
+ pytestCheckHook
+
+ pytest-cov
+ pytest-mock
+ ];
+ pytestFlagsArray = [
+ "--cov"
+ "update_vim_plugins"
+ "--cov-report"
+ "term-missing:skip-covered"
+ "--cov-fail-under"
+ "50"
+ "update_vim_plugins/tests"
+ ];
+}
diff --git a/sys/nixpkgs/pkgs/update_vim_plugins/poetry.lock b/sys/nixpkgs/pkgs/update_vim_plugins/poetry.lock
new file mode 100644
index 00000000..8512035a
--- /dev/null
+++ b/sys/nixpkgs/pkgs/update_vim_plugins/poetry.lock
@@ -0,0 +1,838 @@
+# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand.
+
+[[package]]
+name = "attrs"
+version = "23.1.0"
+description = "Classes Without Boilerplate"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"},
+ {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"},
+]
+
+[package.extras]
+cov = ["attrs[tests]", "coverage[toml] (>=5.3)"]
+dev = ["attrs[docs,tests]", "pre-commit"]
+docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"]
+tests = ["attrs[tests-no-zope]", "zope-interface"]
+tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
+
+[[package]]
+name = "black"
+version = "23.3.0"
+description = "The uncompromising code formatter."
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "black-23.3.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915"},
+ {file = "black-23.3.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9"},
+ {file = "black-23.3.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2"},
+ {file = "black-23.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c"},
+ {file = "black-23.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c"},
+ {file = "black-23.3.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6"},
+ {file = "black-23.3.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b"},
+ {file = "black-23.3.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d"},
+ {file = "black-23.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70"},
+ {file = "black-23.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326"},
+ {file = "black-23.3.0-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b"},
+ {file = "black-23.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2"},
+ {file = "black-23.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925"},
+ {file = "black-23.3.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27"},
+ {file = "black-23.3.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331"},
+ {file = "black-23.3.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5"},
+ {file = "black-23.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961"},
+ {file = "black-23.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8"},
+ {file = "black-23.3.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30"},
+ {file = "black-23.3.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3"},
+ {file = "black-23.3.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266"},
+ {file = "black-23.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab"},
+ {file = "black-23.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb"},
+ {file = "black-23.3.0-py3-none-any.whl", hash = "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4"},
+ {file = "black-23.3.0.tar.gz", hash = "sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940"},
+]
+
+[package.dependencies]
+click = ">=8.0.0"
+mypy-extensions = ">=0.4.3"
+packaging = ">=22.0"
+pathspec = ">=0.9.0"
+platformdirs = ">=2"
+tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
+
+[package.extras]
+colorama = ["colorama (>=0.4.3)"]
+d = ["aiohttp (>=3.7.4)"]
+jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
+uvloop = ["uvloop (>=0.15.2)"]
+
+[[package]]
+name = "cattrs"
+version = "22.2.0"
+description = "Composable complex class support for attrs and dataclasses."
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "cattrs-22.2.0-py3-none-any.whl", hash = "sha256:bc12b1f0d000b9f9bee83335887d532a1d3e99a833d1bf0882151c97d3e68c21"},
+ {file = "cattrs-22.2.0.tar.gz", hash = "sha256:f0eed5642399423cf656e7b66ce92cdc5b963ecafd041d1b24d136fdde7acf6d"},
+]
+
+[package.dependencies]
+attrs = ">=20"
+exceptiongroup = {version = "*", markers = "python_version < \"3.11\""}
+
+[[package]]
+name = "certifi"
+version = "2022.12.7"
+description = "Python package for providing Mozilla's CA Bundle."
+category = "main"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"},
+ {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"},
+]
+
+[[package]]
+name = "charset-normalizer"
+version = "3.1.0"
+description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
+category = "main"
+optional = false
+python-versions = ">=3.7.0"
+files = [
+ {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"},
+ {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"},
+ {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"},
+ {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"},
+ {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"},
+ {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"},
+ {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"},
+]
+
+[[package]]
+name = "cleo"
+version = "2.0.1"
+description = "Cleo allows you to create beautiful and testable command-line interfaces."
+category = "main"
+optional = false
+python-versions = ">=3.7,<4.0"
+files = [
+ {file = "cleo-2.0.1-py3-none-any.whl", hash = "sha256:6eb133670a3ed1f3b052d53789017b6e50fca66d1287e6e6696285f4cb8ea448"},
+ {file = "cleo-2.0.1.tar.gz", hash = "sha256:eb4b2e1f3063c11085cebe489a6e9124163c226575a3c3be69b2e51af4a15ec5"},
+]
+
+[package.dependencies]
+crashtest = ">=0.4.1,<0.5.0"
+rapidfuzz = ">=2.2.0,<3.0.0"
+
+[[package]]
+name = "click"
+version = "8.1.3"
+description = "Composable command line interface toolkit"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
+ {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "platform_system == \"Windows\""}
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+description = "Cross-platform colored terminal text."
+category = "dev"
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+files = [
+ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
+ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
+]
+
+[[package]]
+name = "coverage"
+version = "7.2.3"
+description = "Code coverage measurement for Python"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "coverage-7.2.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e58c0d41d336569d63d1b113bd573db8363bc4146f39444125b7f8060e4e04f5"},
+ {file = "coverage-7.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:344e714bd0fe921fc72d97404ebbdbf9127bac0ca1ff66d7b79efc143cf7c0c4"},
+ {file = "coverage-7.2.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:974bc90d6f6c1e59ceb1516ab00cf1cdfbb2e555795d49fa9571d611f449bcb2"},
+ {file = "coverage-7.2.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0743b0035d4b0e32bc1df5de70fba3059662ace5b9a2a86a9f894cfe66569013"},
+ {file = "coverage-7.2.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d0391fb4cfc171ce40437f67eb050a340fdbd0f9f49d6353a387f1b7f9dd4fa"},
+ {file = "coverage-7.2.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4a42e1eff0ca9a7cb7dc9ecda41dfc7cbc17cb1d02117214be0561bd1134772b"},
+ {file = "coverage-7.2.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:be19931a8dcbe6ab464f3339966856996b12a00f9fe53f346ab3be872d03e257"},
+ {file = "coverage-7.2.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:72fcae5bcac3333a4cf3b8f34eec99cea1187acd55af723bcbd559adfdcb5535"},
+ {file = "coverage-7.2.3-cp310-cp310-win32.whl", hash = "sha256:aeae2aa38395b18106e552833f2a50c27ea0000122bde421c31d11ed7e6f9c91"},
+ {file = "coverage-7.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:83957d349838a636e768251c7e9979e899a569794b44c3728eaebd11d848e58e"},
+ {file = "coverage-7.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dfd393094cd82ceb9b40df4c77976015a314b267d498268a076e940fe7be6b79"},
+ {file = "coverage-7.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:182eb9ac3f2b4874a1f41b78b87db20b66da6b9cdc32737fbbf4fea0c35b23fc"},
+ {file = "coverage-7.2.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bb1e77a9a311346294621be905ea8a2c30d3ad371fc15bb72e98bfcfae532df"},
+ {file = "coverage-7.2.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca0f34363e2634deffd390a0fef1aa99168ae9ed2af01af4a1f5865e362f8623"},
+ {file = "coverage-7.2.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55416d7385774285b6e2a5feca0af9652f7f444a4fa3d29d8ab052fafef9d00d"},
+ {file = "coverage-7.2.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:06ddd9c0249a0546997fdda5a30fbcb40f23926df0a874a60a8a185bc3a87d93"},
+ {file = "coverage-7.2.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:fff5aaa6becf2c6a1699ae6a39e2e6fb0672c2d42eca8eb0cafa91cf2e9bd312"},
+ {file = "coverage-7.2.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ea53151d87c52e98133eb8ac78f1206498c015849662ca8dc246255265d9c3c4"},
+ {file = "coverage-7.2.3-cp311-cp311-win32.whl", hash = "sha256:8f6c930fd70d91ddee53194e93029e3ef2aabe26725aa3c2753df057e296b925"},
+ {file = "coverage-7.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:fa546d66639d69aa967bf08156eb8c9d0cd6f6de84be9e8c9819f52ad499c910"},
+ {file = "coverage-7.2.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b2317d5ed777bf5a033e83d4f1389fd4ef045763141d8f10eb09a7035cee774c"},
+ {file = "coverage-7.2.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be9824c1c874b73b96288c6d3de793bf7f3a597770205068c6163ea1f326e8b9"},
+ {file = "coverage-7.2.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2c3b2803e730dc2797a017335827e9da6da0e84c745ce0f552e66400abdfb9a1"},
+ {file = "coverage-7.2.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f69770f5ca1994cb32c38965e95f57504d3aea96b6c024624fdd5bb1aa494a1"},
+ {file = "coverage-7.2.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1127b16220f7bfb3f1049ed4a62d26d81970a723544e8252db0efde853268e21"},
+ {file = "coverage-7.2.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:aa784405f0c640940595fa0f14064d8e84aff0b0f762fa18393e2760a2cf5841"},
+ {file = "coverage-7.2.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3146b8e16fa60427e03884301bf8209221f5761ac754ee6b267642a2fd354c48"},
+ {file = "coverage-7.2.3-cp37-cp37m-win32.whl", hash = "sha256:1fd78b911aea9cec3b7e1e2622c8018d51c0d2bbcf8faaf53c2497eb114911c1"},
+ {file = "coverage-7.2.3-cp37-cp37m-win_amd64.whl", hash = "sha256:0f3736a5d34e091b0a611964c6262fd68ca4363df56185902528f0b75dbb9c1f"},
+ {file = "coverage-7.2.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:981b4df72c93e3bc04478153df516d385317628bd9c10be699c93c26ddcca8ab"},
+ {file = "coverage-7.2.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c0045f8f23a5fb30b2eb3b8a83664d8dc4fb58faddf8155d7109166adb9f2040"},
+ {file = "coverage-7.2.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f760073fcf8f3d6933178d67754f4f2d4e924e321f4bb0dcef0424ca0215eba1"},
+ {file = "coverage-7.2.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c86bd45d1659b1ae3d0ba1909326b03598affbc9ed71520e0ff8c31a993ad911"},
+ {file = "coverage-7.2.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:172db976ae6327ed4728e2507daf8a4de73c7cc89796483e0a9198fd2e47b462"},
+ {file = "coverage-7.2.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d2a3a6146fe9319926e1d477842ca2a63fe99af5ae690b1f5c11e6af074a6b5c"},
+ {file = "coverage-7.2.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:f649dd53833b495c3ebd04d6eec58479454a1784987af8afb77540d6c1767abd"},
+ {file = "coverage-7.2.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7c4ed4e9f3b123aa403ab424430b426a1992e6f4c8fd3cb56ea520446e04d152"},
+ {file = "coverage-7.2.3-cp38-cp38-win32.whl", hash = "sha256:eb0edc3ce9760d2f21637766c3aa04822030e7451981ce569a1b3456b7053f22"},
+ {file = "coverage-7.2.3-cp38-cp38-win_amd64.whl", hash = "sha256:63cdeaac4ae85a179a8d6bc09b77b564c096250d759eed343a89d91bce8b6367"},
+ {file = "coverage-7.2.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:20d1a2a76bb4eb00e4d36b9699f9b7aba93271c9c29220ad4c6a9581a0320235"},
+ {file = "coverage-7.2.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ea748802cc0de4de92ef8244dd84ffd793bd2e7be784cd8394d557a3c751e21"},
+ {file = "coverage-7.2.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21b154aba06df42e4b96fc915512ab39595105f6c483991287021ed95776d934"},
+ {file = "coverage-7.2.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd214917cabdd6f673a29d708574e9fbdb892cb77eb426d0eae3490d95ca7859"},
+ {file = "coverage-7.2.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c2e58e45fe53fab81f85474e5d4d226eeab0f27b45aa062856c89389da2f0d9"},
+ {file = "coverage-7.2.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:87ecc7c9a1a9f912e306997ffee020297ccb5ea388421fe62a2a02747e4d5539"},
+ {file = "coverage-7.2.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:387065e420aed3c71b61af7e82c7b6bc1c592f7e3c7a66e9f78dd178699da4fe"},
+ {file = "coverage-7.2.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ea3f5bc91d7d457da7d48c7a732beaf79d0c8131df3ab278e6bba6297e23c6c4"},
+ {file = "coverage-7.2.3-cp39-cp39-win32.whl", hash = "sha256:ae7863a1d8db6a014b6f2ff9c1582ab1aad55a6d25bac19710a8df68921b6e30"},
+ {file = "coverage-7.2.3-cp39-cp39-win_amd64.whl", hash = "sha256:3f04becd4fcda03c0160d0da9c8f0c246bc78f2f7af0feea1ec0930e7c93fa4a"},
+ {file = "coverage-7.2.3-pp37.pp38.pp39-none-any.whl", hash = "sha256:965ee3e782c7892befc25575fa171b521d33798132692df428a09efacaffe8d0"},
+ {file = "coverage-7.2.3.tar.gz", hash = "sha256:d298c2815fa4891edd9abe5ad6e6cb4207104c7dd9fd13aea3fdebf6f9b91259"},
+]
+
+[package.dependencies]
+tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""}
+
+[package.extras]
+toml = ["tomli"]
+
+[[package]]
+name = "crashtest"
+version = "0.4.1"
+description = "Manage Python errors with ease"
+category = "main"
+optional = false
+python-versions = ">=3.7,<4.0"
+files = [
+ {file = "crashtest-0.4.1-py3-none-any.whl", hash = "sha256:8d23eac5fa660409f57472e3851dab7ac18aba459a8d19cbbba86d3d5aecd2a5"},
+ {file = "crashtest-0.4.1.tar.gz", hash = "sha256:80d7b1f316ebfbd429f648076d6275c877ba30ba48979de4191714a75266f0ce"},
+]
+
+[[package]]
+name = "exceptiongroup"
+version = "1.1.1"
+description = "Backport of PEP 654 (exception groups)"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"},
+ {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"},
+]
+
+[package.extras]
+test = ["pytest (>=6)"]
+
+[[package]]
+name = "idna"
+version = "3.4"
+description = "Internationalized Domain Names in Applications (IDNA)"
+category = "main"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"},
+ {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
+]
+
+[[package]]
+name = "iniconfig"
+version = "2.0.0"
+description = "brain-dead simple config-ini parsing"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
+ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
+]
+
+[[package]]
+name = "isort"
+version = "5.12.0"
+description = "A Python utility / library to sort Python imports."
+category = "dev"
+optional = false
+python-versions = ">=3.8.0"
+files = [
+ {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"},
+ {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"},
+]
+
+[package.extras]
+colors = ["colorama (>=0.4.3)"]
+pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"]
+plugins = ["setuptools"]
+requirements-deprecated-finder = ["pip-api", "pipreqs"]
+
+[[package]]
+name = "lsprotocol"
+version = "2023.0.0a1"
+description = "Python implementation of the Language Server Protocol."
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "lsprotocol-2023.0.0a1-py3-none-any.whl", hash = "sha256:133c339a7cccb299a5b357f9b8ef6aebe27616e0daf4ba54e63476afe0e12e47"},
+ {file = "lsprotocol-2023.0.0a1.tar.gz", hash = "sha256:32edfd4856abba1349bf5a070567445b3d7286951afba3644b472629796f82d0"},
+]
+
+[package.dependencies]
+attrs = "*"
+cattrs = "*"
+
+[[package]]
+name = "mypy"
+version = "1.2.0"
+description = "Optional static typing for Python"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "mypy-1.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:701189408b460a2ff42b984e6bd45c3f41f0ac9f5f58b8873bbedc511900086d"},
+ {file = "mypy-1.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fe91be1c51c90e2afe6827601ca14353bbf3953f343c2129fa1e247d55fd95ba"},
+ {file = "mypy-1.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d26b513225ffd3eacece727f4387bdce6469192ef029ca9dd469940158bc89e"},
+ {file = "mypy-1.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3a2d219775a120581a0ae8ca392b31f238d452729adbcb6892fa89688cb8306a"},
+ {file = "mypy-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:2e93a8a553e0394b26c4ca683923b85a69f7ccdc0139e6acd1354cc884fe0128"},
+ {file = "mypy-1.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3efde4af6f2d3ccf58ae825495dbb8d74abd6d176ee686ce2ab19bd025273f41"},
+ {file = "mypy-1.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:695c45cea7e8abb6f088a34a6034b1d273122e5530aeebb9c09626cea6dca4cb"},
+ {file = "mypy-1.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0e9464a0af6715852267bf29c9553e4555b61f5904a4fc538547a4d67617937"},
+ {file = "mypy-1.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8293a216e902ac12779eb7a08f2bc39ec6c878d7c6025aa59464e0c4c16f7eb9"},
+ {file = "mypy-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:f46af8d162f3d470d8ffc997aaf7a269996d205f9d746124a179d3abe05ac602"},
+ {file = "mypy-1.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:031fc69c9a7e12bcc5660b74122ed84b3f1c505e762cc4296884096c6d8ee140"},
+ {file = "mypy-1.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:390bc685ec209ada4e9d35068ac6988c60160b2b703072d2850457b62499e336"},
+ {file = "mypy-1.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4b41412df69ec06ab141808d12e0bf2823717b1c363bd77b4c0820feaa37249e"},
+ {file = "mypy-1.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4e4a682b3f2489d218751981639cffc4e281d548f9d517addfd5a2917ac78119"},
+ {file = "mypy-1.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a197ad3a774f8e74f21e428f0de7f60ad26a8d23437b69638aac2764d1e06a6a"},
+ {file = "mypy-1.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c9a084bce1061e55cdc0493a2ad890375af359c766b8ac311ac8120d3a472950"},
+ {file = "mypy-1.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaeaa0888b7f3ccb7bcd40b50497ca30923dba14f385bde4af78fac713d6d6f6"},
+ {file = "mypy-1.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bea55fc25b96c53affab852ad94bf111a3083bc1d8b0c76a61dd101d8a388cf5"},
+ {file = "mypy-1.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:4c8d8c6b80aa4a1689f2a179d31d86ae1367ea4a12855cc13aa3ba24bb36b2d8"},
+ {file = "mypy-1.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:70894c5345bea98321a2fe84df35f43ee7bb0feec117a71420c60459fc3e1eed"},
+ {file = "mypy-1.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4a99fe1768925e4a139aace8f3fb66db3576ee1c30b9c0f70f744ead7e329c9f"},
+ {file = "mypy-1.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:023fe9e618182ca6317ae89833ba422c411469156b690fde6a315ad10695a521"},
+ {file = "mypy-1.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4d19f1a239d59f10fdc31263d48b7937c585810288376671eaf75380b074f238"},
+ {file = "mypy-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:2de7babe398cb7a85ac7f1fd5c42f396c215ab3eff731b4d761d68d0f6a80f48"},
+ {file = "mypy-1.2.0-py3-none-any.whl", hash = "sha256:d8e9187bfcd5ffedbe87403195e1fc340189a68463903c39e2b63307c9fa0394"},
+ {file = "mypy-1.2.0.tar.gz", hash = "sha256:f70a40410d774ae23fcb4afbbeca652905a04de7948eaf0b1789c8d1426b72d1"},
+]
+
+[package.dependencies]
+mypy-extensions = ">=1.0.0"
+tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
+typing-extensions = ">=3.10"
+
+[package.extras]
+dmypy = ["psutil (>=4.0)"]
+install-types = ["pip"]
+python2 = ["typed-ast (>=1.4.0,<2)"]
+reports = ["lxml"]
+
+[[package]]
+name = "mypy-extensions"
+version = "1.0.0"
+description = "Type system extensions for programs checked with the mypy type checker."
+category = "dev"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
+ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
+]
+
+[[package]]
+name = "packaging"
+version = "23.1"
+description = "Core utilities for Python packages"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"},
+ {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"},
+]
+
+[[package]]
+name = "pathspec"
+version = "0.11.1"
+description = "Utility library for gitignore style pattern matching of file paths."
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"},
+ {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"},
+]
+
+[[package]]
+name = "platformdirs"
+version = "3.2.0"
+description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "platformdirs-3.2.0-py3-none-any.whl", hash = "sha256:ebe11c0d7a805086e99506aa331612429a72ca7cd52a1f0d277dc4adc20cb10e"},
+ {file = "platformdirs-3.2.0.tar.gz", hash = "sha256:d5b638ca397f25f979350ff789db335903d7ea010ab28903f57b27e1b16c2b08"},
+]
+
+[package.extras]
+docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"]
+test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
+
+[[package]]
+name = "pluggy"
+version = "1.0.0"
+description = "plugin and hook calling mechanisms for python"
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
+ {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
+]
+
+[package.extras]
+dev = ["pre-commit", "tox"]
+testing = ["pytest", "pytest-benchmark"]
+
+[[package]]
+name = "pygls"
+version = "1.0.1"
+description = "a pythonic generic language server (pronounced like \"pie glass\")."
+category = "dev"
+optional = false
+python-versions = "<4,>=3.7"
+files = [
+ {file = "pygls-1.0.1-py3-none-any.whl", hash = "sha256:adacc96da77598c70f46acfdfd1481d3da90cd54f639f7eee52eb6e4dbd57b55"},
+ {file = "pygls-1.0.1.tar.gz", hash = "sha256:f3ee98ddbb4690eb5c755bc32ba7e129607f14cbd313575f33d0cea443b78cb2"},
+]
+
+[package.dependencies]
+lsprotocol = "*"
+typeguard = ">=2.10.0,<3"
+
+[package.extras]
+dev = ["bandit (==1.7.4)", "flake8 (==4.0.1)", "mypy (==0.961)"]
+docs = ["sphinx (==5.0.1)", "sphinx-rtd-theme (==1.0.0)"]
+test = ["mock (==4.0.3)", "pytest (==7.1.2)", "pytest-asyncio (==0.18.3)"]
+ws = ["websockets (>=10.0.0,<11.0.0)"]
+
+[[package]]
+name = "pytest"
+version = "7.3.1"
+description = "pytest: simple powerful testing with Python"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pytest-7.3.1-py3-none-any.whl", hash = "sha256:3799fa815351fea3a5e96ac7e503a96fa51cc9942c3753cda7651b93c1cfa362"},
+ {file = "pytest-7.3.1.tar.gz", hash = "sha256:434afafd78b1d78ed0addf160ad2b77a30d35d4bdf8af234fe621919d9ed15e3"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
+iniconfig = "*"
+packaging = "*"
+pluggy = ">=0.12,<2.0"
+tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
+
+[package.extras]
+testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
+
+[[package]]
+name = "pytest-cov"
+version = "4.0.0"
+description = "Pytest plugin for measuring coverage."
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "pytest-cov-4.0.0.tar.gz", hash = "sha256:996b79efde6433cdbd0088872dbc5fb3ed7fe1578b68cdbba634f14bb8dd0470"},
+ {file = "pytest_cov-4.0.0-py3-none-any.whl", hash = "sha256:2feb1b751d66a8bd934e5edfa2e961d11309dc37b73b0eabe73b5945fee20f6b"},
+]
+
+[package.dependencies]
+coverage = {version = ">=5.2.1", extras = ["toml"]}
+pytest = ">=4.6"
+
+[package.extras]
+testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"]
+
+[[package]]
+name = "pytest-mock"
+version = "3.10.0"
+description = "Thin-wrapper around the mock package for easier use with pytest"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pytest-mock-3.10.0.tar.gz", hash = "sha256:fbbdb085ef7c252a326fd8cdcac0aa3b1333d8811f131bdcc701002e1be7ed4f"},
+ {file = "pytest_mock-3.10.0-py3-none-any.whl", hash = "sha256:f4c973eeae0282963eb293eb173ce91b091a79c1334455acfac9ddee8a1c784b"},
+]
+
+[package.dependencies]
+pytest = ">=5.0"
+
+[package.extras]
+dev = ["pre-commit", "pytest-asyncio", "tox"]
+
+[[package]]
+name = "rapidfuzz"
+version = "2.15.1"
+description = "rapid fuzzy string matching"
+category = "main"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "rapidfuzz-2.15.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fc0bc259ebe3b93e7ce9df50b3d00e7345335d35acbd735163b7c4b1957074d3"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d59fb3a410d253f50099d7063855c2b95df1ef20ad93ea3a6b84115590899f25"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c525a3da17b6d79d61613096c8683da86e3573e807dfaecf422eea09e82b5ba6"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4deae6a918ecc260d0c4612257be8ba321d8e913ccb43155403842758c46fbe"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2577463d10811386e704a3ab58b903eb4e2a31b24dfd9886d789b0084d614b01"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f67d5f56aa48c0da9de4ab81bffb310683cf7815f05ea38e5aa64f3ba4368339"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d7927722ff43690e52b3145b5bd3089151d841d350c6f8378c3cfac91f67573a"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6534afc787e32c4104f65cdeb55f6abe4d803a2d0553221d00ef9ce12788dcde"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d0ae6ec79a1931929bb9dd57bc173eb5ba4c7197461bf69e3a34b6dd314feed2"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:be7ccc45c4d1a7dfb595f260e8022a90c6cb380c2a346ee5aae93f85c96d362b"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:8ba013500a2b68c64b2aecc5fb56a2dad6c2872cf545a0308fd044827b6e5f6a"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4d9f7d10065f657f960b48699e7dddfce14ab91af4bab37a215f0722daf0d716"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7e24a1b802cea04160b3fccd75d2d0905065783ebc9de157d83c14fb9e1c6ce2"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-win32.whl", hash = "sha256:dffdf03499e0a5b3442951bb82b556333b069e0661e80568752786c79c5b32de"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:7d150d90a7c6caae7962f29f857a4e61d42038cfd82c9df38508daf30c648ae7"},
+ {file = "rapidfuzz-2.15.1-cp310-cp310-win_arm64.whl", hash = "sha256:87c30e9184998ff6eb0fa9221f94282ce7c908fd0da96a1ef66ecadfaaa4cdb7"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6986413cb37035eb796e32f049cbc8c13d8630a4ac1e0484e3e268bb3662bd1b"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a72f26e010d4774b676f36e43c0fc8a2c26659efef4b3be3fd7714d3491e9957"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b5cd54c98a387cca111b3b784fc97a4f141244bbc28a92d4bde53f164464112e"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da7fac7c3da39f93e6b2ebe386ed0ffe1cefec91509b91857f6e1204509e931f"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f976e76ac72f650790b3a5402431612175b2ac0363179446285cb3c901136ca9"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:abde47e1595902a490ed14d4338d21c3509156abb2042a99e6da51f928e0c117"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca8f1747007a3ce919739a60fa95c5325f7667cccf6f1c1ef18ae799af119f5e"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c35da09ab9797b020d0d4f07a66871dfc70ea6566363811090353ea971748b5a"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a3a769ca7580686a66046b77df33851b3c2d796dc1eb60c269b68f690f3e1b65"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d50622efefdb03a640a51a6123748cd151d305c1f0431af762e833d6ffef71f0"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b7461b0a7651d68bc23f0896bffceea40f62887e5ab8397bf7caa883592ef5cb"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:074ee9e17912e025c72a5780ee4c7c413ea35cd26449719cc399b852d4e42533"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7025fb105a11f503943f17718cdb8241ea3bb4d812c710c609e69bead40e2ff0"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-win32.whl", hash = "sha256:2084d36b95139413cef25e9487257a1cc892b93bd1481acd2a9656f7a1d9930c"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:5a738fcd24e34bce4b19126b92fdae15482d6d3a90bd687fd3d24ce9d28ce82d"},
+ {file = "rapidfuzz-2.15.1-cp311-cp311-win_arm64.whl", hash = "sha256:dc3cafa68cfa54638632bdcadf9aab89a3d182b4a3f04d2cad7585ed58ea8731"},
+ {file = "rapidfuzz-2.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3c53d57ba7a88f7bf304d4ea5a14a0ca112db0e0178fff745d9005acf2879f7d"},
+ {file = "rapidfuzz-2.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6ee758eec4cf2215dc8d8eafafcea0d1f48ad4b0135767db1b0f7c5c40a17dd"},
+ {file = "rapidfuzz-2.15.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2d93ba3ae59275e7a3a116dac4ffdb05e9598bf3ee0861fecc5b60fb042d539e"},
+ {file = "rapidfuzz-2.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7c3ff75e647908ddbe9aa917fbe39a112d5631171f3fcea5809e2363e525a59d"},
+ {file = "rapidfuzz-2.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6d89c421702474c6361245b6b199e6e9783febacdbfb6b002669e6cb3ef17a09"},
+ {file = "rapidfuzz-2.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f69e6199fec0f58f9a89afbbaea78d637c7ce77f656a03a1d6ea6abdc1d44f8"},
+ {file = "rapidfuzz-2.15.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:41dfea282844d0628279b4db2929da0dacb8ac317ddc5dcccc30093cf16357c1"},
+ {file = "rapidfuzz-2.15.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2dd03477feefeccda07b7659dd614f6738cfc4f9b6779dd61b262a73b0a9a178"},
+ {file = "rapidfuzz-2.15.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:5efe035aa76ff37d1b5fa661de3c4b4944de9ff227a6c0b2e390a95c101814c0"},
+ {file = "rapidfuzz-2.15.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:ed2cf7c69102c7a0a06926d747ed855bc836f52e8d59a5d1e3adfd980d1bd165"},
+ {file = "rapidfuzz-2.15.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a0e441d4c2025110ec3eba5d54f11f78183269a10152b3a757a739ffd1bb12bf"},
+ {file = "rapidfuzz-2.15.1-cp37-cp37m-win32.whl", hash = "sha256:a4a54efe17cc9f53589c748b53f28776dfdfb9bc83619685740cb7c37985ac2f"},
+ {file = "rapidfuzz-2.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:bb8318116ecac4dfb84841d8b9b461f9bb0c3be5b616418387d104f72d2a16d1"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e9296c530e544f68858c3416ad1d982a1854f71e9d2d3dcedb5b216e6d54f067"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:49c4bcdb9238f11f8c4eba1b898937f09b92280d6f900023a8216008f299b41a"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ebb40a279e134bb3fef099a8b58ed5beefb201033d29bdac005bddcdb004ef71"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7381c11cb590bbd4e6f2d8779a0b34fdd2234dfa13d0211f6aee8ca166d9d05"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfdcdedfd12a0077193f2cf3626ff6722c5a184adf0d2d51f1ec984bf21c23c3"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f85bece1ec59bda8b982bd719507d468d4df746dfb1988df11d916b5e9fe19e8"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b1b393f4a1eaa6867ffac6aef58cfb04bab2b3d7d8e40b9fe2cf40dd1d384601"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53de456ef020a77bf9d7c6c54860a48e2e902584d55d3001766140ac45c54bc7"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2492330bc38b76ed967eab7bdaea63a89b6ceb254489e2c65c3824efcbf72993"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:099e4c6befaa8957a816bdb67ce664871f10aaec9bebf2f61368cf7e0869a7a1"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:46599b2ad4045dd3f794a24a6db1e753d23304699d4984462cf1ead02a51ddf3"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:591f19d16758a3c55c9d7a0b786b40d95599a5b244d6eaef79c7a74fcf5104d8"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ed17359061840eb249f8d833cb213942e8299ffc4f67251a6ed61833a9f2ea20"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-win32.whl", hash = "sha256:aa1e5aad325168e29bf8e17006479b97024aa9d2fdbe12062bd2f8f09080acf8"},
+ {file = "rapidfuzz-2.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:c2bb68832b140c551dbed691290bef4ee6719d4e8ce1b7226a3736f61a9d1a83"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3fac40972cf7b6c14dded88ae2331eb50dfbc278aa9195473ef6fc6bfe49f686"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f0e456cbdc0abf39352800309dab82fd3251179fa0ff6573fa117f51f4e84be8"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:22b9d22022b9d09fd4ece15102270ab9b6a5cfea8b6f6d1965c1df7e3783f5ff"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46754fe404a9a6f5cbf7abe02d74af390038d94c9b8c923b3f362467606bfa28"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91abb8bf7610efe326394adc1d45e1baca8f360e74187f3fa0ef3df80cdd3ba6"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e40a2f60024f9d3c15401e668f732800114a023f3f8d8c40f1521a62081ff054"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a48ee83916401ac73938526d7bd804e01d2a8fe61809df7f1577b0b3b31049a3"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c71580052f9dbac443c02f60484e5a2e5f72ad4351b84b2009fbe345b1f38422"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:82b86d5b8c1b9bcbc65236d75f81023c78d06a721c3e0229889ff4ed5c858169"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:fc4528b7736e5c30bc954022c2cf410889abc19504a023abadbc59cdf9f37cae"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e1e0e569108a5760d8f01d0f2148dd08cc9a39ead79fbefefca9e7c7723c7e88"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:94e1c97f0ad45b05003806f8a13efc1fc78983e52fa2ddb00629003acf4676ef"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47e81767a962e41477a85ad7ac937e34d19a7d2a80be65614f008a5ead671c56"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-win32.whl", hash = "sha256:79fc574aaf2d7c27ec1022e29c9c18f83cdaf790c71c05779528901e0caad89b"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:f3dd4bcef2d600e0aa121e19e6e62f6f06f22a89f82ef62755e205ce14727874"},
+ {file = "rapidfuzz-2.15.1-cp39-cp39-win_arm64.whl", hash = "sha256:cac095cbdf44bc286339a77214bbca6d4d228c9ebae3da5ff6a80aaeb7c35634"},
+ {file = "rapidfuzz-2.15.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b89d1126be65c85763d56e3b47d75f1a9b7c5529857b4d572079b9a636eaa8a7"},
+ {file = "rapidfuzz-2.15.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19b7460e91168229768be882ea365ba0ac7da43e57f9416e2cfadc396a7df3c2"},
+ {file = "rapidfuzz-2.15.1-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93c33c03e7092642c38f8a15ca2d8fc38da366f2526ec3b46adf19d5c7aa48ba"},
+ {file = "rapidfuzz-2.15.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:040faca2e26d9dab5541b45ce72b3f6c0e36786234703fc2ac8c6f53bb576743"},
+ {file = "rapidfuzz-2.15.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:6e2a3b23e1e9aa13474b3c710bba770d0dcc34d517d3dd6f97435a32873e3f28"},
+ {file = "rapidfuzz-2.15.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2e597b9dfd6dd180982684840975c458c50d447e46928efe3e0120e4ec6f6686"},
+ {file = "rapidfuzz-2.15.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d14752c9dd2036c5f36ebe8db5f027275fa7d6b3ec6484158f83efb674bab84e"},
+ {file = "rapidfuzz-2.15.1-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:558224b6fc6124d13fa32d57876f626a7d6188ba2a97cbaea33a6ee38a867e31"},
+ {file = "rapidfuzz-2.15.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c89cfa88dc16fd8c9bcc0c7f0b0073f7ef1e27cceb246c9f5a3f7004fa97c4d"},
+ {file = "rapidfuzz-2.15.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:509c5b631cd64df69f0f011893983eb15b8be087a55bad72f3d616b6ae6a0f96"},
+ {file = "rapidfuzz-2.15.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0f73a04135a03a6e40393ecd5d46a7a1049d353fc5c24b82849830d09817991f"},
+ {file = "rapidfuzz-2.15.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c99d53138a2dfe8ada67cb2855719f934af2733d726fbf73247844ce4dd6dd5"},
+ {file = "rapidfuzz-2.15.1-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f01fa757f0fb332a1f045168d29b0d005de6c39ee5ce5d6c51f2563bb53c601b"},
+ {file = "rapidfuzz-2.15.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60368e1add6e550faae65614844c43f8a96e37bf99404643b648bf2dba92c0fb"},
+ {file = "rapidfuzz-2.15.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:785744f1270828cc632c5a3660409dee9bcaac6931a081bae57542c93e4d46c4"},
+ {file = "rapidfuzz-2.15.1.tar.gz", hash = "sha256:d62137c2ca37aea90a11003ad7dc109c8f1739bfbe5a9a217f3cdb07d7ac00f6"},
+]
+
+[package.extras]
+full = ["numpy"]
+
+[[package]]
+name = "requests"
+version = "2.28.2"
+description = "Python HTTP for Humans."
+category = "main"
+optional = false
+python-versions = ">=3.7, <4"
+files = [
+ {file = "requests-2.28.2-py3-none-any.whl", hash = "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa"},
+ {file = "requests-2.28.2.tar.gz", hash = "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf"},
+]
+
+[package.dependencies]
+certifi = ">=2017.4.17"
+charset-normalizer = ">=2,<4"
+idna = ">=2.5,<4"
+urllib3 = ">=1.21.1,<1.27"
+
+[package.extras]
+socks = ["PySocks (>=1.5.6,!=1.5.7)"]
+use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
+
+[[package]]
+name = "ruff"
+version = "0.0.262"
+description = "An extremely fast Python linter, written in Rust."
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "ruff-0.0.262-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:c26c1abd420d041592d05d63aee8c6a18feb24aed4deb6e91129e9f2c7b4914a"},
+ {file = "ruff-0.0.262-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:b379e9765afa679316e52288a942df085e590862f8945088936a7bce3116d8f3"},
+ {file = "ruff-0.0.262-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b7e0ca6821aafbd2b059df3119fcd5881250721ca8e825789fd2c471f7c59be"},
+ {file = "ruff-0.0.262-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4cca35e2aeddff72bb4379a1dabc134e0c0d25ebc754a2cb733a1f8d4dbbb5e0"},
+ {file = "ruff-0.0.262-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:15bf5533ce169aebbafa00017987f673e879f60a625d932b464b8cdaf32a4fce"},
+ {file = "ruff-0.0.262-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:3909e249d984c4517194005a1c30eaa0c3a6d906c789d9fc0c9c7e007fb3e759"},
+ {file = "ruff-0.0.262-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4e2813013a19b3e147e840bdb2e42db5825b53b47364e58e7b467c5fa47ffda2"},
+ {file = "ruff-0.0.262-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d25a94996b2037e566c2a801c8b324c0a826194d5d4d90ad7c1ccb8cf06521fa"},
+ {file = "ruff-0.0.262-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85ca04348372efc59f6ee808d903d35e0d352cf2c78e487757cd48b65104b83e"},
+ {file = "ruff-0.0.262-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:24f989363e9bb5d0283490298102a5218682e49ebf300e445d69e24bee03ac83"},
+ {file = "ruff-0.0.262-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:3c24e678e43ca4b67e29cc9a7a54eea05f31a5898cbf17bfec47b68f08d32a60"},
+ {file = "ruff-0.0.262-py3-none-musllinux_1_2_i686.whl", hash = "sha256:0baff3c9a22227358ea109c165efe62dbdd0f2b9fd5256567dda8682b444fe23"},
+ {file = "ruff-0.0.262-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:083bac6e238d8b7d5ac3618666ea63b7ac661cf94c5da160070a58e190082831"},
+ {file = "ruff-0.0.262-py3-none-win32.whl", hash = "sha256:15bbfa2d15c137717627e0d56b0e535ae297b734551e34e03fcc25d7642cf43a"},
+ {file = "ruff-0.0.262-py3-none-win_amd64.whl", hash = "sha256:973ac29193f718349cf5746b7d86dfeaf7d40e9651ed97790a9b9327305888b9"},
+ {file = "ruff-0.0.262-py3-none-win_arm64.whl", hash = "sha256:f102904ebe395acd2a181d295b98120acd7a63f732b691672977fc688674f4af"},
+ {file = "ruff-0.0.262.tar.gz", hash = "sha256:faea54231c265f5349975ba6f3d855b71881a01f391b2000c47740390c6d5f68"},
+]
+
+[[package]]
+name = "ruff-lsp"
+version = "0.0.24"
+description = "A Language Server Protocol implementation for Ruff."
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "ruff_lsp-0.0.24-py3-none-any.whl", hash = "sha256:71207b0a64f40577db3e9aef0b1331fcf4122f9b98bba66b905d41706d639e65"},
+ {file = "ruff_lsp-0.0.24.tar.gz", hash = "sha256:d617bf19893c3bd2ea3d71f79aeede196b91ca08831b53a727e24d4f63f29f3a"},
+]
+
+[package.dependencies]
+lsprotocol = ">=2023.0.0a1"
+pygls = ">=1.0.1"
+ruff = ">=0.0.253"
+typing-extensions = "*"
+
+[package.extras]
+dev = ["black (==22.12.0)", "mypy (==0.991)", "python-lsp-jsonrpc (==1.0.0)"]
+
+[[package]]
+name = "tomli"
+version = "2.0.1"
+description = "A lil' TOML parser"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
+ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
+]
+
+[[package]]
+name = "typeguard"
+version = "2.13.3"
+description = "Run-time type checker for Python"
+category = "dev"
+optional = false
+python-versions = ">=3.5.3"
+files = [
+ {file = "typeguard-2.13.3-py3-none-any.whl", hash = "sha256:5e3e3be01e887e7eafae5af63d1f36c849aaa94e3a0112097312aabfa16284f1"},
+ {file = "typeguard-2.13.3.tar.gz", hash = "sha256:00edaa8da3a133674796cf5ea87d9f4b4c367d77476e185e80251cc13dfbb8c4"},
+]
+
+[package.extras]
+doc = ["sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"]
+test = ["mypy", "pytest", "typing-extensions"]
+
+[[package]]
+name = "types-requests"
+version = "2.28.11.17"
+description = "Typing stubs for requests"
+category = "dev"
+optional = false
+python-versions = "*"
+files = [
+ {file = "types-requests-2.28.11.17.tar.gz", hash = "sha256:0d580652ce903f643f8c3b494dd01d29367ea57cea0c7ad7f65cf3169092edb0"},
+ {file = "types_requests-2.28.11.17-py3-none-any.whl", hash = "sha256:cc1aba862575019306b2ed134eb1ea994cab1c887a22e18d3383e6dd42e9789b"},
+]
+
+[package.dependencies]
+types-urllib3 = "<1.27"
+
+[[package]]
+name = "types-urllib3"
+version = "1.26.25.10"
+description = "Typing stubs for urllib3"
+category = "dev"
+optional = false
+python-versions = "*"
+files = [
+ {file = "types-urllib3-1.26.25.10.tar.gz", hash = "sha256:c44881cde9fc8256d05ad6b21f50c4681eb20092552351570ab0a8a0653286d6"},
+ {file = "types_urllib3-1.26.25.10-py3-none-any.whl", hash = "sha256:12c744609d588340a07e45d333bf870069fc8793bcf96bae7a96d4712a42591d"},
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.5.0"
+description = "Backported and Experimental Type Hints for Python 3.7+"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"},
+ {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"},
+]
+
+[[package]]
+name = "urllib3"
+version = "1.26.15"
+description = "HTTP library with thread-safe connection pooling, file post, and more."
+category = "main"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
+files = [
+ {file = "urllib3-1.26.15-py2.py3-none-any.whl", hash = "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42"},
+ {file = "urllib3-1.26.15.tar.gz", hash = "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305"},
+]
+
+[package.extras]
+brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
+secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"]
+socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
+
+[metadata]
+lock-version = "2.0"
+python-versions = "^3.10"
+content-hash = "519ec995a8bf87cd80caa4e18e100450209fbbf6970296ea08ad71f27586644a"
diff --git a/sys/nixpkgs/pkgs/update_vim_plugins/pyproject.toml b/sys/nixpkgs/pkgs/update_vim_plugins/pyproject.toml
new file mode 100644
index 00000000..d08dc043
--- /dev/null
+++ b/sys/nixpkgs/pkgs/update_vim_plugins/pyproject.toml
@@ -0,0 +1,45 @@
+[tool.poetry]
+name = "update_vim_plugins"
+version = "0.1.0"
+description = ""
+authors = ["Your Name <you@example.com>"]
+packages = [{include = "update_vim_plugins"}]
+
+[tool.poetry.scripts]
+update-vim-plugins = "update_vim_plugins.__main__:main"
+
+[tool.poetry.dependencies]
+python = "^3.10"
+requests = "^2.28.2"
+cleo = "^2.0.1"
+jsonpickle = "*"
+dateparser = "1.1.8"
+
+[tool.poetry.group.test.dependencies]
+pytest-cov = "^4.0.0"
+pytest = "^7.3.1"
+pytest-mock = "^3.10.0"
+
+[tool.poetry.group.dev]
+optional = true
+
+[tool.poetry.group.dev.dependencies]
+# black = "^23.3.0"
+# ruff-lsp = "^0.0.24"
+# mypy = "^1.2.0"
+# types-requests = "^2.28.11.17"
+# isort = "^5.12.0"
+# ruff = "^0.0.262"
+
+[tool.isort]
+profile = "black"
+
+[tool.black]
+line-length = 120
+
+[tool.ruff]
+line-length = 120
+
+[build-system]
+requires = ["poetry-core"]
+build-backend = "poetry.core.masonry.api"
diff --git a/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/__init__.py b/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/__init__.py
diff --git a/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/__main__.py b/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/__main__.py
new file mode 100644
index 00000000..a8d9e06f
--- /dev/null
+++ b/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/__main__.py
@@ -0,0 +1,15 @@
+from cleo.application import Application
+
+from .update import UpdateCommand
+from .cleanup import CleanUpCommand
+
+
+def main():
+ application = Application()
+ application.add(UpdateCommand())
+ application.add(CleanUpCommand())
+ application.run()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/cleanup.py b/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/cleanup.py
new file mode 100644
index 00000000..fd313ed0
--- /dev/null
+++ b/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/cleanup.py
@@ -0,0 +1,100 @@
+from cleo.commands.command import Command
+from cleo.helpers import argument
+
+from .helpers import read_manifest_to_spec, read_blacklist_to_spec, write_manifest_from_spec
+
+
+class CleanUpCommand(Command):
+ name = "cleanup"
+ description = "Clean up manifest"
+ arguments = [argument("plug_dir", description="Path to the plugin directory", optional=False)]
+
+ def handle(self):
+ """Main command function"""
+
+ plug_dir = self.argument("plug_dir")
+ self.line("<comment>Checking manifest file</comment>")
+ # all cleaning up will be done during reading and writing automatically
+ manifest = read_manifest_to_spec(plug_dir)
+ blacklist = read_blacklist_to_spec(plug_dir)
+
+ new_manifest = [spec for spec in manifest if spec not in blacklist]
+
+ new_manifest_filterd = self.filter_renamed(new_manifest)
+
+ write_manifest_from_spec(new_manifest_filterd, plug_dir)
+
+ self.line("<comment>Done</comment>")
+
+ def filter_renamed(self, specs):
+ """Filter specs that define the same plugin (same owner and same repo) but with different properties.
+ This could be a different name, source, or branch
+ """
+
+ error = False
+ for i, p in enumerate(specs):
+ for p2 in specs:
+ same_owner = p.owner.lower() == p2.owner.lower()
+ same_repo = p.repo.lower() == p2.repo.lower()
+ different_specs = p != p2
+ marked_duplicate = p.marked_duplicate or p2.marked_duplicate
+
+ if same_owner and same_repo and different_specs and not marked_duplicate:
+ self.line("<info>The following lines appear to define the same plugin</info>")
+
+ p_props_defined = p.branch is not None or p.custom_name is not None
+ p2_props_defined = p2.branch is not None or p2.custom_name is not None
+ p_is_lower_case = p.owner == p.owner.lower() and p.name == p.name.lower()
+ p2_is_lower_case = p2.owner == p2.owner.lower() and p2.name == p2.name.lower()
+
+ # list of conditions for selecting p
+ select_p = p_props_defined and not p2_props_defined or p2_is_lower_case and not p_is_lower_case
+ # list of conditions for selecting p2
+ select_p2 = p2_props_defined and not p_props_defined or p_is_lower_case and not p2_is_lower_case
+
+ # one is more defined and is all lower, but the other is not all lower
+ # (we assume the not all lower case is the correct naming)
+ error_props_lower = (
+ p_props_defined and p_is_lower_case and not p2_props_defined and not p2_is_lower_case
+ )
+ error_props_lower2 = (
+ p2_props_defined and p2_is_lower_case and not p_props_defined and not p_is_lower_case
+ )
+
+ # both props are defined
+ error_props = p_props_defined and p2_props_defined
+
+ # the sources are different
+ error_source = p.repository_host != p2.repository_host
+
+ if error_props_lower or error_props_lower2 or error_props or error_source:
+ self.line(" • <error>Cannot determine which is the correct plugin</error>")
+ self.line(f" - {p.line}")
+ self.line(f" - {p2.line}")
+ error = True
+ # remove second spec to not encounter the error twice
+ # this will not be written to the manifest.txt because we set
+ # the error flag and will exit after the loop
+ specs.remove(p2)
+ elif select_p:
+ self.line(f" - <comment>{p.line}</comment>")
+ self.line(f" - {p2.line}")
+ specs.remove(p2)
+ elif select_p2:
+ self.line(f" - {p.line}")
+ self.line(f" - <comment>{p2.line}</comment>")
+ specs.remove(p)
+ else:
+ self.line(" • <error>Logic error in correct spec determination</error>")
+ self.line(f" - {p.line}")
+ self.line(f" - {p2.line}")
+ error = True
+ # remove second spec to not encounter the error twice
+ # this will not be written to the manifest.txt because we set
+ # the error flag and will exit after the loop
+ specs.remove(p)
+ if error:
+ # exit after all errors have been found
+ exit(1)
+
+ return specs
diff --git a/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/helpers.py b/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/helpers.py
new file mode 100644
index 00000000..8a28b0e8
--- /dev/null
+++ b/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/helpers.py
@@ -0,0 +1,61 @@
+from .spec import PluginSpec
+
+MANIFEST_FILE = "manifest.txt"
+BLACKLIST_FILE = "blacklist.txt"
+PKGS_FILE = "default.nix"
+JSON_FILE = ".plugins.json"
+PLUGINS_LIST_FILE = "plugins.md"
+
+
+def get_const(const: str, plug_dir: str) -> str:
+ out = plug_dir + "/" + const
+ return out
+
+
+def read_manifest(plug_dir: str) -> list[str]:
+ with open(get_const(MANIFEST_FILE, plug_dir), "r") as file:
+ specs = set([spec.strip() for spec in file.readlines()])
+
+ return sorted(specs)
+
+
+def read_manifest_to_spec(plug_dir: str) -> list[PluginSpec]:
+ manifest = read_manifest(plug_dir)
+ specs = [PluginSpec.from_spec(spec.strip()) for spec in manifest]
+
+ return sorted(specs)
+
+
+def read_blacklist(plug_dir: str) -> list[str]:
+ with open(get_const(BLACKLIST_FILE, plug_dir), "r") as file:
+ if len(file.readlines()) == 0:
+ return [""]
+ else:
+ blacklisted_specs = set([spec.strip() for spec in file.readlines()])
+
+ return sorted(blacklisted_specs)
+
+
+def read_blacklist_to_spec(plug_dir: str) -> list[PluginSpec]:
+ blacklist = read_blacklist(plug_dir)
+ specs = [PluginSpec.from_spec(spec.strip()) for spec in blacklist]
+
+ return sorted(specs)
+
+
+def write_manifest(specs: list[str] | set[str], plug_dir: str):
+ """write specs to manifest file. Does some cleaning up"""
+
+ with open(get_const(MANIFEST_FILE, plug_dir), "w") as file:
+ specs = sorted(set(specs), key=lambda x: x.lower())
+ specs = [p for p in specs]
+
+ for s in specs:
+ file.write(f"{s}\n")
+
+
+def write_manifest_from_spec(specs: list[PluginSpec], plug_dir: str):
+ """write specs to manifest file. Does some cleaning up"""
+
+ strings = [f"{spec}" for spec in specs]
+ write_manifest(strings, plug_dir)
diff --git a/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/nix.py b/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/nix.py
new file mode 100644
index 00000000..66a8df4c
--- /dev/null
+++ b/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/nix.py
@@ -0,0 +1,121 @@
+import abc
+import enum
+import json
+import subprocess
+
+
+def nix_prefetch_url(url):
+ """Return the sha256 hash of the given url."""
+ subprocess_output = subprocess.check_output(
+ ["nix-prefetch-url", "--type", "sha256", url],
+ stderr=subprocess.DEVNULL,
+ )
+ sha256 = subprocess_output.decode("utf-8").strip()
+ return sha256
+
+
+def nix_prefetch_git(url):
+ """Return the sha256 hash of the given git url."""
+ subprocess_output = subprocess.check_output(["nix-prefetch-git", url], stderr=subprocess.DEVNULL)
+ sha256 = json.loads(subprocess_output)["sha256"]
+ return sha256
+
+
+class Source(abc.ABC):
+ """Abstract base class for sources."""
+
+ url: str
+ sha256: str
+
+ @abc.abstractmethod
+ def __init__(self, url: str) -> None:
+ """Initialize a Source."""
+
+ @abc.abstractmethod
+ def get_nix_expression(self):
+ """Return the nix expression for this source."""
+
+ def __repr__(self):
+ """Return the representation of this source."""
+ return self.get_nix_expression()
+
+
+class UrlSource(Source):
+ """A source that is a url."""
+
+ def __init__(self, url: str) -> None:
+ """Initialize a UrlSource."""
+ self.url = url
+ self.sha256 = nix_prefetch_url(url)
+
+ def get_nix_expression(self):
+ """Return the nix expression for this source."""
+ return f'fetchurl {{ url = "{self.url}"; sha256 = "{self.sha256}"; }}'
+
+
+class GitSource(Source):
+ """A source that is a git repository."""
+
+ def __init__(self, url: str, rev: str) -> None:
+ """Initialize a GitSource."""
+ self.url = url
+ self.rev = rev
+ self.sha256 = nix_prefetch_git(url)
+
+ def get_nix_expression(self):
+ """Return the nix expression for this source."""
+ return f'fetchgit {{ url = "{self.url}"; rev = "{self.rev}"; sha256 = "{self.sha256}"; }}'
+
+
+class License(enum.Enum):
+ """An enumeration of licenses."""
+
+ AGPL_3_0 = "agpl3Only"
+ APACHE_2_0 = "asf20"
+ BSD_2_CLAUSE = "bsd2"
+ BSD_3_CLAUSE = "bsd3"
+ BSL_1_0 = "bsl1_0"
+ CC0_1_0 = "cc0"
+ EPL_2_0 = "epl20"
+ GPL_2_0 = "gpl2Only"
+ GPL_3_0 = "gpl3Only"
+ ISCLGPL_2_1 = "lgpl21Only"
+ MIT = "mit"
+ MPL_2_0 = "mpl20"
+ UNLUNLICENSE = "unlicense"
+ WTFPL = "wtfpl"
+ UNFREE = "unfree"
+ UNKNOWN = ""
+
+ @classmethod
+ def from_spdx_id(cls, spdx_id: str | None) -> "License":
+ """Return the License from the given spdx_id."""
+ mapping = {
+ "AGPL-3.0": cls.AGPL_3_0,
+ "AGPL-3.0-only": cls.AGPL_3_0,
+ "Apache-2.0": cls.APACHE_2_0,
+ "BSD-2-Clause": cls.BSD_2_CLAUSE,
+ "BSD-3-Clause": cls.BSD_3_CLAUSE,
+ "BSL-1.0": cls.BSL_1_0,
+ "CC0-1.0": cls.CC0_1_0,
+ "EPL-2.0": cls.EPL_2_0,
+ "GPL-2.0": cls.GPL_2_0,
+ "GPL-2.0-only": cls.GPL_2_0,
+ "GPL-3.0": cls.GPL_3_0,
+ "GPL-3.0-only": cls.GPL_3_0,
+ "LGPL-2.1-only": cls.ISCLGPL_2_1,
+ "MIT": cls.MIT,
+ "MPL-2.0": cls.MPL_2_0,
+ "Unlicense": cls.UNLUNLICENSE,
+ "WTFPL": cls.WTFPL,
+ }
+
+ if spdx_id is None:
+ return cls.UNKNOWN
+
+ spdx_id = spdx_id.upper()
+ return mapping.get(spdx_id, cls.UNKNOWN)
+
+ def __str__(self):
+ """Return the string representation of this license."""
+ return self.value
diff --git a/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/plugin.py b/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/plugin.py
new file mode 100644
index 00000000..8334ad53
--- /dev/null
+++ b/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/plugin.py
@@ -0,0 +1,182 @@
+import logging
+import os
+import urllib
+
+import requests
+import jsonpickle
+from datetime import datetime, date
+from dateparser import parse
+
+from .nix import GitSource, License, Source, UrlSource
+from .spec import PluginSpec, RepositoryHost
+
+
+logger = logging.getLogger(__name__)
+
+
+class VimPlugin:
+ """Abstract base class for vim plugins."""
+
+ name: str
+ owner: str
+ repo: str
+ version: date
+ source: Source
+ description: str = "No description"
+ homepage: str
+ license: License
+ source_line: str
+ checked: date = datetime.now().date()
+
+ def to_nix(self):
+ """Return the nix expression for this plugin."""
+ meta = f'with lib; {{ description = "{self.description}"; homepage = "{self.homepage}"; license = with licenses; [ {self.license.value} ]; }}'
+ return f'/* Generated from: {self.source_line} */ {self.name} = buildVimPlugin {{ pname = "{self.name}"; version = "{self.version}"; src = {self.source.get_nix_expression()}; meta = {meta}; }};'
+
+ def to_json(self):
+ """Serizalize the plugin to json"""
+ return jsonpickle.encode(self)
+
+ def to_markdown(self):
+ link = f"[{self.source_line}]({self.homepage})"
+ version = f"{self.version}"
+ package_name = f"{self.name}"
+ checked = f"{self.checked}"
+
+ return f"| {link} | {version} | `{package_name}` | {checked} |"
+
+ def __lt__(self, o: object) -> bool:
+ if not isinstance(o, VimPlugin):
+ return False
+
+ return self.name.lower() < o.name.lower()
+
+ def __repr__(self):
+ """Return the representation of this plugin."""
+ return f"VimPlugin({self.name!r}, {self.version.strftime('%Y-%m-%d')})"
+
+
+def _get_github_token():
+ token = os.environ.get("GITHUB_TOKEN")
+ if token is None:
+ # NOTE: This should never use more than the free api requests <2023-12-09>
+ pass
+ # logger.warning("GITHUB_TOKEN environment variable not set")
+ return token
+
+
+class GitHubPlugin(VimPlugin):
+ def __init__(self, plugin_spec: PluginSpec) -> None:
+ """Initialize a GitHubPlugin."""
+
+ full_name = f"{plugin_spec.owner}/{plugin_spec.repo}"
+ repo_info = self._api_call(f"repos/{full_name}")
+ default_branch = plugin_spec.branch or repo_info["default_branch"]
+ api_callback = self._api_call(f"repos/{full_name}/commits/{default_branch}")
+ latest_commit = api_callback["commit"]
+ sha = api_callback["sha"]
+
+ self.name = plugin_spec.name
+ self.owner = plugin_spec.owner
+ self.version = parse(latest_commit["committer"]["date"]).date()
+ self.source = UrlSource(f"https://github.com/{full_name}/archive/{sha}.tar.gz")
+ self.description = (repo_info.get("description") or "").replace('"', '\\"')
+ self.homepage = repo_info["html_url"]
+ self.license = plugin_spec.license or License.from_spdx_id((repo_info.get("license") or {}).get("spdx_id"))
+ self.source_line = plugin_spec.line
+
+ def _api_call(self, path: str, token: str | None = _get_github_token()):
+ """Call the GitHub API."""
+ url = f"https://api.github.com/{path}"
+ headers = {"Content-Type": "application/json"}
+ if token is not None:
+ headers["Authorization"] = f"token {token}"
+ response = requests.get(url, headers=headers)
+ if response.status_code != 200:
+ raise RuntimeError(f"GitHub API call failed: {response.text}")
+ return response.json()
+
+
+class GitlabPlugin(VimPlugin):
+ def __init__(self, plugin_spec: PluginSpec) -> None:
+ """Initialize a GitlabPlugin."""
+
+ full_name = urllib.parse.quote(f"{plugin_spec.owner}/{plugin_spec.repo}", safe="")
+ repo_info = self._api_call(f"projects/{full_name}")
+ default_branch = plugin_spec.branch or repo_info["default_branch"]
+ api_callback = self._api_call(f"projects/{full_name}/repository/branches/{default_branch}")
+ latest_commit = api_callback["commit"]
+ sha = latest_commit["id"]
+
+ self.name = plugin_spec.name
+ self.owner = plugin_spec.owner
+ self.version = parse(latest_commit["created_at"]).date()
+ self.source = UrlSource(f"https://gitlab.com/api/v4/projects/{full_name}/repository/archive.tar.gz?sha={sha}")
+ self.description = (repo_info.get("description") or "").replace('"', '\\"')
+ self.homepage = repo_info["web_url"]
+ self.license = plugin_spec.license or License.from_spdx_id(repo_info.get("license", {}).get("key"))
+ self.source_line = plugin_spec.line
+
+ def _api_call(self, path: str) -> dict:
+ """Call the Gitlab API."""
+ url = f"https://gitlab.com/api/v4/{path}"
+ response = requests.get(url)
+ if response.status_code != 200:
+ raise RuntimeError(f"Gitlab API call failed: {response.text}")
+ return response.json()
+
+
+def _get_sourcehut_token():
+ token = os.environ.get("SOURCEHUT_TOKEN")
+ if token is None:
+ # NOTE: This should never use more than the free requests <2023-12-09>
+ pass
+ # logger.warning("SOURCEHUT_TOKEN environment variable not set")
+ return token
+
+
+class SourceHutPlugin(VimPlugin):
+ def __init__(self, plugin_spec: PluginSpec) -> None:
+ """Initialize a SourceHutPlugin."""
+
+ repo_info = self._api_call(f"~{plugin_spec.owner}/repos/{plugin_spec.repo}")
+ if plugin_spec.branch is None:
+ commits = self._api_call(f"~{plugin_spec.owner}/repos/{plugin_spec.repo}/log")
+ else:
+ commits = self._api_call(f"~{plugin_spec.owner}/repos/{plugin_spec.repo}/log/{plugin_spec.branch}")
+ latest_commit = commits["results"][0]
+ sha = latest_commit["id"]
+
+ self.name = plugin_spec.name
+ self.owner = plugin_spec.owner
+ self.version = parse(latest_commit["timestamp"]).date()
+ self.description = (repo_info.get("description") or "").replace('"', '\\"')
+ self.homepage = f"https://git.sr.ht/~{plugin_spec.owner}/{plugin_spec.repo}"
+ self.source = GitSource(self.homepage, sha)
+ self.license = plugin_spec.license or License.UNKNOWN # cannot be determined via API
+ self.source_line = plugin_spec.line
+
+ def _api_call(self, path: str, token: str | None = _get_sourcehut_token()):
+ """Call the SourceHut API."""
+
+ url = f"https://git.sr.ht/api/{path}"
+ headers = {"Content-Type": "application/json"}
+ if token is not None:
+ headers["Authorization"] = f"token {token}"
+ response = requests.get(url, headers=headers)
+ if response.status_code != 200:
+ raise RuntimeError(f"SourceHut API call failed: {response.json()}")
+ return response.json()
+
+
+def plugin_from_spec(plugin_spec: PluginSpec) -> VimPlugin:
+ """Initialize a VimPlugin."""
+
+ if plugin_spec.repository_host == RepositoryHost.GITHUB:
+ return GitHubPlugin(plugin_spec)
+ elif plugin_spec.repository_host == RepositoryHost.GITLAB:
+ return GitlabPlugin(plugin_spec)
+ elif plugin_spec.repository_host == RepositoryHost.SOURCEHUT:
+ return SourceHutPlugin(plugin_spec)
+ else:
+ raise NotImplementedError(f"Unsupported source: {plugin_spec.repository_host}")
diff --git a/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/spec.py b/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/spec.py
new file mode 100644
index 00000000..04f25ccc
--- /dev/null
+++ b/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/spec.py
@@ -0,0 +1,143 @@
+import enum
+import re
+
+from .nix import License
+
+
+class RepositoryHost(enum.Enum):
+ """A repository host."""
+
+ GITHUB = "github"
+ GITLAB = "gitlab"
+ SOURCEHUT = "sourcehut"
+
+
+class PluginSpec:
+ """A Vim plugin Spec."""
+
+ @classmethod
+ def from_spec(cls, spec):
+ """The spec line must be in the format:
+ [<repository_host>:]<owner>/<repo>[:<branch>][:name].
+
+ repository_host is one of github (default), gitlab, or sourcehut.
+ owner is the repository owner.
+ repo is the repository name.
+ branch is the git branch.
+ name is the name to use for the plugin (default is value of repo).
+ """
+ repository_host = RepositoryHost.GITHUB
+ gitref = "master"
+
+ repository_host_regex = r"((?P<repository_host>[^:]+):)"
+ owner_regex = r"(?P<owner>[^/:]+)"
+ repo_regex = r"(?P<repo>[^:]+)"
+ branch_regex = r"(:(?P<branch>[^:]+)?)"
+ name_regex = r"(:(?P<name>[^:]+)?)"
+ license_regex = r"(:(?P<license>[^:]+)?)"
+ marked_duplicate_regex = r'(:(?P<duplicate>duplicate))'
+
+ spec_regex = re.compile(
+ f"^{repository_host_regex}?{owner_regex}/{repo_regex}{branch_regex}?{name_regex}?{license_regex}?{marked_duplicate_regex}?$",
+ )
+
+ match = spec_regex.match(spec)
+ if match is None:
+ raise ValueError(f"Invalid spec: {spec}")
+
+ group_dict = match.groupdict()
+
+ repository_host = RepositoryHost(group_dict.get("repository_host") or "github")
+
+ owner = group_dict.get("owner")
+ if owner is None:
+ raise RuntimeError("Could not get owner")
+
+ repo = group_dict.get("repo")
+ if repo is None:
+ raise RuntimeError("Could not get repo")
+
+ branch = group_dict.get("branch")
+ name = group_dict.get("name")
+ license = group_dict.get("license")
+ marked_duplicate = bool(group_dict.get("duplicate")) # True if 'duplicate', False if None
+
+ line = spec
+
+ return cls(repository_host, owner, repo, line, branch, name, license, marked_duplicate)
+
+ def __init__(
+ self,
+ repository_host: RepositoryHost,
+ owner: str,
+ repo: str,
+ line: str,
+ branch: str | None = None,
+ name: str | None = None,
+ license: str | None = None,
+ marked_duplicate: bool = False,
+ ) -> None:
+ """Initialize a VimPluginSpec."""
+ self.repository_host = repository_host
+ self.owner = owner
+ self.repo = repo
+ self.branch = branch
+ self.custom_name = name
+ self.name = name or repo.replace(".", "-").replace("_", "-")
+ self.license = License(license) if license else None
+ self.line = line
+ self.marked_duplicate = marked_duplicate
+
+ def __str__(self) -> str:
+ """Return a string representation of a VimPluginSpec."""
+ spec = ""
+
+ if self.repository_host != RepositoryHost.GITHUB:
+ spec += f"{self.repository_host.value}:"
+
+ spec += f"{self.owner}/{self.repo}"
+
+ spec += ":"
+ if self.branch is not None:
+ spec += self.branch
+
+ spec += ":"
+ if self.custom_name is not None:
+ spec += self.custom_name
+
+ spec += ":"
+ if self.license is not None:
+ spec += str(self.license)
+
+ spec += ":"
+ if self.marked_duplicate:
+ spec += "duplicate"
+
+ return spec.rstrip(":")
+
+ def __repr__(self):
+ """Return the representation of the specs"""
+ return f"PluginSpec({self.owner}/{self.repo}, {self.name})"
+
+ def to_spec(self):
+ """Return a spec line for a VimPluginSpec."""
+ return str(self)
+
+ def __lt__(self, o: object) -> bool:
+ if not isinstance(o, PluginSpec):
+ return False
+
+ return self.name.lower() < o.name.lower()
+
+ def __eq__(self, o: object) -> bool:
+ """Return True if the two specs are equal."""
+ if not isinstance(o, PluginSpec):
+ return False
+
+ return (
+ self.repository_host == o.repository_host
+ and self.owner == o.owner
+ and self.repo == o.repo
+ and self.branch == o.branch
+ and self.name == o.name
+ )
diff --git a/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/tests/__init__.py b/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/tests/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/tests/__init__.py
diff --git a/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/tests/fixtures.py b/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/tests/fixtures.py
new file mode 100644
index 00000000..a90d67c6
--- /dev/null
+++ b/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/tests/fixtures.py
@@ -0,0 +1,44 @@
+import json
+
+import pytest
+from pytest_mock import MockerFixture
+
+from update_vim_plugins.nix import GitSource, License, UrlSource
+
+
+@pytest.fixture()
+def url():
+ return "https://example.com"
+
+
+@pytest.fixture()
+def rev():
+ return "1234567890abcdef"
+
+
+@pytest.fixture()
+def sha256():
+ return "sha256-1234567890abcdef"
+
+
+@pytest.fixture()
+def url_source(mocker: MockerFixture, url: str, sha256: str):
+ mocker.patch("subprocess.check_output", return_value=bytes(sha256, "utf-8"))
+ return UrlSource(url)
+
+
+@pytest.fixture()
+def git_source(mocker: MockerFixture, url: str, rev: str, sha256: str):
+ return_value = {
+ "url": url,
+ "rev": rev,
+ "date": "1970-01-01T00:00:00+00:00",
+ "path": "",
+ "sha256": sha256,
+ "fetchLFS": False,
+ "fetchSubmodules": False,
+ "deepClone": False,
+ "leaveDotGit": False,
+ }
+ mocker.patch("subprocess.check_output", return_value=json.dumps(return_value).encode("utf-8"))
+ return GitSource(url, rev)
diff --git a/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/tests/test_nix.py b/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/tests/test_nix.py
new file mode 100644
index 00000000..5d6e51b1
--- /dev/null
+++ b/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/tests/test_nix.py
@@ -0,0 +1,34 @@
+from update_vim_plugins.nix import GitSource, License, UrlSource
+
+from .fixtures import git_source, rev, sha256, url, url_source
+
+
+def test_url_source(url_source: UrlSource, url: str, sha256: str):
+ assert url_source.url == url
+ assert url_source.sha256 == sha256
+
+
+def test_url_source_nix_expression(url_source: UrlSource, url: str, sha256: str):
+ assert url_source.get_nix_expression() == f'fetchurl {{ url = "{url}"; sha256 = "{sha256}"; }}'
+
+
+def test_git_source(git_source: GitSource, url: str, rev: str, sha256: str):
+ assert git_source.url == url
+ assert git_source.sha256 == sha256
+ assert git_source.rev == rev
+
+
+def test_git_source_nix_expression(git_source: GitSource, url: str, rev: str, sha256: str):
+ assert git_source.get_nix_expression() == f'fetchgit {{ url = "{url}"; rev = "{rev}"; sha256 = "{sha256}"; }}'
+
+
+def test_license_github():
+ github_license = "MIT"
+ license = License.from_spdx_id(github_license)
+ assert license == License.MIT
+
+
+def test_license_gitlab():
+ gitlab_license = "mit"
+ license = License.from_spdx_id(gitlab_license)
+ assert license == License.MIT
diff --git a/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/tests/test_plugin.py b/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/tests/test_plugin.py
new file mode 100644
index 00000000..27d1a8db
--- /dev/null
+++ b/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/tests/test_plugin.py
@@ -0,0 +1,146 @@
+import json
+from typing import Callable
+
+import pytest
+from pytest_mock import MockFixture
+
+from update_vim_plugins.nix import License, Source, UrlSource
+from update_vim_plugins.plugin import GitHubPlugin, VimPlugin
+from update_vim_plugins.spec import PluginSpec
+
+from .fixtures import sha256, url, url_source
+
+
+@pytest.fixture()
+def mock_source(sha256: str):
+ class MockSource:
+ def __init__(self, *args, **kwargs):
+ pass
+
+ def get_nix_expression(self):
+ return "src"
+
+ return MockSource()
+
+
+@pytest.fixture()
+def mock_plugin(mock_source):
+ class MockVimPlugin(VimPlugin):
+ def __init__(self):
+ self.name = "test"
+ self.version = "1.0.0"
+ self.source = mock_source
+ self.description = "No description"
+ self.homepage = "https://example.com"
+ self.license = License.UNKNOWN
+
+ return MockVimPlugin()
+
+
+def test_vim_plugin_nix_expression(mock_plugin):
+ assert (
+ mock_plugin.get_nix_expression()
+ == 'test = buildVimPluginFrom2Nix { pname = "test"; version = "1.0.0"; src = src; meta = with lib; { description = "No description"; homepage = "https://example.com"; license = with licenses; [ ]; }; };'
+ )
+
+
+class MockResponse:
+ def __init__(self, status_code: int, content: bytes):
+ self.status_code = status_code
+ self.content = content
+
+ def json(self):
+ return json.loads(self.content)
+
+
+def mock_request_get(repsonses: dict[str, MockResponse]):
+ respones_not_found = MockResponse(404, b'{"message": "Not Found"}')
+
+ def mock_get(url: str, *args, **kwargs):
+ return repsonses.get(url, respones_not_found)
+
+ return mock_get
+
+
+@pytest.fixture()
+def github_commits_response():
+ return MockResponse(
+ 200,
+ json.dumps(
+ {
+ "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e",
+ "commit": {
+ "committer": {
+ "date": "2011-04-14T16:00:49Z",
+ },
+ },
+ }
+ ),
+ )
+
+
+@pytest.fixture()
+def github_get(github_commits_response: MockResponse):
+ repos_response = MockResponse(
+ 200,
+ json.dumps(
+ {
+ "html_url": "https://github.com/octocat/Hello-World",
+ "description": "This your first repo!",
+ "fork": False,
+ "default_branch": "master",
+ "license": {
+ "spdx_id": "MIT",
+ },
+ }
+ ),
+ )
+ responses = {
+ "https://api.github.com/repos/octocat/Hello-World": repos_response,
+ "https://api.github.com/repos/octocat/Hello-World/commits/master": github_commits_response,
+ }
+ return mock_request_get(responses)
+
+
+@pytest.fixture()
+def github_get_no_license(github_commits_response: MockResponse):
+ repos_response = MockResponse(
+ 200,
+ json.dumps(
+ {
+ "html_url": "https://github.com/octocat/Hello-World",
+ "description": "This your first repo!",
+ "fork": False,
+ "default_branch": "master",
+ }
+ ),
+ )
+ responses = {
+ "https://api.github.com/repos/octocat/Hello-World": repos_response,
+ "https://api.github.com/repos/octocat/Hello-World/commits/master": github_commits_response,
+ }
+ return mock_request_get(responses)
+
+
+def test_github_plugin(mocker: MockFixture, github_get: Callable, url_source: UrlSource):
+ mocker.patch("requests.get", github_get)
+ url_source = mocker.patch("update_vim_plugins.nix.UrlSource", url_source)
+
+ spec = PluginSpec.from_spec("octocat/Hello-World")
+ plugin = GitHubPlugin(spec)
+
+ assert plugin.name == "Hello-World"
+ assert plugin.version == "2011-04-14"
+ assert plugin.description == "This your first repo!"
+ assert plugin.homepage == "https://github.com/octocat/Hello-World"
+ assert plugin.license == License.MIT
+
+
+def test_github_plugin_no_license(mocker: MockFixture, github_get_no_license: Callable, url_source: UrlSource):
+ mocker.patch("requests.get", github_get_no_license)
+ url_source = mocker.patch("update_vim_plugins.nix.UrlSource", url_source)
+
+ spec = PluginSpec.from_spec("octocat/Hello-World")
+ plugin = GitHubPlugin(spec)
+
+ assert plugin.license == License.UNKNOWN
diff --git a/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/tests/test_spec.py b/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/tests/test_spec.py
new file mode 100644
index 00000000..2b9a1d24
--- /dev/null
+++ b/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/tests/test_spec.py
@@ -0,0 +1,136 @@
+import pytest
+
+from update_vim_plugins.spec import PluginSpec, RepositoryHost
+
+
+@pytest.fixture()
+def owner():
+ return "owner"
+
+
+@pytest.fixture()
+def repo():
+ return "repo.nvim"
+
+
+@pytest.fixture()
+def branch():
+ return "main"
+
+
+@pytest.fixture()
+def name():
+ return "repo-nvim"
+
+
+@pytest.fixture()
+def license():
+ return "mit"
+
+
+def test_from_spec_simple(owner: str, repo: str):
+ vim_plugin = PluginSpec.from_spec(f"{owner}/{repo}")
+
+ assert vim_plugin.owner == owner
+ assert vim_plugin.repo == repo
+
+
+def test_from_spec_with_gitref(owner: str, repo: str, branch: str):
+ vim_plugin = PluginSpec.from_spec(f"{owner}/{repo}:{branch}")
+
+ assert vim_plugin.branch == branch
+
+
+def test_from_spec_with_name(owner: str, repo: str, name: str):
+ vim_plugin = PluginSpec.from_spec(f"{owner}/{repo}::{name}")
+
+ assert vim_plugin.name == name
+
+
+@pytest.mark.parametrize("host", RepositoryHost)
+def test_from_spec_with_repository_host(owner: str, repo: str, host: RepositoryHost):
+ vim_plugin = PluginSpec.from_spec(f"{host.value}:{owner}/{repo}")
+
+ assert vim_plugin.repository_host == host
+
+
+def test_from_spec_without_repository_host(owner: str, repo: str):
+ vim_plugin = PluginSpec.from_spec(f"{owner}/{repo}")
+
+ assert vim_plugin.repository_host == RepositoryHost.GITHUB
+
+
+def test_from_spec_complex(owner: str, repo: str, branch: str, name: str):
+ vim_plugin = PluginSpec.from_spec(f"gitlab:{owner}/{repo}:{branch}:{name}")
+
+ assert vim_plugin.repository_host == RepositoryHost.GITLAB
+ assert vim_plugin.owner == owner
+ assert vim_plugin.repo == repo
+ assert vim_plugin.branch == branch
+ assert vim_plugin.name == name
+
+
+def test_from_spec_invalid_spec():
+ with pytest.raises(ValueError):
+ PluginSpec.from_spec("invalid_spec")
+
+
+def test_to_spec_simple(owner: str, repo: str):
+ vim_plugin = PluginSpec(RepositoryHost.GITHUB, owner, repo)
+
+ assert vim_plugin.to_spec() == f"{owner}/{repo}"
+
+
+def test_to_spec_with_branch(owner: str, repo: str, branch: str):
+ vim_plugin = PluginSpec(RepositoryHost.GITHUB, owner, repo, branch=branch)
+ assert vim_plugin.to_spec() == f"{owner}/{repo}:{branch}"
+
+
+def test_to_spec_with_name(owner: str, repo: str, name: str):
+ vim_plugin = PluginSpec(RepositoryHost.GITHUB, owner, repo, name=name)
+
+ assert vim_plugin.to_spec() == f"{owner}/{repo}::{name}"
+
+
+@pytest.mark.parametrize("host", [RepositoryHost.GITLAB, RepositoryHost.SOURCEHUT])
+def test_to_spec_with_repository_host(host: RepositoryHost, owner: str, repo: str):
+ vim_plugin = PluginSpec(host, owner, repo)
+
+ assert vim_plugin.to_spec() == f"{host.value}:{owner}/{repo}"
+
+
+def test_to_spec_complex(owner: str, repo: str, branch: str, name: str, license: str):
+ vim_plugin = PluginSpec(RepositoryHost.GITLAB, owner, repo, branch=branch, name=name, license=license)
+
+ assert vim_plugin.to_spec() == f"gitlab:{owner}/{repo}:{branch}:{name}:{license}"
+
+
+def test_spec_equal(owner: str, repo: str):
+ vim_plugin = PluginSpec(RepositoryHost.GITHUB, owner, repo)
+ vim_plugin2 = PluginSpec(RepositoryHost.GITHUB, owner, repo)
+
+ assert vim_plugin == vim_plugin2
+
+
+def test_spec_not_equal_different_branch(owner: str, repo: str):
+ vim_plugin = PluginSpec(RepositoryHost.GITHUB, owner, repo)
+ vim_plugin2 = PluginSpec(RepositoryHost.GITHUB, owner, repo, branch="main")
+
+ assert vim_plugin != vim_plugin2
+
+
+def test_spec_not_equal_different_name(owner: str, repo: str):
+ vim_plugin = PluginSpec(RepositoryHost.GITHUB, owner, repo)
+ vim_plugin2 = PluginSpec(RepositoryHost.GITHUB, owner, repo, name="renamed")
+
+ assert vim_plugin != vim_plugin2
+
+
+def test_spec_equal_same_normalized_name(owner: str):
+ repo = "repo.nvim"
+ name = "repo-nvim"
+
+ vim_plugin = PluginSpec(RepositoryHost.GITHUB, owner, repo)
+ vim_plugin2 = PluginSpec(RepositoryHost.GITHUB, owner, repo, name=name)
+
+ assert vim_plugin == vim_plugin2
diff --git a/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/update.py b/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/update.py
new file mode 100644
index 00000000..7eb3eeb4
--- /dev/null
+++ b/sys/nixpkgs/pkgs/update_vim_plugins/update_vim_plugins/update.py
@@ -0,0 +1,212 @@
+import subprocess
+from random import shuffle
+from cleo.helpers import argument, option
+from cleo.commands.command import Command
+from concurrent.futures import ThreadPoolExecutor, as_completed
+
+from pprint import pprint
+
+from .plugin import plugin_from_spec
+
+from .helpers import read_manifest_to_spec, get_const
+from .helpers import JSON_FILE, PLUGINS_LIST_FILE, PKGS_FILE
+
+import json
+import jsonpickle
+
+jsonpickle.set_encoder_options("json", sort_keys=True)
+
+
+class UpdateCommand(Command):
+ name = "update"
+ description = "Generate nix module from input file"
+ arguments = [argument("plug_dir", description="Path to the plugin directory", optional=False)]
+ options = [
+ option("all", "a", description="Update all plugins. Else only update new plugins", flag=True),
+ option("dry-run", "d", description="Show which plugins would be updated", flag=True),
+ ]
+
+ def handle(self):
+ """Main command function"""
+
+ plug_dir = self.argument("plug_dir")
+ self.specs = read_manifest_to_spec(plug_dir)
+
+ if self.option("all"):
+ # update all plugins
+ spec_list = self.specs
+ known_plugins = []
+ else:
+ # filter plugins we already know
+ spec_list = self.specs
+
+ with open(get_const(JSON_FILE, plug_dir), "r") as json_file:
+ data = json.load(json_file)
+
+ known_specs = list(filter(lambda x: x.line in data, spec_list))
+ known_plugins = [jsonpickle.decode(data[x.line]) for x in known_specs]
+
+ spec_list = list(filter(lambda x: x.line not in data, spec_list))
+
+ if self.option("dry-run"):
+ self.line("<comment>These plugins would be updated</comment>")
+ pprint(spec_list)
+ self.line(f"<info>Total:</info> {len(spec_list)}")
+ exit(0)
+
+ processed_plugins, failed_plugins, failed_but_known = self.process_manifest(spec_list, plug_dir)
+
+ processed_plugins += known_plugins # add plugins from .plugins.json
+ processed_plugins: list = sorted(set(processed_plugins)) # remove duplicates based only on source line
+
+ self.check_duplicates(processed_plugins)
+
+ if failed_plugins != []:
+ self.line("<error>Not processed:</error> The following plugins could not be updated")
+ for s, e in failed_plugins:
+ self.line(f" - {s!r} - {e}")
+
+ if failed_but_known != []:
+ self.line(
+ "<error>Not updated:</error> The following plugins could not be updated but an older version is known"
+ )
+ for s, e in failed_but_known:
+ self.line(f" - {s!r} - {e}")
+
+ # update plugin "database"
+ self.write_plugins_json(processed_plugins, plug_dir)
+
+ # generate output
+ self.write_plugins_nix(processed_plugins, plug_dir)
+
+ self.write_plugins_markdown(processed_plugins, plug_dir)
+
+ self.line("<comment>Done</comment>")
+
+ def write_plugins_markdown(self, plugins, plug_dir):
+ """Write the list of all plugins to PLUGINS_LIST_FILE in markdown"""
+
+ plugins.sort()
+
+ self.line("<info>Updating plugins.md</info>")
+
+ header = f" - Plugin count: {len(plugins)}\n\n| Repo | Last Update | Nix package name | Last checked |\n|:---|:---|:---|:---|\n"
+
+ with open(get_const(PLUGINS_LIST_FILE, plug_dir), "w") as file:
+ file.write(header)
+ for plugin in plugins:
+ file.write(f"{plugin.to_markdown()}\n")
+
+ def write_plugins_nix(self, plugins, plug_dir):
+ self.line("<info>Generating nix output</info>")
+
+ plugins.sort()
+
+ header = "{ lib, buildVimPlugin, fetchurl, fetchgit }: {"
+ footer = "}"
+
+ with open(get_const(PKGS_FILE, plug_dir), "w") as file:
+ file.write(header)
+ for plugin in plugins:
+ file.write(f"{plugin.to_nix()}\n")
+ file.write(footer)
+
+ self.line("<info>Formatting nix output</info>")
+
+ subprocess.run(
+ ["alejandra", get_const(PKGS_FILE, plug_dir)],
+ stdout=subprocess.DEVNULL,
+ stderr=subprocess.DEVNULL,
+ )
+
+ def write_plugins_json(self, plugins, plug_dir):
+ self.line("<info>Storing results in .plugins.json</info>")
+
+ plugins.sort()
+
+ with open(get_const(JSON_FILE, plug_dir), "r+") as json_file:
+ data = json.load(json_file)
+
+ for plugin in plugins:
+ data.update({f"{plugin.source_line}": plugin.to_json()})
+
+ json_file.seek(0)
+ json_file.write(json.dumps(data, indent=2, sort_keys=True))
+ json_file.truncate()
+
+ def check_duplicates(self, plugins):
+ """check for duplicates in proccesed_plugins"""
+ error = False
+ for i, plugin in enumerate(plugins):
+ for p in plugins[i + 1 :]:
+ if plugin.name == p.name:
+ self.line(
+ f"<error>Error:</error> The following two lines produce the same plugin name:\n - {plugin.source_line}\n - {p.source_line}\n -> {p.name}"
+ )
+ error = True
+
+ # We want to exit if the resulting nix file would be broken
+ # But we want to go through all plugins before we do so
+ if error:
+ exit(1)
+
+ def generate_plugin(self, spec, i, size, plug_dir):
+ debug_string = ""
+
+ processed_plugin = None
+ failed_but_known = None
+ failed_plugin = None
+ try:
+ debug_string += f" - <info>({i+1}/{size}) Processing</info> {spec!r}\n"
+ vim_plugin = plugin_from_spec(spec)
+ debug_string += f" • <comment>Success</comment> {vim_plugin!r}\n"
+ processed_plugin = vim_plugin
+ except Exception as e:
+ debug_string += f" • <error>Error:</error> Could not update <info>{spec.name}</info>. Keeping old values. Reason: {e}\n"
+ with open(get_const(JSON_FILE, plug_dir), "r") as json_file:
+ data = json.load(json_file)
+
+ plugin_json = data.get(spec.line)
+ if plugin_json:
+ vim_plugin = jsonpickle.decode(plugin_json)
+ processed_plugin = vim_plugin
+ failed_but_known = (vim_plugin, e)
+ else:
+ debug_string += f" • <error>Error:</error> No entries for <info>{spec.name}</info> in '.plugins.json'. Skipping...\n"
+ failed_plugin = (spec, e)
+
+ self.line(debug_string.strip())
+
+ return processed_plugin, failed_plugin, failed_but_known
+
+ def process_manifest(self, spec_list, plug_dir):
+ """Read specs in 'spec_list' and generate plugins"""
+
+ size = len(spec_list)
+
+ # We have to assume that we will reach an api limit. Therefore
+ # we randomize the spec list to give every entry the same change to be updated and
+ # not favor those at the start of the list
+ shuffle(spec_list)
+
+ with ThreadPoolExecutor() as executor:
+ futures = [
+ executor.submit(self.generate_plugin, spec, i, size, plug_dir) for i, spec in enumerate(spec_list)
+ ]
+ results = [future.result() for future in as_completed(futures)]
+
+ processed_plugins = [r[0] for r in results]
+ failed_plugins = [r[1] for r in results]
+ failed_but_known = [r[2] for r in results]
+
+ processed_plugins = list(filter(lambda x: x is not None, processed_plugins))
+ failed_plugins = list(filter(lambda x: x is not None, failed_plugins))
+ failed_but_known = list(filter(lambda x: x is not None, failed_but_known))
+
+ processed_plugins.sort()
+ failed_plugins.sort()
+ failed_but_known.sort()
+
+ assert len(processed_plugins) == len(spec_list) - len(failed_plugins)
+
+ return processed_plugins, failed_plugins, failed_but_known