From 204731c0a69136c9cebcb54f1afecf5145e26bbe Mon Sep 17 00:00:00 2001 From: Benedikt Peetz Date: Thu, 23 May 2024 13:26:22 +0200 Subject: refactor(pkgs): Categorize into `by-name` shards This might not be the perfect way to organize a package set -- especially if the set is not nearly the size of nixpkgs -- but it is _at_ least a way of organization. --- pkgs/by-name/up/update-vim-plugins/.envrc | 1 + .../up/update-vim-plugins/check-duplicates.sh | 43 ++ pkgs/by-name/up/update-vim-plugins/flake.lock | 61 ++ pkgs/by-name/up/update-vim-plugins/flake.nix | 24 + pkgs/by-name/up/update-vim-plugins/package.nix | 47 ++ pkgs/by-name/up/update-vim-plugins/poetry.lock | 680 +++++++++++++++++++++ pkgs/by-name/up/update-vim-plugins/pyproject.toml | 45 ++ pkgs/by-name/up/update-vim-plugins/update.sh | 5 + .../update_vim_plugins/__init__.py | 0 .../update_vim_plugins/__main__.py | 15 + .../update_vim_plugins/cleanup.py | 100 +++ .../update_vim_plugins/helpers.py | 61 ++ .../update-vim-plugins/update_vim_plugins/nix.py | 121 ++++ .../update_vim_plugins/plugin.py | 182 ++++++ .../update-vim-plugins/update_vim_plugins/spec.py | 143 +++++ .../update_vim_plugins/tests/__init__.py | 0 .../update_vim_plugins/tests/fixtures.py | 44 ++ .../update_vim_plugins/tests/test_nix.py | 32 + .../update_vim_plugins/tests/test_plugin.py | 144 +++++ .../update_vim_plugins/tests/test_spec.py | 136 +++++ .../update_vim_plugins/update.py | 212 +++++++ 21 files changed, 2096 insertions(+) create mode 100644 pkgs/by-name/up/update-vim-plugins/.envrc create mode 100755 pkgs/by-name/up/update-vim-plugins/check-duplicates.sh create mode 100644 pkgs/by-name/up/update-vim-plugins/flake.lock create mode 100644 pkgs/by-name/up/update-vim-plugins/flake.nix create mode 100644 pkgs/by-name/up/update-vim-plugins/package.nix create mode 100644 pkgs/by-name/up/update-vim-plugins/poetry.lock create mode 100644 pkgs/by-name/up/update-vim-plugins/pyproject.toml create mode 100755 pkgs/by-name/up/update-vim-plugins/update.sh create mode 100644 pkgs/by-name/up/update-vim-plugins/update_vim_plugins/__init__.py create mode 100644 pkgs/by-name/up/update-vim-plugins/update_vim_plugins/__main__.py create mode 100644 pkgs/by-name/up/update-vim-plugins/update_vim_plugins/cleanup.py create mode 100644 pkgs/by-name/up/update-vim-plugins/update_vim_plugins/helpers.py create mode 100644 pkgs/by-name/up/update-vim-plugins/update_vim_plugins/nix.py create mode 100644 pkgs/by-name/up/update-vim-plugins/update_vim_plugins/plugin.py create mode 100644 pkgs/by-name/up/update-vim-plugins/update_vim_plugins/spec.py create mode 100644 pkgs/by-name/up/update-vim-plugins/update_vim_plugins/tests/__init__.py create mode 100644 pkgs/by-name/up/update-vim-plugins/update_vim_plugins/tests/fixtures.py create mode 100644 pkgs/by-name/up/update-vim-plugins/update_vim_plugins/tests/test_nix.py create mode 100644 pkgs/by-name/up/update-vim-plugins/update_vim_plugins/tests/test_plugin.py create mode 100644 pkgs/by-name/up/update-vim-plugins/update_vim_plugins/tests/test_spec.py create mode 100644 pkgs/by-name/up/update-vim-plugins/update_vim_plugins/update.py (limited to 'pkgs/by-name/up/update-vim-plugins') diff --git a/pkgs/by-name/up/update-vim-plugins/.envrc b/pkgs/by-name/up/update-vim-plugins/.envrc new file mode 100644 index 00000000..3550a30f --- /dev/null +++ b/pkgs/by-name/up/update-vim-plugins/.envrc @@ -0,0 +1 @@ +use flake diff --git a/pkgs/by-name/up/update-vim-plugins/check-duplicates.sh b/pkgs/by-name/up/update-vim-plugins/check-duplicates.sh new file mode 100755 index 00000000..781b8aeb --- /dev/null +++ b/pkgs/by-name/up/update-vim-plugins/check-duplicates.sh @@ -0,0 +1,43 @@ +#!/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 # do not add " " here. It would break the plugin + 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/pkgs/by-name/up/update-vim-plugins/flake.lock b/pkgs/by-name/up/update-vim-plugins/flake.lock new file mode 100644 index 00000000..50494465 --- /dev/null +++ b/pkgs/by-name/up/update-vim-plugins/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1715087517, + "narHash": "sha256-CLU5Tsg24Ke4+7sH8azHWXKd0CFd4mhLWfhYgUiDBpQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "b211b392b8486ee79df6cdfb1157ad2133427a29", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/pkgs/by-name/up/update-vim-plugins/flake.nix b/pkgs/by-name/up/update-vim-plugins/flake.nix new file mode 100644 index 00000000..ef440af0 --- /dev/null +++ b/pkgs/by-name/up/update-vim-plugins/flake.nix @@ -0,0 +1,24 @@ +{ + description = "update_vim_plugins"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { + self, + nixpkgs, + flake-utils, + }: (flake-utils.lib.eachDefaultSystem (system: let + pkgs = nixpkgs.legacyPackages.${system}; + in { + devShells.default = pkgs.mkShell { + packages = [ + pkgs.python3 + pkgs.poetry + ]; + }; + })); +} diff --git a/pkgs/by-name/up/update-vim-plugins/package.nix b/pkgs/by-name/up/update-vim-plugins/package.nix new file mode 100644 index 00000000..e74a29b1 --- /dev/null +++ b/pkgs/by-name/up/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/pkgs/by-name/up/update-vim-plugins/poetry.lock b/pkgs/by-name/up/update-vim-plugins/poetry.lock new file mode 100644 index 00000000..f4764b42 --- /dev/null +++ b/pkgs/by-name/up/update-vim-plugins/poetry.lock @@ -0,0 +1,680 @@ +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. + +[[package]] +name = "certifi" +version = "2024.2.2" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, + {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.3.2" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, +] + +[[package]] +name = "cleo" +version = "2.1.0" +description = "Cleo allows you to create beautiful and testable command-line interfaces." +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "cleo-2.1.0-py3-none-any.whl", hash = "sha256:4a31bd4dd45695a64ee3c4758f583f134267c2bc518d8ae9a29cf237d009b07e"}, + {file = "cleo-2.1.0.tar.gz", hash = "sha256:0b2c880b5d13660a7ea651001fb4acb527696c01f15c9ee650f377aa543fd523"}, +] + +[package.dependencies] +crashtest = ">=0.4.1,<0.5.0" +rapidfuzz = ">=3.0.0,<4.0.0" + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +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.5.1" +description = "Code coverage measurement for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "coverage-7.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c0884920835a033b78d1c73b6d3bbcda8161a900f38a488829a83982925f6c2e"}, + {file = "coverage-7.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:39afcd3d4339329c5f58de48a52f6e4e50f6578dd6099961cf22228feb25f38f"}, + {file = "coverage-7.5.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a7b0ceee8147444347da6a66be737c9d78f3353b0681715b668b72e79203e4a"}, + {file = "coverage-7.5.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a9ca3f2fae0088c3c71d743d85404cec8df9be818a005ea065495bedc33da35"}, + {file = "coverage-7.5.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd215c0c7d7aab005221608a3c2b46f58c0285a819565887ee0b718c052aa4e"}, + {file = "coverage-7.5.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4bf0655ab60d754491004a5efd7f9cccefcc1081a74c9ef2da4735d6ee4a6223"}, + {file = "coverage-7.5.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:61c4bf1ba021817de12b813338c9be9f0ad5b1e781b9b340a6d29fc13e7c1b5e"}, + {file = "coverage-7.5.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:db66fc317a046556a96b453a58eced5024af4582a8dbdc0c23ca4dbc0d5b3146"}, + {file = "coverage-7.5.1-cp310-cp310-win32.whl", hash = "sha256:b016ea6b959d3b9556cb401c55a37547135a587db0115635a443b2ce8f1c7228"}, + {file = "coverage-7.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:df4e745a81c110e7446b1cc8131bf986157770fa405fe90e15e850aaf7619bc8"}, + {file = "coverage-7.5.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:796a79f63eca8814ca3317a1ea443645c9ff0d18b188de470ed7ccd45ae79428"}, + {file = "coverage-7.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4fc84a37bfd98db31beae3c2748811a3fa72bf2007ff7902f68746d9757f3746"}, + {file = "coverage-7.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6175d1a0559986c6ee3f7fccfc4a90ecd12ba0a383dcc2da30c2b9918d67d8a3"}, + {file = "coverage-7.5.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fc81d5878cd6274ce971e0a3a18a8803c3fe25457165314271cf78e3aae3aa2"}, + {file = "coverage-7.5.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:556cf1a7cbc8028cb60e1ff0be806be2eded2daf8129b8811c63e2b9a6c43bca"}, + {file = "coverage-7.5.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9981706d300c18d8b220995ad22627647be11a4276721c10911e0e9fa44c83e8"}, + {file = "coverage-7.5.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d7fed867ee50edf1a0b4a11e8e5d0895150e572af1cd6d315d557758bfa9c057"}, + {file = "coverage-7.5.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ef48e2707fb320c8f139424a596f5b69955a85b178f15af261bab871873bb987"}, + {file = "coverage-7.5.1-cp311-cp311-win32.whl", hash = "sha256:9314d5678dcc665330df5b69c1e726a0e49b27df0461c08ca12674bcc19ef136"}, + {file = "coverage-7.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:5fa567e99765fe98f4e7d7394ce623e794d7cabb170f2ca2ac5a4174437e90dd"}, + {file = "coverage-7.5.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b6cf3764c030e5338e7f61f95bd21147963cf6aa16e09d2f74f1fa52013c1206"}, + {file = "coverage-7.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ec92012fefebee89a6b9c79bc39051a6cb3891d562b9270ab10ecfdadbc0c34"}, + {file = "coverage-7.5.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16db7f26000a07efcf6aea00316f6ac57e7d9a96501e990a36f40c965ec7a95d"}, + {file = "coverage-7.5.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:beccf7b8a10b09c4ae543582c1319c6df47d78fd732f854ac68d518ee1fb97fa"}, + {file = "coverage-7.5.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8748731ad392d736cc9ccac03c9845b13bb07d020a33423fa5b3a36521ac6e4e"}, + {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7352b9161b33fd0b643ccd1f21f3a3908daaddf414f1c6cb9d3a2fd618bf2572"}, + {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:7a588d39e0925f6a2bff87154752481273cdb1736270642aeb3635cb9b4cad07"}, + {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:68f962d9b72ce69ea8621f57551b2fa9c70509af757ee3b8105d4f51b92b41a7"}, + {file = "coverage-7.5.1-cp312-cp312-win32.whl", hash = "sha256:f152cbf5b88aaeb836127d920dd0f5e7edff5a66f10c079157306c4343d86c19"}, + {file = "coverage-7.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:5a5740d1fb60ddf268a3811bcd353de34eb56dc24e8f52a7f05ee513b2d4f596"}, + {file = "coverage-7.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e2213def81a50519d7cc56ed643c9e93e0247f5bbe0d1247d15fa520814a7cd7"}, + {file = "coverage-7.5.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5037f8fcc2a95b1f0e80585bd9d1ec31068a9bcb157d9750a172836e98bc7a90"}, + {file = "coverage-7.5.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3721c2c9e4c4953a41a26c14f4cef64330392a6d2d675c8b1db3b645e31f0e"}, + {file = "coverage-7.5.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca498687ca46a62ae590253fba634a1fe9836bc56f626852fb2720f334c9e4e5"}, + {file = "coverage-7.5.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0cdcbc320b14c3e5877ee79e649677cb7d89ef588852e9583e6b24c2e5072661"}, + {file = "coverage-7.5.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:57e0204b5b745594e5bc14b9b50006da722827f0b8c776949f1135677e88d0b8"}, + {file = "coverage-7.5.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8fe7502616b67b234482c3ce276ff26f39ffe88adca2acf0261df4b8454668b4"}, + {file = "coverage-7.5.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:9e78295f4144f9dacfed4f92935fbe1780021247c2fabf73a819b17f0ccfff8d"}, + {file = "coverage-7.5.1-cp38-cp38-win32.whl", hash = "sha256:1434e088b41594baa71188a17533083eabf5609e8e72f16ce8c186001e6b8c41"}, + {file = "coverage-7.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:0646599e9b139988b63704d704af8e8df7fa4cbc4a1f33df69d97f36cb0a38de"}, + {file = "coverage-7.5.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4cc37def103a2725bc672f84bd939a6fe4522310503207aae4d56351644682f1"}, + {file = "coverage-7.5.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fc0b4d8bfeabd25ea75e94632f5b6e047eef8adaed0c2161ada1e922e7f7cece"}, + {file = "coverage-7.5.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d0a0f5e06881ecedfe6f3dd2f56dcb057b6dbeb3327fd32d4b12854df36bf26"}, + {file = "coverage-7.5.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9735317685ba6ec7e3754798c8871c2f49aa5e687cc794a0b1d284b2389d1bd5"}, + {file = "coverage-7.5.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d21918e9ef11edf36764b93101e2ae8cc82aa5efdc7c5a4e9c6c35a48496d601"}, + {file = "coverage-7.5.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c3e757949f268364b96ca894b4c342b41dc6f8f8b66c37878aacef5930db61be"}, + {file = "coverage-7.5.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:79afb6197e2f7f60c4824dd4b2d4c2ec5801ceb6ba9ce5d2c3080e5660d51a4f"}, + {file = "coverage-7.5.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d1d0d98d95dd18fe29dc66808e1accf59f037d5716f86a501fc0256455219668"}, + {file = "coverage-7.5.1-cp39-cp39-win32.whl", hash = "sha256:1cc0fe9b0b3a8364093c53b0b4c0c2dd4bb23acbec4c9240b5f284095ccf7981"}, + {file = "coverage-7.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:dde0070c40ea8bb3641e811c1cfbf18e265d024deff6de52c5950677a8fb1e0f"}, + {file = "coverage-7.5.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:6537e7c10cc47c595828b8a8be04c72144725c383c4702703ff4e42e44577312"}, + {file = "coverage-7.5.1.tar.gz", hash = "sha256:54de9ef3a9da981f7af93eafde4ede199e0846cd819eb27c88e2b712aae9708c"}, +] + +[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" +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 = "dateparser" +version = "1.2.0" +description = "Date parsing library designed to parse dates from HTML pages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "dateparser-1.2.0-py2.py3-none-any.whl", hash = "sha256:0b21ad96534e562920a0083e97fd45fa959882d4162acc358705144520a35830"}, + {file = "dateparser-1.2.0.tar.gz", hash = "sha256:7975b43a4222283e0ae15be7b4999d08c9a70e2d378ac87385b1ccf2cffbbb30"}, +] + +[package.dependencies] +python-dateutil = "*" +pytz = "*" +regex = "<2019.02.19 || >2019.02.19,<2021.8.27 || >2021.8.27" +tzlocal = "*" + +[package.extras] +calendars = ["convertdate", "hijri-converter"] +fasttext = ["fasttext"] +langdetect = ["langdetect"] + +[[package]] +name = "exceptiongroup" +version = "1.2.1" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"}, + {file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "idna" +version = "3.7" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, + {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, +] + +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +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 = "jsonpickle" +version = "3.0.4" +description = "Serialize any Python object to JSON" +optional = false +python-versions = ">=3.7" +files = [ + {file = "jsonpickle-3.0.4-py3-none-any.whl", hash = "sha256:04ae7567a14269579e3af66b76bda284587458d7e8a204951ca8f71a3309952e"}, + {file = "jsonpickle-3.0.4.tar.gz", hash = "sha256:a1b14c8d6221cd8f394f2a97e735ea1d7edc927fbd135b26f2f8700657c8c62b"}, +] + +[package.extras] +docs = ["furo", "rst.linker (>=1.9)", "sphinx"] +packaging = ["build", "twine"] +testing = ["bson", "ecdsa", "feedparser", "gmpy2", "numpy", "pandas", "pymongo", "pytest (>=3.5,!=3.7.3)", "pytest-benchmark", "pytest-benchmark[histogram]", "pytest-checkdocs (>=1.2.3)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-ruff (>=0.2.1)", "scikit-learn", "scipy", "scipy (>=1.9.3)", "simplejson", "sqlalchemy", "ujson"] + +[[package]] +name = "packaging" +version = "24.0" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"}, + {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, +] + +[[package]] +name = "pluggy" +version = "1.5.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "pytest" +version = "7.4.4" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, + {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, +] + +[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", "setuptools", "xmlschema"] + +[[package]] +name = "pytest-cov" +version = "4.1.0" +description = "Pytest plugin for measuring coverage." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, + {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, +] + +[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.14.0" +description = "Thin-wrapper around the mock package for easier use with pytest" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0"}, + {file = "pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f"}, +] + +[package.dependencies] +pytest = ">=6.2.5" + +[package.extras] +dev = ["pre-commit", "pytest-asyncio", "tox"] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "pytz" +version = "2024.1" +description = "World timezone definitions, modern and historical" +optional = false +python-versions = "*" +files = [ + {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, + {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, +] + +[[package]] +name = "rapidfuzz" +version = "3.9.0" +description = "rapid fuzzy string matching" +optional = false +python-versions = ">=3.8" +files = [ + {file = "rapidfuzz-3.9.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:bd375c4830fee11d502dd93ecadef63c137ae88e1aaa29cc15031fa66d1e0abb"}, + {file = "rapidfuzz-3.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:55e2c5076f38fc1dbaacb95fa026a3e409eee6ea5ac4016d44fb30e4cad42b20"}, + {file = "rapidfuzz-3.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:488f74126904db6b1bea545c2f3567ea882099f4c13f46012fe8f4b990c683df"}, + {file = "rapidfuzz-3.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3f2d1ea7cd57dfcd34821e38b4924c80a31bcf8067201b1ab07386996a9faee"}, + {file = "rapidfuzz-3.9.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b11e602987bcb4ea22b44178851f27406fca59b0836298d0beb009b504dba266"}, + {file = "rapidfuzz-3.9.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3083512e9bf6ed2bb3d25883922974f55e21ae7f8e9f4e298634691ae1aee583"}, + {file = "rapidfuzz-3.9.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b33c6d4b3a1190bc0b6c158c3981535f9434e8ed9ffa40cf5586d66c1819fb4b"}, + {file = "rapidfuzz-3.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dcb95fde22f98e6d0480db8d6038c45fe2d18a338690e6f9bba9b82323f3469"}, + {file = "rapidfuzz-3.9.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:08d8b49b3a4fb8572e480e73fcddc750da9cbb8696752ee12cca4bf8c8220d52"}, + {file = "rapidfuzz-3.9.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e721842e6b601ebbeb8cc5e12c75bbdd1d9e9561ea932f2f844c418c31256e82"}, + {file = "rapidfuzz-3.9.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7988363b3a415c5194ce1a68d380629247f8713e669ad81db7548eb156c4f365"}, + {file = "rapidfuzz-3.9.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:2d267d4c982ab7d177e994ab1f31b98ff3814f6791b90d35dda38307b9e7c989"}, + {file = "rapidfuzz-3.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0bb28ab5300cf974c7eb68ea21125c493e74b35b1129e629533468b2064ae0a2"}, + {file = "rapidfuzz-3.9.0-cp310-cp310-win32.whl", hash = "sha256:1b1f74997b6d94d66375479fa55f70b1c18e4d865d7afcd13f0785bfd40a9d3c"}, + {file = "rapidfuzz-3.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:c56d2efdfaa1c642029f3a7a5bb76085c5531f7a530777be98232d2ce142553c"}, + {file = "rapidfuzz-3.9.0-cp310-cp310-win_arm64.whl", hash = "sha256:6a83128d505cac76ea560bb9afcb3f6986e14e50a6f467db9a31faef4bd9b347"}, + {file = "rapidfuzz-3.9.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e2218d62ab63f3c5ad48eced898854d0c2c327a48f0fb02e2288d7e5332a22c8"}, + {file = "rapidfuzz-3.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:36bf35df2d6c7d5820da20a6720aee34f67c15cd2daf8cf92e8141995c640c25"}, + {file = "rapidfuzz-3.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:905b01a9b633394ff6bb5ebb1c5fd660e0e180c03fcf9d90199cc6ed74b87cf7"}, + {file = "rapidfuzz-3.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33cfabcb7fd994938a6a08e641613ce5fe46757832edc789c6a5602e7933d6fa"}, + {file = "rapidfuzz-3.9.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1179dcd3d150a67b8a678cd9c84f3baff7413ff13c9e8fe85e52a16c97e24c9b"}, + {file = "rapidfuzz-3.9.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:47d97e28c42f1efb7781993b67c749223f198f6653ef177a0c8f2b1c516efcaf"}, + {file = "rapidfuzz-3.9.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28da953eb2ef9ad527e536022da7afff6ace7126cdd6f3e21ac20f8762e76d2c"}, + {file = "rapidfuzz-3.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:182b4e11de928fb4834e8f8b5ecd971b5b10a86fabe8636ab65d3a9b7e0e9ca7"}, + {file = "rapidfuzz-3.9.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c74f2da334ce597f31670db574766ddeaee5d9430c2c00e28d0fbb7f76172036"}, + {file = "rapidfuzz-3.9.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:014ac55b03f4074f903248ded181f3000f4cdbd134e6155cbf643f0eceb4f70f"}, + {file = "rapidfuzz-3.9.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c4ef34b2ddbf448f1d644b4ec6475df8bbe5b9d0fee173ff2e87322a151663bd"}, + {file = "rapidfuzz-3.9.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fc02157f521af15143fae88f92ef3ddcc4e0cff05c40153a9549dc0fbdb9adb3"}, + {file = "rapidfuzz-3.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ff08081c49b18ba253a99e6a47f492e6ee8019e19bbb6ddc3ed360cd3ecb2f62"}, + {file = "rapidfuzz-3.9.0-cp311-cp311-win32.whl", hash = "sha256:b9bf90b3d96925cbf8ef44e5ee3cf39ef0c422f12d40f7a497e91febec546650"}, + {file = "rapidfuzz-3.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:d5d5684f54d82d9b0cf0b2701e55a630527a9c3dd5ddcf7a2e726a475ac238f2"}, + {file = "rapidfuzz-3.9.0-cp311-cp311-win_arm64.whl", hash = "sha256:a2de844e0e971d7bd8aa41284627dbeacc90e750b90acfb016836553c7a63192"}, + {file = "rapidfuzz-3.9.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f81fe99a69ac8ee3fd905e70c62f3af033901aeb60b69317d1d43d547b46e510"}, + {file = "rapidfuzz-3.9.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:633b9d03fc04abc585c197104b1d0af04b1f1db1abc99f674d871224cd15557a"}, + {file = "rapidfuzz-3.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ab872cb57ae97c54ba7c71a9e3c9552beb57cb907c789b726895576d1ea9af6f"}, + {file = "rapidfuzz-3.9.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdd8c15c3a14e409507fdf0c0434ec481d85c6cbeec8bdcd342a8cd1eda03825"}, + {file = "rapidfuzz-3.9.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2444d8155d9846f206e2079bb355b85f365d9457480b0d71677a112d0a7f7128"}, + {file = "rapidfuzz-3.9.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f83bd3d01f04061c3660742dc85143a89d49fd23eb31eccbf60ad56c4b955617"}, + {file = "rapidfuzz-3.9.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ca799f882364e69d0872619afb19efa3652b7133c18352e4a3d86a324fb2bb1"}, + {file = "rapidfuzz-3.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6993d361f28b9ef5f0fa4e79b8541c2f3507be7471b9f9cb403a255e123b31e1"}, + {file = "rapidfuzz-3.9.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:170822a1b1719f02b58e3dce194c8ad7d4c5b39be38c0fdec603bd19c6f9cf81"}, + {file = "rapidfuzz-3.9.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:0e86e39c1c1a0816ceda836e6f7bd3743b930cbc51a43a81bb433b552f203f25"}, + {file = "rapidfuzz-3.9.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:731269812ea837e0b93d913648e404736407408e33a00b75741e8f27c590caa2"}, + {file = "rapidfuzz-3.9.0-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:8e5ff882d3a3d081157ceba7e0ebc7fac775f95b08cbb143accd4cece6043819"}, + {file = "rapidfuzz-3.9.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2003071aa633477a01509890c895f9ef56cf3f2eaa72c7ec0b567f743c1abcba"}, + {file = "rapidfuzz-3.9.0-cp312-cp312-win32.whl", hash = "sha256:13857f9070600ea1f940749f123b02d0b027afbaa45e72186df0f278915761d0"}, + {file = "rapidfuzz-3.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:134b7098ac109834eeea81424b6822f33c4c52bf80b81508295611e7a21be12a"}, + {file = "rapidfuzz-3.9.0-cp312-cp312-win_arm64.whl", hash = "sha256:2a96209f046fe328be30fc43f06e3d4b91f0d5b74e9dcd627dbfd65890fa4a5e"}, + {file = "rapidfuzz-3.9.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:544b0bf9d17170720809918e9ccd0d482d4a3a6eca35630d8e1459f737f71755"}, + {file = "rapidfuzz-3.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d536f8beb8dd82d6efb20fe9f82c2cfab9ffa0384b5d184327e393a4edde91d"}, + {file = "rapidfuzz-3.9.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:30f7609da871510583f87484a10820b26555a473a90ab356cdda2f3b4456256c"}, + {file = "rapidfuzz-3.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f4a2468432a1db491af6f547fad8f6d55fa03e57265c2f20e5eaceb68c7907e"}, + {file = "rapidfuzz-3.9.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11a7ec4676242c8a430509cff42ce98bca2fbe30188a63d0f60fdcbfd7e84970"}, + {file = "rapidfuzz-3.9.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dcb523243e988c849cf81220164ec3bbed378a699e595a8914fffe80596dc49f"}, + {file = "rapidfuzz-3.9.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4eea3bf72c4fe68e957526ffd6bcbb403a21baa6b3344aaae2d3252313df6199"}, + {file = "rapidfuzz-3.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4514980a5d204c076dd5b756960f6b1b7598f030009456e6109d76c4c331d03c"}, + {file = "rapidfuzz-3.9.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9a06a99f1335fe43464d7121bc6540de7cd9c9475ac2025babb373fe7f27846b"}, + {file = "rapidfuzz-3.9.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6c1ed63345d1581c39d4446b1a8c8f550709656ce2a3c88c47850b258167f3c2"}, + {file = "rapidfuzz-3.9.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:cd2e6e97daf17ebb3254285cf8dd86c60d56d6cf35c67f0f9a557ef26bd66290"}, + {file = "rapidfuzz-3.9.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:9bc0f7e6256a9c668482c41c8a3de5d0aa12e8ca346dcc427b97c7edb82cba48"}, + {file = "rapidfuzz-3.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7c09f4e87e82a164c9db769474bc61f8c8b677f2aeb0234b8abac73d2ecf9799"}, + {file = "rapidfuzz-3.9.0-cp38-cp38-win32.whl", hash = "sha256:e65b8f7921bf60cbb207c132842a6b45eefef48c4c3b510eb16087d6c08c70af"}, + {file = "rapidfuzz-3.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:9d6478957fb35c7844ad08f2442b62ba76c1857a56370781a707eefa4f4981e1"}, + {file = "rapidfuzz-3.9.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:65d9250a4b0bf86320097306084bc3ca479c8f5491927c170d018787793ebe95"}, + {file = "rapidfuzz-3.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:47b7c0840afa724db3b1a070bc6ed5beab73b4e659b1d395023617fc51bf68a2"}, + {file = "rapidfuzz-3.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3a16c48c6df8fb633efbbdea744361025d01d79bca988f884a620e63e782fe5b"}, + {file = "rapidfuzz-3.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48105991ff6e4a51c7f754df500baa070270ed3d41784ee0d097549bc9fcb16d"}, + {file = "rapidfuzz-3.9.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a7f273906b3c7cc6d63a76e088200805947aa0bc1ada42c6a0e582e19c390d7"}, + {file = "rapidfuzz-3.9.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c396562d304e974b4b0d5cd3afc4f92c113ea46a36e6bc62e45333d6aa8837e"}, + {file = "rapidfuzz-3.9.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:68da1b70458fea5290ec9a169fcffe0c17ff7e5bb3c3257e63d7021a50601a8e"}, + {file = "rapidfuzz-3.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c5b8f9a7b177af6ce7c6ad5b95588b4b73e37917711aafa33b2e79ee80fe709"}, + {file = "rapidfuzz-3.9.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3c42a238bf9dd48f4ccec4c6934ac718225b00bb3a438a008c219e7ccb3894c7"}, + {file = "rapidfuzz-3.9.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a365886c42177b2beab475a50ba311b59b04f233ceaebc4c341f6f91a86a78e2"}, + {file = "rapidfuzz-3.9.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:ce897b5dafb7fb7587a95fe4d449c1ea0b6d9ac4462fbafefdbbeef6eee4cf6a"}, + {file = "rapidfuzz-3.9.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:413ac49bae291d7e226a5c9be65c71b2630b3346bce39268d02cb3290232e4b7"}, + {file = "rapidfuzz-3.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8982fc3bd49d55a91569fc8a3feba0de4cef0b391ff9091be546e9df075b81"}, + {file = "rapidfuzz-3.9.0-cp39-cp39-win32.whl", hash = "sha256:3904d0084ab51f82e9f353031554965524f535522a48ec75c30b223eb5a0a488"}, + {file = "rapidfuzz-3.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:3733aede16ea112728ffeafeb29ccc62e095ed8ec816822fa2a82e92e2c08696"}, + {file = "rapidfuzz-3.9.0-cp39-cp39-win_arm64.whl", hash = "sha256:fc4e26f592b51f97acf0a3f8dfed95e4d830c6a8fbf359361035df836381ab81"}, + {file = "rapidfuzz-3.9.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e33362e98c7899b5f60dcb06ada00acd8673ce0d59aefe9a542701251fd00423"}, + {file = "rapidfuzz-3.9.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb67cf43ad83cb886cbbbff4df7dcaad7aedf94d64fca31aea0da7d26684283c"}, + {file = "rapidfuzz-3.9.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e2e106cc66453bb80d2ad9c0044f8287415676df5c8036d737d05d4b9cdbf8e"}, + {file = "rapidfuzz-3.9.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1256915f7e7a5cf2c151c9ac44834b37f9bd1c97e8dec6f936884f01b9dfc7d"}, + {file = "rapidfuzz-3.9.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:ae643220584518cbff8bf2974a0494d3e250763af816b73326a512c86ae782ce"}, + {file = "rapidfuzz-3.9.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:491274080742110427f38a6085bb12dffcaff1eef12dccf9e8758398c7e3957e"}, + {file = "rapidfuzz-3.9.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bc5559b9b94326922c096b30ae2d8e5b40b2e9c2c100c2cc396ad91bcb84d30"}, + {file = "rapidfuzz-3.9.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:849160dc0f128acb343af514ca827278005c1d00148d025e4035e034fc2d8c7f"}, + {file = "rapidfuzz-3.9.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:623883fb78e692d54ed7c43b09beec52c6685f10a45a7518128e25746667403b"}, + {file = "rapidfuzz-3.9.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d20ab9abc7e19767f1951772a6ab14cb4eddd886493c2da5ee12014596ad253f"}, + {file = "rapidfuzz-3.9.0.tar.gz", hash = "sha256:b182f0fb61f6ac435e416eb7ab330d62efdbf9b63cf0c7fa12d1f57c2eaaf6f3"}, +] + +[package.extras] +full = ["numpy"] + +[[package]] +name = "regex" +version = "2024.4.28" +description = "Alternative regular expression module, to replace re." +optional = false +python-versions = ">=3.8" +files = [ + {file = "regex-2024.4.28-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd196d056b40af073d95a2879678585f0b74ad35190fac04ca67954c582c6b61"}, + {file = "regex-2024.4.28-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8bb381f777351bd534462f63e1c6afb10a7caa9fa2a421ae22c26e796fe31b1f"}, + {file = "regex-2024.4.28-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:47af45b6153522733aa6e92543938e97a70ce0900649ba626cf5aad290b737b6"}, + {file = "regex-2024.4.28-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99d6a550425cc51c656331af0e2b1651e90eaaa23fb4acde577cf15068e2e20f"}, + {file = "regex-2024.4.28-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bf29304a8011feb58913c382902fde3395957a47645bf848eea695839aa101b7"}, + {file = "regex-2024.4.28-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:92da587eee39a52c91aebea8b850e4e4f095fe5928d415cb7ed656b3460ae79a"}, + {file = "regex-2024.4.28-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6277d426e2f31bdbacb377d17a7475e32b2d7d1f02faaecc48d8e370c6a3ff31"}, + {file = "regex-2024.4.28-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:28e1f28d07220c0f3da0e8fcd5a115bbb53f8b55cecf9bec0c946eb9a059a94c"}, + {file = "regex-2024.4.28-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:aaa179975a64790c1f2701ac562b5eeb733946eeb036b5bcca05c8d928a62f10"}, + {file = "regex-2024.4.28-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6f435946b7bf7a1b438b4e6b149b947c837cb23c704e780c19ba3e6855dbbdd3"}, + {file = "regex-2024.4.28-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:19d6c11bf35a6ad077eb23852827f91c804eeb71ecb85db4ee1386825b9dc4db"}, + {file = "regex-2024.4.28-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:fdae0120cddc839eb8e3c15faa8ad541cc6d906d3eb24d82fb041cfe2807bc1e"}, + {file = "regex-2024.4.28-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e672cf9caaf669053121f1766d659a8813bd547edef6e009205378faf45c67b8"}, + {file = "regex-2024.4.28-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f57515750d07e14743db55d59759893fdb21d2668f39e549a7d6cad5d70f9fea"}, + {file = "regex-2024.4.28-cp310-cp310-win32.whl", hash = "sha256:a1409c4eccb6981c7baabc8888d3550df518add6e06fe74fa1d9312c1838652d"}, + {file = "regex-2024.4.28-cp310-cp310-win_amd64.whl", hash = "sha256:1f687a28640f763f23f8a9801fe9e1b37338bb1ca5d564ddd41619458f1f22d1"}, + {file = "regex-2024.4.28-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:84077821c85f222362b72fdc44f7a3a13587a013a45cf14534df1cbbdc9a6796"}, + {file = "regex-2024.4.28-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b45d4503de8f4f3dc02f1d28a9b039e5504a02cc18906cfe744c11def942e9eb"}, + {file = "regex-2024.4.28-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:457c2cd5a646dd4ed536c92b535d73548fb8e216ebee602aa9f48e068fc393f3"}, + {file = "regex-2024.4.28-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b51739ddfd013c6f657b55a508de8b9ea78b56d22b236052c3a85a675102dc6"}, + {file = "regex-2024.4.28-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:459226445c7d7454981c4c0ce0ad1a72e1e751c3e417f305722bbcee6697e06a"}, + {file = "regex-2024.4.28-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:670fa596984b08a4a769491cbdf22350431970d0112e03d7e4eeaecaafcd0fec"}, + {file = "regex-2024.4.28-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe00f4fe11c8a521b173e6324d862ee7ee3412bf7107570c9b564fe1119b56fb"}, + {file = "regex-2024.4.28-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:36f392dc7763fe7924575475736bddf9ab9f7a66b920932d0ea50c2ded2f5636"}, + {file = "regex-2024.4.28-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:23a412b7b1a7063f81a742463f38821097b6a37ce1e5b89dd8e871d14dbfd86b"}, + {file = "regex-2024.4.28-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f1d6e4b7b2ae3a6a9df53efbf199e4bfcff0959dbdb5fd9ced34d4407348e39a"}, + {file = "regex-2024.4.28-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:499334ad139557de97cbc4347ee921c0e2b5e9c0f009859e74f3f77918339257"}, + {file = "regex-2024.4.28-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:0940038bec2fe9e26b203d636c44d31dd8766abc1fe66262da6484bd82461ccf"}, + {file = "regex-2024.4.28-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:66372c2a01782c5fe8e04bff4a2a0121a9897e19223d9eab30c54c50b2ebeb7f"}, + {file = "regex-2024.4.28-cp311-cp311-win32.whl", hash = "sha256:c77d10ec3c1cf328b2f501ca32583625987ea0f23a0c2a49b37a39ee5c4c4630"}, + {file = "regex-2024.4.28-cp311-cp311-win_amd64.whl", hash = "sha256:fc0916c4295c64d6890a46e02d4482bb5ccf33bf1a824c0eaa9e83b148291f90"}, + {file = "regex-2024.4.28-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:08a1749f04fee2811c7617fdd46d2e46d09106fa8f475c884b65c01326eb15c5"}, + {file = "regex-2024.4.28-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b8eb28995771c087a73338f695a08c9abfdf723d185e57b97f6175c5051ff1ae"}, + {file = "regex-2024.4.28-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:dd7ef715ccb8040954d44cfeff17e6b8e9f79c8019daae2fd30a8806ef5435c0"}, + {file = "regex-2024.4.28-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb0315a2b26fde4005a7c401707c5352df274460f2f85b209cf6024271373013"}, + {file = "regex-2024.4.28-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f2fc053228a6bd3a17a9b0a3f15c3ab3cf95727b00557e92e1cfe094b88cc662"}, + {file = "regex-2024.4.28-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fe9739a686dc44733d52d6e4f7b9c77b285e49edf8570754b322bca6b85b4cc"}, + {file = "regex-2024.4.28-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74fcf77d979364f9b69fcf8200849ca29a374973dc193a7317698aa37d8b01c"}, + {file = "regex-2024.4.28-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:965fd0cf4694d76f6564896b422724ec7b959ef927a7cb187fc6b3f4e4f59833"}, + {file = "regex-2024.4.28-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:2fef0b38c34ae675fcbb1b5db760d40c3fc3612cfa186e9e50df5782cac02bcd"}, + {file = "regex-2024.4.28-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bc365ce25f6c7c5ed70e4bc674f9137f52b7dd6a125037f9132a7be52b8a252f"}, + {file = "regex-2024.4.28-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:ac69b394764bb857429b031d29d9604842bc4cbfd964d764b1af1868eeebc4f0"}, + {file = "regex-2024.4.28-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:144a1fc54765f5c5c36d6d4b073299832aa1ec6a746a6452c3ee7b46b3d3b11d"}, + {file = "regex-2024.4.28-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2630ca4e152c221072fd4a56d4622b5ada876f668ecd24d5ab62544ae6793ed6"}, + {file = "regex-2024.4.28-cp312-cp312-win32.whl", hash = "sha256:7f3502f03b4da52bbe8ba962621daa846f38489cae5c4a7b5d738f15f6443d17"}, + {file = "regex-2024.4.28-cp312-cp312-win_amd64.whl", hash = "sha256:0dd3f69098511e71880fb00f5815db9ed0ef62c05775395968299cb400aeab82"}, + {file = "regex-2024.4.28-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:374f690e1dd0dbdcddea4a5c9bdd97632cf656c69113f7cd6a361f2a67221cb6"}, + {file = "regex-2024.4.28-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:25f87ae6b96374db20f180eab083aafe419b194e96e4f282c40191e71980c666"}, + {file = "regex-2024.4.28-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5dbc1bcc7413eebe5f18196e22804a3be1bfdfc7e2afd415e12c068624d48247"}, + {file = "regex-2024.4.28-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f85151ec5a232335f1be022b09fbbe459042ea1951d8a48fef251223fc67eee1"}, + {file = "regex-2024.4.28-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:57ba112e5530530fd175ed550373eb263db4ca98b5f00694d73b18b9a02e7185"}, + {file = "regex-2024.4.28-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:224803b74aab56aa7be313f92a8d9911dcade37e5f167db62a738d0c85fdac4b"}, + {file = "regex-2024.4.28-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a54a047b607fd2d2d52a05e6ad294602f1e0dec2291152b745870afc47c1397"}, + {file = "regex-2024.4.28-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a2a512d623f1f2d01d881513af9fc6a7c46e5cfffb7dc50c38ce959f9246c94"}, + {file = "regex-2024.4.28-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c06bf3f38f0707592898428636cbb75d0a846651b053a1cf748763e3063a6925"}, + {file = "regex-2024.4.28-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1031a5e7b048ee371ab3653aad3030ecfad6ee9ecdc85f0242c57751a05b0ac4"}, + {file = "regex-2024.4.28-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d7a353ebfa7154c871a35caca7bfd8f9e18666829a1dc187115b80e35a29393e"}, + {file = "regex-2024.4.28-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:7e76b9cfbf5ced1aca15a0e5b6f229344d9b3123439ffce552b11faab0114a02"}, + {file = "regex-2024.4.28-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:5ce479ecc068bc2a74cb98dd8dba99e070d1b2f4a8371a7dfe631f85db70fe6e"}, + {file = "regex-2024.4.28-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7d77b6f63f806578c604dca209280e4c54f0fa9a8128bb8d2cc5fb6f99da4150"}, + {file = "regex-2024.4.28-cp38-cp38-win32.whl", hash = "sha256:d84308f097d7a513359757c69707ad339da799e53b7393819ec2ea36bc4beb58"}, + {file = "regex-2024.4.28-cp38-cp38-win_amd64.whl", hash = "sha256:2cc1b87bba1dd1a898e664a31012725e48af826bf3971e786c53e32e02adae6c"}, + {file = "regex-2024.4.28-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7413167c507a768eafb5424413c5b2f515c606be5bb4ef8c5dee43925aa5718b"}, + {file = "regex-2024.4.28-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:108e2dcf0b53a7c4ab8986842a8edcb8ab2e59919a74ff51c296772e8e74d0ae"}, + {file = "regex-2024.4.28-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f1c5742c31ba7d72f2dedf7968998730664b45e38827637e0f04a2ac7de2f5f1"}, + {file = "regex-2024.4.28-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecc6148228c9ae25ce403eade13a0961de1cb016bdb35c6eafd8e7b87ad028b1"}, + {file = "regex-2024.4.28-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7d893c8cf0e2429b823ef1a1d360a25950ed11f0e2a9df2b5198821832e1947"}, + {file = "regex-2024.4.28-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4290035b169578ffbbfa50d904d26bec16a94526071ebec3dadbebf67a26b25e"}, + {file = "regex-2024.4.28-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44a22ae1cfd82e4ffa2066eb3390777dc79468f866f0625261a93e44cdf6482b"}, + {file = "regex-2024.4.28-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd24fd140b69f0b0bcc9165c397e9b2e89ecbeda83303abf2a072609f60239e2"}, + {file = "regex-2024.4.28-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:39fb166d2196413bead229cd64a2ffd6ec78ebab83fff7d2701103cf9f4dfd26"}, + {file = "regex-2024.4.28-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9301cc6db4d83d2c0719f7fcda37229691745168bf6ae849bea2e85fc769175d"}, + {file = "regex-2024.4.28-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7c3d389e8d76a49923683123730c33e9553063d9041658f23897f0b396b2386f"}, + {file = "regex-2024.4.28-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:99ef6289b62042500d581170d06e17f5353b111a15aa6b25b05b91c6886df8fc"}, + {file = "regex-2024.4.28-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:b91d529b47798c016d4b4c1d06cc826ac40d196da54f0de3c519f5a297c5076a"}, + {file = "regex-2024.4.28-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:43548ad74ea50456e1c68d3c67fff3de64c6edb85bcd511d1136f9b5376fc9d1"}, + {file = "regex-2024.4.28-cp39-cp39-win32.whl", hash = "sha256:05d9b6578a22db7dedb4df81451f360395828b04f4513980b6bd7a1412c679cc"}, + {file = "regex-2024.4.28-cp39-cp39-win_amd64.whl", hash = "sha256:3986217ec830c2109875be740531feb8ddafe0dfa49767cdcd072ed7e8927962"}, + {file = "regex-2024.4.28.tar.gz", hash = "sha256:83ab366777ea45d58f72593adf35d36ca911ea8bd838483c1823b883a121b0e4"}, +] + +[[package]] +name = "requests" +version = "2.31.0" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.7" +files = [ + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +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 = "tzdata" +version = "2024.1" +description = "Provider of IANA time zone data" +optional = false +python-versions = ">=2" +files = [ + {file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"}, + {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, +] + +[[package]] +name = "tzlocal" +version = "5.2" +description = "tzinfo object for the local timezone" +optional = false +python-versions = ">=3.8" +files = [ + {file = "tzlocal-5.2-py3-none-any.whl", hash = "sha256:49816ef2fe65ea8ac19d19aa7a1ae0551c834303d5014c6d5a62e4cbda8047b8"}, + {file = "tzlocal-5.2.tar.gz", hash = "sha256:8d399205578f1a9342816409cc1e46a93ebd5755e39ea2d85334bea911bf0e6e"}, +] + +[package.dependencies] +tzdata = {version = "*", markers = "platform_system == \"Windows\""} + +[package.extras] +devenv = ["check-manifest", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3)", "zest.releaser"] + +[[package]] +name = "urllib3" +version = "2.2.1" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.8" +files = [ + {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, + {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[metadata] +lock-version = "2.0" +python-versions = "^3.10" +content-hash = "f65cd66387236673e2a5afb3b2a75362c97815cdde592a86712737fb9ca71695" diff --git a/pkgs/by-name/up/update-vim-plugins/pyproject.toml b/pkgs/by-name/up/update-vim-plugins/pyproject.toml new file mode 100644 index 00000000..38caf76d --- /dev/null +++ b/pkgs/by-name/up/update-vim-plugins/pyproject.toml @@ -0,0 +1,45 @@ +[tool.poetry] +name = "update_vim_plugins" +version = "0.1.0" +description = "" +authors = ["Your Name "] +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/pkgs/by-name/up/update-vim-plugins/update.sh b/pkgs/by-name/up/update-vim-plugins/update.sh new file mode 100755 index 00000000..1bad12a9 --- /dev/null +++ b/pkgs/by-name/up/update-vim-plugins/update.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env sh + +poetry update --lock + +# vim: ft=sh diff --git a/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/__init__.py b/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/__main__.py b/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/__main__.py new file mode 100644 index 00000000..a8d9e06f --- /dev/null +++ b/pkgs/by-name/up/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/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/cleanup.py b/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/cleanup.py new file mode 100644 index 00000000..fd313ed0 --- /dev/null +++ b/pkgs/by-name/up/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("Checking manifest file") + # 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("Done") + + 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("The following lines appear to define the same plugin") + + 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(" • Cannot determine which is the correct plugin") + 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" - {p.line}") + self.line(f" - {p2.line}") + specs.remove(p2) + elif select_p2: + self.line(f" - {p.line}") + self.line(f" - {p2.line}") + specs.remove(p) + else: + self.line(" • Logic error in correct spec determination") + 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/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/helpers.py b/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/helpers.py new file mode 100644 index 00000000..8a28b0e8 --- /dev/null +++ b/pkgs/by-name/up/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/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/nix.py b/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/nix.py new file mode 100644 index 00000000..66a8df4c --- /dev/null +++ b/pkgs/by-name/up/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/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/plugin.py b/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/plugin.py new file mode 100644 index 00000000..8334ad53 --- /dev/null +++ b/pkgs/by-name/up/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/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/spec.py b/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/spec.py new file mode 100644 index 00000000..0f2fb29c --- /dev/null +++ b/pkgs/by-name/up/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: + [:]/[:][: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[^:]+):)" + owner_regex = r"(?P[^/:]+)" + repo_regex = r"(?P[^:]+)" + branch_regex = r"(:(?P[^:]+)?)" + name_regex = r"(:(?P[^:]+)?)" + license_regex = r"(:(?P[^:]+)?)" + marked_duplicate_regex = r"(:(?Pduplicate))" + + 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/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/tests/__init__.py b/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/tests/fixtures.py b/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/tests/fixtures.py new file mode 100644 index 00000000..75dd251a --- /dev/null +++ b/pkgs/by-name/up/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, 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/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/tests/test_nix.py b/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/tests/test_nix.py new file mode 100644 index 00000000..46e59f76 --- /dev/null +++ b/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/tests/test_nix.py @@ -0,0 +1,32 @@ +from update_vim_plugins.nix import GitSource, License, UrlSource + + +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/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/tests/test_plugin.py b/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/tests/test_plugin.py new file mode 100644 index 00000000..32377e24 --- /dev/null +++ b/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/tests/test_plugin.py @@ -0,0 +1,144 @@ +import json +from typing import Callable + +import pytest +from pytest_mock import MockFixture + +from update_vim_plugins.nix import License, UrlSource +from update_vim_plugins.plugin import GitHubPlugin, VimPlugin +from update_vim_plugins.spec import PluginSpec + + +@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/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/tests/test_spec.py b/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/tests/test_spec.py new file mode 100644 index 00000000..2b9a1d24 --- /dev/null +++ b/pkgs/by-name/up/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/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/update.py b/pkgs/by-name/up/update-vim-plugins/update_vim_plugins/update.py new file mode 100644 index 00000000..7eb3eeb4 --- /dev/null +++ b/pkgs/by-name/up/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("These plugins would be updated") + pprint(spec_list) + self.line(f"Total: {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("Not processed: 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( + "Not updated: 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("Done") + + def write_plugins_markdown(self, plugins, plug_dir): + """Write the list of all plugins to PLUGINS_LIST_FILE in markdown""" + + plugins.sort() + + self.line("Updating plugins.md") + + 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("Generating nix output") + + 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("Formatting nix output") + + 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("Storing results in .plugins.json") + + 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: 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" - ({i+1}/{size}) Processing {spec!r}\n" + vim_plugin = plugin_from_spec(spec) + debug_string += f" • Success {vim_plugin!r}\n" + processed_plugin = vim_plugin + except Exception as e: + debug_string += f" • Error: Could not update {spec.name}. 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: No entries for {spec.name} 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 -- cgit 1.4.1