From 34b7f26d0cc154a9c7361640812f1561223055c8 Mon Sep 17 00:00:00 2001 From: Graham Hukill Date: Mon, 10 Jun 2024 14:20:44 -0400 Subject: [PATCH 1/5] Bump python 3.12 and maintenance updates Why these changes are being introduced: Some new CLI application project structures, linting, and testing conventions were established in 2023. This is the first time this project has receieved maintenance updates since that time. Additionally, this commit bumps the python version to 3.12. How this addresses that need: * Bumps python version in required areas * Establishes new linting and testing conventions * Updates files to meet new linting requirements Side effects of this change: * None Relevant ticket(s): * None --- .github/pull-request-template.md | 35 +- .gitignore | 1 + .pre-commit-config.yaml | 29 + .python-version | 2 +- Dockerfile | 2 +- Makefile | 47 +- Pipfile | 7 +- Pipfile.lock | 2007 ++++++++++++++---------------- README.md | 32 +- pyproject.toml | 70 ++ sapinvoices/alma.py | 9 +- sapinvoices/cli.py | 20 +- sapinvoices/config.py | 5 +- sapinvoices/email.py | 16 +- sapinvoices/sample_data.py | 22 +- sapinvoices/sap.py | 122 +- sapinvoices/ssm.py | 6 +- tests/conftest.py | 141 ++- tests/test_alma.py | 12 +- tests/test_cli.py | 22 +- tests/test_config.py | 6 +- tests/test_email.py | 2 + tests/test_sample_data.py | 5 +- tests/test_sap.py | 78 +- tests/test_ssm.py | 2 + 25 files changed, 1349 insertions(+), 1351 deletions(-) create mode 100644 .pre-commit-config.yaml create mode 100644 pyproject.toml diff --git a/.github/pull-request-template.md b/.github/pull-request-template.md index fc70031..67b36da 100644 --- a/.github/pull-request-template.md +++ b/.github/pull-request-template.md @@ -1,39 +1,30 @@ -### What does this PR do? - -Describe the overall purpose of the PR changes. Doesn't need to be as specific as the -individual commits. - -### Helpful background context - -Describe any additional context beyond what the PR accomplishes if it is likely to be -useful to a reviewer. - -Delete this section if it isn't applicable to the PR. +### Purpose and background context +Describe the overall purpose of the PR changes and any useful background context. ### How can a reviewer manually see the effects of these changes? - Explain how to see the proposed changes in the application if possible. Delete this section if it isn't applicable to the PR. ### Includes new or updated dependencies? +YES | NO +### Changes expectations for external applications? YES | NO ### What are the relevant tickets? - -Include links to Jira Software and/or Jira Service Management tickets here. +- Include links to Jira Software and/or Jira Service Management tickets here. ### Developer - -- [ ] All new ENV is documented in README (or there is none) +- [ ] All new ENV is documented in README +- [ ] All new ENV has been added to staging and production environments +- [ ] All related Jira tickets are linked in commit message(s) - [ ] Stakeholder approval has been confirmed (or is not needed) -### Code Reviewer - -- [ ] The commit message is clear and follows our guidelines - (not just this pull request message) +### Code Reviewer(s) +- [ ] The commit message is clear and follows our guidelines (not just this PR message) - [ ] There are appropriate tests covering any new functionality -- [ ] The documentation has been updated or is unnecessary -- [ ] The changes have been verified +- [ ] The provided documentation is sufficient for understanding any new functionality introduced +- [ ] Any manual tests have been performed **or** provided examples verified - [ ] New dependencies are appropriate or there were no changes + diff --git a/.gitignore b/.gitignore index d37c967..1c51a4e 100644 --- a/.gitignore +++ b/.gitignore @@ -155,3 +155,4 @@ cython_debug/ .DS_Store output/ .vscode/ +.idea/ \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..d842a91 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,29 @@ +default_language_version: + python: python3.11 # set for project python version +repos: + - repo: local + hooks: + - id: black-apply + name: black-apply + entry: pipenv run black + language: system + pass_filenames: true + types: ["python"] + - id: mypy + name: mypy + entry: pipenv run mypy + language: system + pass_filenames: true + types: ["python"] + exclude: "tests/" + - id: ruff-apply + name: ruff-apply + entry: pipenv run ruff check --fix + language: system + pass_filenames: true + types: ["python"] + - id: safety + name: safety + entry: pipenv check + language: system + pass_filenames: false \ No newline at end of file diff --git a/.python-version b/.python-version index 1e33456..e4fba21 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -3.11.2 +3.12 diff --git a/Dockerfile b/Dockerfile index df37d90..27480b8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.11-slim as build +FROM python:3.12-slim as build WORKDIR /app COPY . . diff --git a/Makefile b/Makefile index 03b5033..c326e0d 100644 --- a/Makefile +++ b/Makefile @@ -9,47 +9,54 @@ ECR_URL_DEV:=222053980223.dkr.ecr.us-east-1.amazonaws.com/alma-sapinvoices-dev SHELL=/bin/bash DATETIME:=$(shell date -u +%Y%m%dT%H%M%SZ) -### Dependency commands ### +help: # preview Makefile commands + @awk 'BEGIN { FS = ":.*#"; print "Usage: make \n\nTargets:" } \ +/^[-_[:alpha:]]+:.?*#/ { printf " %-15s%s\n", $$1, $$2 }' $(MAKEFILE_LIST) -install: ## Install dependencies and CLI app +## ---- Dependency commands ---- ## + +install: # Install Python dependencies pipenv install --dev + pipenv run pre-commit install -update: install ## Update all Python dependencies +update: install # Update Python dependencies pipenv clean pipenv update --dev -### Test commands ### +## ---- Unit test commands ---- ## -test: ## Run tests and print a coverage report +test: # Run tests and print a coverage report pipenv run coverage run --source=sapinvoices -m pytest -vv pipenv run coverage report -m -coveralls: test +coveralls: test # Write coverage data to an LCOV report pipenv run coverage lcov -o ./coverage/lcov.info -### Code quality and safety commands ### - -lint: bandit black mypy pylama pydocstyle safety ## Run linting, code quality, and safety checks +## ---- Code quality and safety commands ---- ## -bandit: - pipenv run bandit -r sapinvoices +lint: black mypy ruff safety # run linters -black: +black: # run 'black' linter and print a preview of suggested changes pipenv run black --check --diff . -mypy: - pipenv run mypy sapinvoices - -pylama: - pipenv run pylama --options setup.cfg +mypy: # run 'mypy' linter + pipenv run mypy . -pydocstyle: - pipenv run pydocstyle sapinvoices +ruff: # run 'ruff' linter and print a preview of errors + pipenv run ruff check . -safety: +safety: # check for security vulnerabilities and verify Pipfile.lock is up-to-date pipenv check pipenv verify +lint-apply: black-apply ruff-apply # apply changes to resolve any linting errors + +black-apply: # apply changes with 'black' + pipenv run black . + +ruff-apply: # resolve 'fixable errors' with 'ruff' + pipenv run ruff check --fix . + ### Terraform-generated Developer Deploy Commands for Dev environment ### dist-dev: ## Build docker container (intended for developer-based manual build) diff --git a/Pipfile b/Pipfile index 2154cbe..aa29c61 100644 --- a/Pipfile +++ b/Pipfile @@ -15,7 +15,6 @@ decorator = "*" click = "==8.1.3" [dev-packages] -bandit = "*" black = "*" boto3-stubs = "*" coverage = "*" @@ -23,15 +22,15 @@ coveralls = "*" mock-ssh-server = "*" moto = "*" mypy = "*" -pylama = {extras = ["all"], version = "*"} -pytest = "*" +pre-commit = "*" pydocstyle = "*" requests-mock = "*" +ruff = "*" types-requests = "*" types-paramiko = "*" [requires] -python_version = "3.11" +python_version = "3.12" [scripts] sap = "python -c \"from sapinvoices.cli import main; main()\"" diff --git a/Pipfile.lock b/Pipfile.lock index 4b1be81..7d54cec 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,11 +1,11 @@ { "_meta": { "hash": { - "sha256": "17b7e94b7d0be86b3408730e4428f8a745918e6dd0dfadb0b43419d6deaad812" + "sha256": "8a9120c48177c342275a03ddfb56f29efc1f8da01b5c323df5f2df02b753fee7" }, "pipfile-spec": 6, "requires": { - "python_version": "3.11" + "python_version": "3.12" }, "sources": [ { @@ -18,204 +18,215 @@ "default": { "bcrypt": { "hashes": [ - "sha256:089098effa1bc35dc055366740a067a2fc76987e8ec75349eb9484061c54f535", - "sha256:08d2947c490093a11416df18043c27abe3921558d2c03e2076ccb28a116cb6d0", - "sha256:0eaa47d4661c326bfc9d08d16debbc4edf78778e6aaba29c1bc7ce67214d4410", - "sha256:27d375903ac8261cfe4047f6709d16f7d18d39b1ec92aaf72af989552a650ebd", - "sha256:2b3ac11cf45161628f1f3733263e63194f22664bf4d0c0f3ab34099c02134665", - "sha256:2caffdae059e06ac23fce178d31b4a702f2a3264c20bfb5ff541b338194d8fab", - "sha256:3100851841186c25f127731b9fa11909ab7b1df6fc4b9f8353f4f1fd952fbf71", - "sha256:5ad4d32a28b80c5fa6671ccfb43676e8c1cc232887759d1cd7b6f56ea4355215", - "sha256:67a97e1c405b24f19d08890e7ae0c4f7ce1e56a712a016746c8b2d7732d65d4b", - "sha256:705b2cea8a9ed3d55b4491887ceadb0106acf7c6387699fca771af56b1cdeeda", - "sha256:8a68f4341daf7522fe8d73874de8906f3a339048ba406be6ddc1b3ccb16fc0d9", - "sha256:a522427293d77e1c29e303fc282e2d71864579527a04ddcfda6d4f8396c6c36a", - "sha256:ae88eca3024bb34bb3430f964beab71226e761f51b912de5133470b649d82344", - "sha256:b1023030aec778185a6c16cf70f359cbb6e0c289fd564a7cfa29e727a1c38f8f", - "sha256:b3b85202d95dd568efcb35b53936c5e3b3600c7cdcc6115ba461df3a8e89f38d", - "sha256:b57adba8a1444faf784394de3436233728a1ecaeb6e07e8c22c8848f179b893c", - "sha256:bf4fa8b2ca74381bb5442c089350f09a3f17797829d958fad058d6e44d9eb83c", - "sha256:ca3204d00d3cb2dfed07f2d74a25f12fc12f73e606fcaa6975d1f7ae69cacbb2", - "sha256:cbb03eec97496166b704ed663a53680ab57c5084b2fc98ef23291987b525cb7d", - "sha256:e9a51bbfe7e9802b5f3508687758b564069ba937748ad7b9e890086290d2f79e", - "sha256:fbdaec13c5105f0c4e5c52614d04f0bca5f5af007910daa8b6b12095edaa67b3" + "sha256:01746eb2c4299dd0ae1670234bf77704f581dd72cc180f444bfe74eb80495b64", + "sha256:037c5bf7c196a63dcce75545c8874610c600809d5d82c305dd327cd4969995bf", + "sha256:094fd31e08c2b102a14880ee5b3d09913ecf334cd604af27e1013c76831f7b05", + "sha256:0d4cf6ef1525f79255ef048b3489602868c47aea61f375377f0d00514fe4a78c", + "sha256:193bb49eeeb9c1e2db9ba65d09dc6384edd5608d9d672b4125e9320af9153a15", + "sha256:2505b54afb074627111b5a8dc9b6ae69d0f01fea65c2fcaea403448c503d3991", + "sha256:2ee15dd749f5952fe3f0430d0ff6b74082e159c50332a1413d51b5689cf06623", + "sha256:31adb9cbb8737a581a843e13df22ffb7c84638342de3708a98d5c986770f2834", + "sha256:3a5be252fef513363fe281bafc596c31b552cf81d04c5085bc5dac29670faa08", + "sha256:3d3b317050a9a711a5c7214bf04e28333cf528e0ed0ec9a4e55ba628d0f07c1a", + "sha256:48429c83292b57bf4af6ab75809f8f4daf52aa5d480632e53707805cc1ce9b74", + "sha256:4a8bea4c152b91fd8319fef4c6a790da5c07840421c2b785084989bf8bbb7455", + "sha256:4fb253d65da30d9269e0a6f4b0de32bd657a0208a6f4e43d3e645774fb5457f3", + "sha256:551b320396e1d05e49cc18dd77d970accd52b322441628aca04801bbd1d52a73", + "sha256:5f7cd3399fbc4ec290378b541b0cf3d4398e4737a65d0f938c7c0f9d5e686611", + "sha256:6004f5229b50f8493c49232b8e75726b568535fd300e5039e255d919fc3a07f2", + "sha256:6717543d2c110a155e6821ce5670c1f512f602eabb77dba95717ca76af79867d", + "sha256:6cac78a8d42f9d120b3987f82252bdbeb7e6e900a5e1ba37f6be6fe4e3848286", + "sha256:8a893d192dfb7c8e883c4576813bf18bb9d59e2cfd88b68b725990f033f1b978", + "sha256:8cbb119267068c2581ae38790e0d1fbae65d0725247a930fc9900c285d95725d", + "sha256:9f8ea645eb94fb6e7bea0cf4ba121c07a3a182ac52876493870033141aa687bc", + "sha256:c4c8d9b3e97209dd7111bf726e79f638ad9224b4691d1c7cfefa571a09b1b2d6", + "sha256:cb9c707c10bddaf9e5ba7cdb769f3e889e60b7d4fea22834b261f51ca2b89fed", + "sha256:d84702adb8f2798d813b17d8187d27076cca3cd52fe3686bb07a9083930ce650", + "sha256:ec3c2e1ca3e5c4b9edb94290b356d082b721f3f50758bce7cce11d8a7c89ce84", + "sha256:f44a97780677e7ac0ca393bd7982b19dbbd8d7228c1afe10b128fd9550eef5f1", + "sha256:f5698ce5292a4e4b9e5861f7e53b1d89242ad39d54c3da451a93cac17b61921a" ], - "markers": "python_version >= '3.6'", - "version": "==4.0.1" + "markers": "python_version >= '3.7'", + "version": "==4.1.3" }, "boto3": { "hashes": [ - "sha256:34f07b3fc2503240c0f58114cf3afea91295c7996d084991b78a278a56157c48", - "sha256:610369a7f984b58973c097ea649ec81976c04565d39a2d6d3edc280d23b0cb87" + "sha256:56840d8ce91654d182f1c113f0791fa2113c3aa43230c50b4481f235348a6037", + "sha256:b2d7400ff84fa547e53b3d9acfa3c95d65d45b5886ba1ede1f7df4768d1cc0b1" ], "index": "pypi", - "version": "==1.28.3" + "markers": "python_version >= '3.8'", + "version": "==1.34.122" }, "botocore": { "hashes": [ - "sha256:2aa27c75e62bfcf7900cb85283228fcb7df0fa1bdc2ae76dcee90788dd444934", - "sha256:744ce853cadc7ae87ba42ef6828194ddec97d606dd4d08b4dfe3d96d5001eb0c" + "sha256:6d75df3af831b62f0c7baa109728d987e0a8d34bfadf0476eb32e2f29a079a36", + "sha256:9374e16a36f1062c3e27816e8599b53eba99315dfac71cc84fc3aee3f5d3cbe3" ], - "markers": "python_version >= '3.7'", - "version": "==1.31.3" + "markers": "python_version >= '3.8'", + "version": "==1.34.122" }, "certifi": { "hashes": [ - "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7", - "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716" + "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516", + "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56" ], "markers": "python_version >= '3.6'", - "version": "==2023.5.7" + "version": "==2024.6.2" }, "cffi": { "hashes": [ - "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5", - "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef", - "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104", - "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426", - "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405", - "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375", - "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a", - "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e", - "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc", - "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf", - "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185", - "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497", - "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3", - "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35", - "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c", - "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83", - "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21", - "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca", - "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984", - "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac", - "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd", - "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee", - "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a", - "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2", - "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192", - "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7", - "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585", - "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f", - "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e", - "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27", - "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b", - "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e", - "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e", - "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d", - "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c", - "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415", - "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82", - "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02", - "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314", - "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325", - "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c", - "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3", - "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914", - "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045", - "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d", - "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9", - "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5", - "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2", - "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c", - "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3", - "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2", - "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8", - "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d", - "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d", - "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9", - "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162", - "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76", - "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4", - "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e", - "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9", - "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6", - "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b", - "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01", - "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0" - ], - "version": "==1.15.1" + "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc", + "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a", + "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417", + "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab", + "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520", + "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36", + "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743", + "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8", + "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed", + "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684", + "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56", + "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324", + "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d", + "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235", + "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e", + "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088", + "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000", + "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7", + "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e", + "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673", + "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c", + "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe", + "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2", + "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098", + "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8", + "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a", + "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0", + "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b", + "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896", + "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e", + "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9", + "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2", + "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b", + "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6", + "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404", + "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f", + "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0", + "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4", + "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc", + "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936", + "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba", + "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872", + "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb", + "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614", + "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1", + "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d", + "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969", + "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b", + "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4", + "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627", + "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956", + "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357" + ], + "markers": "platform_python_implementation != 'PyPy'", + "version": "==1.16.0" }, "charset-normalizer": { "hashes": [ - "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96", - "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c", - "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710", - "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706", - "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020", - "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252", - "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad", - "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329", - "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a", - "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f", - "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6", - "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4", - "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a", - "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46", - "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2", - "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23", - "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace", - "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd", - "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982", - "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10", - "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2", - "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea", - "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09", - "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5", - "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149", - "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489", - "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9", - "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80", - "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592", - "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3", - "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6", - "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed", - "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c", - "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200", - "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a", - "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e", - "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d", - "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6", - "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623", - "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669", - "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3", - "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa", - "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9", - "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2", - "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f", - "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1", - "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4", - "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a", - "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8", - "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3", - "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029", - "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f", - "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959", - "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22", - "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7", - "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952", - "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346", - "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e", - "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d", - "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299", - "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd", - "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a", - "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3", - "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037", - "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94", - "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c", - "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858", - "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a", - "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449", - "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c", - "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918", - "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1", - "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c", - "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac", - "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa" + "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027", + "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087", + "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786", + "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8", + "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09", + "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185", + "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574", + "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e", + "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519", + "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898", + "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269", + "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3", + "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f", + "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6", + "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8", + "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a", + "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73", + "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc", + "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714", + "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2", + "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc", + "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce", + "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d", + "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e", + "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6", + "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269", + "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96", + "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d", + "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a", + "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4", + "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77", + "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d", + "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0", + "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed", + "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068", + "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac", + "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25", + "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8", + "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab", + "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26", + "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2", + "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db", + "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f", + "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5", + "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99", + "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c", + "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d", + "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811", + "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa", + "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a", + "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03", + "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b", + "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04", + "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c", + "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001", + "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458", + "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389", + "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99", + "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985", + "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537", + "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238", + "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f", + "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d", + "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796", + "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a", + "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143", + "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8", + "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c", + "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5", + "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5", + "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711", + "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4", + "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6", + "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c", + "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7", + "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4", + "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b", + "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae", + "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12", + "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c", + "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae", + "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8", + "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887", + "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b", + "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4", + "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f", + "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5", + "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33", + "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519", + "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561" ], "markers": "python_full_version >= '3.7.0'", - "version": "==3.2.0" + "version": "==3.3.2" }, "click": { "hashes": [ @@ -223,36 +234,46 @@ "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==8.1.3" }, "cryptography": { "hashes": [ - "sha256:01f1d9e537f9a15b037d5d9ee442b8c22e3ae11ce65ea1f3316a41c78756b711", - "sha256:079347de771f9282fbfe0e0236c716686950c19dee1b76240ab09ce1624d76d7", - "sha256:182be4171f9332b6741ee818ec27daff9fb00349f706629f5cbf417bd50e66fd", - "sha256:192255f539d7a89f2102d07d7375b1e0a81f7478925b3bc2e0549ebf739dae0e", - "sha256:2a034bf7d9ca894720f2ec1d8b7b5832d7e363571828037f9e0c4f18c1b58a58", - "sha256:342f3767e25876751e14f8459ad85e77e660537ca0a066e10e75df9c9e9099f0", - "sha256:439c3cc4c0d42fa999b83ded80a9a1fb54d53c58d6e59234cfe97f241e6c781d", - "sha256:49c3222bb8f8e800aead2e376cbef687bc9e3cb9b58b29a261210456a7783d83", - "sha256:674b669d5daa64206c38e507808aae49904c988fa0a71c935e7006a3e1e83831", - "sha256:7a9a3bced53b7f09da251685224d6a260c3cb291768f54954e28f03ef14e3766", - "sha256:7af244b012711a26196450d34f483357e42aeddb04128885d95a69bd8b14b69b", - "sha256:7d230bf856164de164ecb615ccc14c7fc6de6906ddd5b491f3af90d3514c925c", - "sha256:84609ade00a6ec59a89729e87a503c6e36af98ddcd566d5f3be52e29ba993182", - "sha256:9a6673c1828db6270b76b22cc696f40cde9043eb90373da5c2f8f2158957f42f", - "sha256:9b6d717393dbae53d4e52684ef4f022444fc1cce3c48c38cb74fca29e1f08eaa", - "sha256:9c3fe6534d59d071ee82081ca3d71eed3210f76ebd0361798c74abc2bcf347d4", - "sha256:a719399b99377b218dac6cf547b6ec54e6ef20207b6165126a280b0ce97e0d2a", - "sha256:b332cba64d99a70c1e0836902720887fb4529ea49ea7f5462cf6640e095e11d2", - "sha256:d124682c7a23c9764e54ca9ab5b308b14b18eba02722b8659fb238546de83a76", - "sha256:d73f419a56d74fef257955f51b18d046f3506270a5fd2ac5febbfa259d6c0fa5", - "sha256:f0dc40e6f7aa37af01aba07277d3d64d5a03dc66d682097541ec4da03cc140ee", - "sha256:f14ad275364c8b4e525d018f6716537ae7b6d369c094805cae45300847e0894f", - "sha256:f772610fe364372de33d76edcd313636a25684edb94cee53fd790195f5989d14" + "sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad", + "sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583", + "sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b", + "sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c", + "sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1", + "sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648", + "sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949", + "sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba", + "sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c", + "sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9", + "sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d", + "sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c", + "sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e", + "sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2", + "sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d", + "sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7", + "sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70", + "sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2", + "sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7", + "sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14", + "sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe", + "sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e", + "sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71", + "sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961", + "sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7", + "sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c", + "sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28", + "sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842", + "sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902", + "sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801", + "sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a", + "sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e" ], "markers": "python_version >= '3.7'", - "version": "==41.0.2" + "version": "==42.0.8" }, "decorator": { "hashes": [ @@ -260,18 +281,26 @@ "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186" ], "index": "pypi", + "markers": "python_version >= '3.5'", "version": "==5.1.1" }, + "deprecated": { + "hashes": [ + "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c", + "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.2.14" + }, "fabric": { "extras": [ "pytest" ], "hashes": [ - "sha256:0a13217db1aa203167376119b0e165081c5906c31e2b2104410685d1310ef8fb", - "sha256:ea1c5ea3956d196b5990ba720cc8ee457fa1b9c6f265ab3b643ff63b05e8970a" + "sha256:8783ca42e3b0076f08b26901aac6b9d9b1f19c410074e7accfab902c184ff4a3", + "sha256:91c47c0be68b14936c88b34da8a1f55e5710fd28397dac5d4ff2e21558113a6f" ], - "index": "pypi", - "version": "==3.1.0" + "version": "==3.2.2" }, "flatdict": { "hashes": [ @@ -282,19 +311,20 @@ }, "freezegun": { "hashes": [ - "sha256:cd22d1ba06941384410cd967d8a99d5ae2442f57dfafeff2fda5de8dc5c05446", - "sha256:ea1b963b993cb9ea195adbd893a48d573fda951b0da64f60883d7e988b606c9f" + "sha256:b29dedfcda6d5e8e083ce71b2b542753ad48cfec44037b3fc79702e2980a89e9", + "sha256:bf111d7138a8abe55ab48a71755673dbaa4ab87f4cff5634a4442dfec34c15f1" ], "index": "pypi", - "version": "==1.2.2" + "markers": "python_version >= '3.7'", + "version": "==1.5.1" }, "idna": { "hashes": [ - "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4", - "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2" + "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc", + "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0" ], "markers": "python_version >= '3.5'", - "version": "==3.4" + "version": "==3.7" }, "iniconfig": { "hashes": [ @@ -322,34 +352,36 @@ }, "packaging": { "hashes": [ - "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61", - "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f" + "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002", + "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124" ], - "markers": "python_version >= '3.7'", - "version": "==23.1" + "markers": "python_version >= '3.8'", + "version": "==24.1" }, "paramiko": { "hashes": [ - "sha256:93cdce625a8a1dc12204439d45033f3261bdb2c201648cfcdc06f9fd0f94ec29", - "sha256:df0f9dd8903bc50f2e10580af687f3015bf592a377cd438d2ec9546467a14eb8" + "sha256:43f0b51115a896f9c00f59618023484cb3a14b98bbceab43394a39c6739b7ee7", + "sha256:aac08f26a31dc4dffd92821527d1682d99d52f9ef6851968114a8728f3c274d3" ], "index": "pypi", - "version": "==3.2.0" + "markers": "python_version >= '3.6'", + "version": "==3.4.0" }, "pluggy": { "hashes": [ - "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849", - "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3" + "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", + "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669" ], - "markers": "python_version >= '3.7'", - "version": "==1.2.0" + "markers": "python_version >= '3.8'", + "version": "==1.5.0" }, "pycparser": { "hashes": [ - "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", - "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206" + "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", + "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc" ], - "version": "==2.21" + "markers": "python_version >= '3.8'", + "version": "==2.22" }, "pynacl": { "hashes": [ @@ -369,42 +401,44 @@ }, "pytest": { "hashes": [ - "sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32", - "sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a" + "sha256:c434598117762e2bd304e526244f67bf66bbd7b5d6cf22138be51ff661980343", + "sha256:de4bb8104e201939ccdc688b27a89a7be2079b22e2bd2b07f806b6ba71117977" ], - "version": "==7.4.0" + "version": "==8.2.2" }, "python-dateutil": { "hashes": [ - "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", - "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" + "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", + "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==2.8.2" + "version": "==2.9.0.post0" }, "requests": { "hashes": [ - "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f", - "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1" + "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", + "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6" ], "index": "pypi", - "version": "==2.31.0" + "markers": "python_version >= '3.8'", + "version": "==2.32.3" }, "s3transfer": { "hashes": [ - "sha256:3c0da2d074bf35d6870ef157158641178a4204a6e689e82546083e31e0311346", - "sha256:640bb492711f4c0c0905e1f62b6aaeb771881935ad27884852411f8e9cacbca9" + "sha256:5683916b4c724f799e600f41dd9e10a9ff19871bf87623cc8f491cb4f5fa0a19", + "sha256:ceb252b11bcf87080fb7850a224fb6e05c8a776bab8f2b64b7f25b969464839d" ], - "markers": "python_version >= '3.7'", - "version": "==0.6.1" + "markers": "python_version >= '3.8'", + "version": "==0.10.1" }, "sentry-sdk": { "hashes": [ - "sha256:6bdb25bd9092478d3a817cb0d01fa99e296aea34d404eac3ca0037faa5c2aa0a", - "sha256:dcd88c68aa64dae715311b5ede6502fd684f70d00a7cd4858118f0ba3153a3ae" + "sha256:1f87acdce4a43a523ae5aa21a3fc37522d73ebd9ec04b1dbf01aa3d173852def", + "sha256:fbc40a78a8a9c6675133031116144f0d0940376fa6e4e1acd5624c90b0aaf58b" ], "index": "pypi", - "version": "==1.28.1" + "markers": "python_version >= '3.6'", + "version": "==2.5.1" }, "six": { "hashes": [ @@ -416,274 +450,355 @@ }, "urllib3": { "hashes": [ - "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f", - "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==1.26.16" - } - }, - "develop": { - "astroid": { - "hashes": [ - "sha256:389656ca57b6108f939cf5d2f9a2a825a3be50ba9d589670f393236e0a03b91c", - "sha256:903f024859b7c7687d7a7f3a3f73b17301f8e42dfd9cc9df9d4418172d3e2dbd" + "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d", + "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19" ], - "markers": "python_full_version >= '3.7.2'", - "version": "==2.15.6" + "markers": "python_version >= '3.8'", + "version": "==2.2.1" }, - "bandit": { + "wrapt": { "hashes": [ - "sha256:75665181dc1e0096369112541a056c59d1c5f66f9bb74a8d686c3c362b83f549", - "sha256:bdfc739baa03b880c2d15d0431b31c658ffc348e907fe197e54e0389dd59e11e" + "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc", + "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81", + "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09", + "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e", + "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca", + "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0", + "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb", + "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487", + "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40", + "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c", + "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060", + "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202", + "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41", + "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9", + "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b", + "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664", + "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d", + "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362", + "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00", + "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc", + "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1", + "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267", + "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956", + "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966", + "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1", + "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228", + "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72", + "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d", + "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292", + "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0", + "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0", + "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36", + "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c", + "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5", + "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f", + "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73", + "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b", + "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2", + "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593", + "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39", + "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389", + "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf", + "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf", + "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89", + "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c", + "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c", + "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f", + "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440", + "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465", + "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136", + "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b", + "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8", + "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3", + "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8", + "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6", + "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e", + "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f", + "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c", + "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e", + "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8", + "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2", + "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020", + "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35", + "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d", + "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3", + "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537", + "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809", + "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d", + "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a", + "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4" ], - "index": "pypi", - "version": "==1.7.5" - }, + "markers": "python_version >= '3.6'", + "version": "==1.16.0" + } + }, + "develop": { "bcrypt": { "hashes": [ - "sha256:089098effa1bc35dc055366740a067a2fc76987e8ec75349eb9484061c54f535", - "sha256:08d2947c490093a11416df18043c27abe3921558d2c03e2076ccb28a116cb6d0", - "sha256:0eaa47d4661c326bfc9d08d16debbc4edf78778e6aaba29c1bc7ce67214d4410", - "sha256:27d375903ac8261cfe4047f6709d16f7d18d39b1ec92aaf72af989552a650ebd", - "sha256:2b3ac11cf45161628f1f3733263e63194f22664bf4d0c0f3ab34099c02134665", - "sha256:2caffdae059e06ac23fce178d31b4a702f2a3264c20bfb5ff541b338194d8fab", - "sha256:3100851841186c25f127731b9fa11909ab7b1df6fc4b9f8353f4f1fd952fbf71", - "sha256:5ad4d32a28b80c5fa6671ccfb43676e8c1cc232887759d1cd7b6f56ea4355215", - "sha256:67a97e1c405b24f19d08890e7ae0c4f7ce1e56a712a016746c8b2d7732d65d4b", - "sha256:705b2cea8a9ed3d55b4491887ceadb0106acf7c6387699fca771af56b1cdeeda", - "sha256:8a68f4341daf7522fe8d73874de8906f3a339048ba406be6ddc1b3ccb16fc0d9", - "sha256:a522427293d77e1c29e303fc282e2d71864579527a04ddcfda6d4f8396c6c36a", - "sha256:ae88eca3024bb34bb3430f964beab71226e761f51b912de5133470b649d82344", - "sha256:b1023030aec778185a6c16cf70f359cbb6e0c289fd564a7cfa29e727a1c38f8f", - "sha256:b3b85202d95dd568efcb35b53936c5e3b3600c7cdcc6115ba461df3a8e89f38d", - "sha256:b57adba8a1444faf784394de3436233728a1ecaeb6e07e8c22c8848f179b893c", - "sha256:bf4fa8b2ca74381bb5442c089350f09a3f17797829d958fad058d6e44d9eb83c", - "sha256:ca3204d00d3cb2dfed07f2d74a25f12fc12f73e606fcaa6975d1f7ae69cacbb2", - "sha256:cbb03eec97496166b704ed663a53680ab57c5084b2fc98ef23291987b525cb7d", - "sha256:e9a51bbfe7e9802b5f3508687758b564069ba937748ad7b9e890086290d2f79e", - "sha256:fbdaec13c5105f0c4e5c52614d04f0bca5f5af007910daa8b6b12095edaa67b3" + "sha256:01746eb2c4299dd0ae1670234bf77704f581dd72cc180f444bfe74eb80495b64", + "sha256:037c5bf7c196a63dcce75545c8874610c600809d5d82c305dd327cd4969995bf", + "sha256:094fd31e08c2b102a14880ee5b3d09913ecf334cd604af27e1013c76831f7b05", + "sha256:0d4cf6ef1525f79255ef048b3489602868c47aea61f375377f0d00514fe4a78c", + "sha256:193bb49eeeb9c1e2db9ba65d09dc6384edd5608d9d672b4125e9320af9153a15", + "sha256:2505b54afb074627111b5a8dc9b6ae69d0f01fea65c2fcaea403448c503d3991", + "sha256:2ee15dd749f5952fe3f0430d0ff6b74082e159c50332a1413d51b5689cf06623", + "sha256:31adb9cbb8737a581a843e13df22ffb7c84638342de3708a98d5c986770f2834", + "sha256:3a5be252fef513363fe281bafc596c31b552cf81d04c5085bc5dac29670faa08", + "sha256:3d3b317050a9a711a5c7214bf04e28333cf528e0ed0ec9a4e55ba628d0f07c1a", + "sha256:48429c83292b57bf4af6ab75809f8f4daf52aa5d480632e53707805cc1ce9b74", + "sha256:4a8bea4c152b91fd8319fef4c6a790da5c07840421c2b785084989bf8bbb7455", + "sha256:4fb253d65da30d9269e0a6f4b0de32bd657a0208a6f4e43d3e645774fb5457f3", + "sha256:551b320396e1d05e49cc18dd77d970accd52b322441628aca04801bbd1d52a73", + "sha256:5f7cd3399fbc4ec290378b541b0cf3d4398e4737a65d0f938c7c0f9d5e686611", + "sha256:6004f5229b50f8493c49232b8e75726b568535fd300e5039e255d919fc3a07f2", + "sha256:6717543d2c110a155e6821ce5670c1f512f602eabb77dba95717ca76af79867d", + "sha256:6cac78a8d42f9d120b3987f82252bdbeb7e6e900a5e1ba37f6be6fe4e3848286", + "sha256:8a893d192dfb7c8e883c4576813bf18bb9d59e2cfd88b68b725990f033f1b978", + "sha256:8cbb119267068c2581ae38790e0d1fbae65d0725247a930fc9900c285d95725d", + "sha256:9f8ea645eb94fb6e7bea0cf4ba121c07a3a182ac52876493870033141aa687bc", + "sha256:c4c8d9b3e97209dd7111bf726e79f638ad9224b4691d1c7cfefa571a09b1b2d6", + "sha256:cb9c707c10bddaf9e5ba7cdb769f3e889e60b7d4fea22834b261f51ca2b89fed", + "sha256:d84702adb8f2798d813b17d8187d27076cca3cd52fe3686bb07a9083930ce650", + "sha256:ec3c2e1ca3e5c4b9edb94290b356d082b721f3f50758bce7cce11d8a7c89ce84", + "sha256:f44a97780677e7ac0ca393bd7982b19dbbd8d7228c1afe10b128fd9550eef5f1", + "sha256:f5698ce5292a4e4b9e5861f7e53b1d89242ad39d54c3da451a93cac17b61921a" ], - "markers": "python_version >= '3.6'", - "version": "==4.0.1" + "markers": "python_version >= '3.7'", + "version": "==4.1.3" }, "black": { "hashes": [ - "sha256:01ede61aac8c154b55f35301fac3e730baf0c9cf8120f65a9cd61a81cfb4a0c3", - "sha256:022a582720b0d9480ed82576c920a8c1dde97cc38ff11d8d8859b3bd6ca9eedb", - "sha256:25cc308838fe71f7065df53aedd20327969d05671bac95b38fdf37ebe70ac087", - "sha256:27eb7a0c71604d5de083757fbdb245b1a4fae60e9596514c6ec497eb63f95320", - "sha256:327a8c2550ddc573b51e2c352adb88143464bb9d92c10416feb86b0f5aee5ff6", - "sha256:47e56d83aad53ca140da0af87678fb38e44fd6bc0af71eebab2d1f59b1acf1d3", - "sha256:501387a9edcb75d7ae8a4412bb8749900386eaef258f1aefab18adddea1936bc", - "sha256:552513d5cd5694590d7ef6f46e1767a4df9af168d449ff767b13b084c020e63f", - "sha256:5c4bc552ab52f6c1c506ccae05681fab58c3f72d59ae6e6639e8885e94fe2587", - "sha256:642496b675095d423f9b8448243336f8ec71c9d4d57ec17bf795b67f08132a91", - "sha256:6d1c6022b86f83b632d06f2b02774134def5d4d4f1dac8bef16d90cda18ba28a", - "sha256:7f3bf2dec7d541b4619b8ce526bda74a6b0bffc480a163fed32eb8b3c9aed8ad", - "sha256:831d8f54c3a8c8cf55f64d0422ee875eecac26f5f649fb6c1df65316b67c8926", - "sha256:8417dbd2f57b5701492cd46edcecc4f9208dc75529bcf76c514864e48da867d9", - "sha256:86cee259349b4448adb4ef9b204bb4467aae74a386bce85d56ba4f5dc0da27be", - "sha256:893695a76b140881531062d48476ebe4a48f5d1e9388177e175d76234ca247cd", - "sha256:9fd59d418c60c0348505f2ddf9609c1e1de8e7493eab96198fc89d9f865e7a96", - "sha256:ad0014efc7acf0bd745792bd0d8857413652979200ab924fbf239062adc12491", - "sha256:b5b0ee6d96b345a8b420100b7d71ebfdd19fab5e8301aff48ec270042cd40ac2", - "sha256:c333286dc3ddca6fdff74670b911cccedacb4ef0a60b34e491b8a67c833b343a", - "sha256:f9062af71c59c004cd519e2fb8f5d25d39e46d3af011b41ab43b9c74e27e236f", - "sha256:fb074d8b213749fa1d077d630db0d5f8cc3b2ae63587ad4116e8a436e9bbe995" + "sha256:257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474", + "sha256:37aae07b029fa0174d39daf02748b379399b909652a806e5708199bd93899da1", + "sha256:415e686e87dbbe6f4cd5ef0fbf764af7b89f9057b97c908742b6008cc554b9c0", + "sha256:48a85f2cb5e6799a9ef05347b476cce6c182d6c71ee36925a6c194d074336ef8", + "sha256:7768a0dbf16a39aa5e9a3ded568bb545c8c2727396d063bbaf847df05b08cd96", + "sha256:7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1", + "sha256:88c57dc656038f1ab9f92b3eb5335ee9b021412feaa46330d5eba4e51fe49b04", + "sha256:8e537d281831ad0e71007dcdcbe50a71470b978c453fa41ce77186bbe0ed6021", + "sha256:98e123f1d5cfd42f886624d84464f7756f60ff6eab89ae845210631714f6db94", + "sha256:accf49e151c8ed2c0cdc528691838afd217c50412534e876a19270fea1e28e2d", + "sha256:b1530ae42e9d6d5b670a34db49a94115a64596bc77710b1d05e9801e62ca0a7c", + "sha256:b9176b9832e84308818a99a561e90aa479e73c523b3f77afd07913380ae2eab7", + "sha256:bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c", + "sha256:be8bef99eb46d5021bf053114442914baeb3649a89dc5f3a555c88737e5e98fc", + "sha256:bf10f7310db693bb62692609b397e8d67257c55f949abde4c67f9cc574492cc7", + "sha256:c872b53057f000085da66a19c55d68f6f8ddcac2642392ad3a355878406fbd4d", + "sha256:d36ed1124bb81b32f8614555b34cc4259c3fbc7eec17870e8ff8ded335b58d8c", + "sha256:da33a1a5e49c4122ccdfd56cd021ff1ebc4a1ec4e2d01594fef9b6f267a9e741", + "sha256:dd1b5a14e417189db4c7b64a6540f31730713d173f0b63e55fabd52d61d8fdce", + "sha256:e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb", + "sha256:eaea3008c281f1038edb473c1aa8ed8143a5535ff18f978a318f10302b254063", + "sha256:ef703f83fc32e131e9bcc0a5094cfe85599e7109f896fe8bc96cc402f3eb4b6e" ], "index": "pypi", - "version": "==23.7.0" + "markers": "python_version >= '3.8'", + "version": "==24.4.2" }, "boto3": { "hashes": [ - "sha256:34f07b3fc2503240c0f58114cf3afea91295c7996d084991b78a278a56157c48", - "sha256:610369a7f984b58973c097ea649ec81976c04565d39a2d6d3edc280d23b0cb87" + "sha256:56840d8ce91654d182f1c113f0791fa2113c3aa43230c50b4481f235348a6037", + "sha256:b2d7400ff84fa547e53b3d9acfa3c95d65d45b5886ba1ede1f7df4768d1cc0b1" ], "index": "pypi", - "version": "==1.28.3" + "markers": "python_version >= '3.8'", + "version": "==1.34.122" }, "boto3-stubs": { "hashes": [ - "sha256:0561c14b7f3839d4692bbfb2c428a7ce43791e3fd3658d29127ad8c47e3309c1", - "sha256:7e27e26b12ba0ccf6da91ea48f31ef0e96e5dc52ece8d15fa47f64d4dd3209af" + "sha256:80974a53998d880af974c54d584fd70733b10f84246e40e7458eaf4d3b27a176", + "sha256:861d12fe7ab8dee3badac5addc95f24dc1cb097677e8f635678c6be4b8ad95cf" ], "index": "pypi", - "version": "==1.28.3" + "markers": "python_version >= '3.8'", + "version": "==1.34.122" }, "botocore": { "hashes": [ - "sha256:2aa27c75e62bfcf7900cb85283228fcb7df0fa1bdc2ae76dcee90788dd444934", - "sha256:744ce853cadc7ae87ba42ef6828194ddec97d606dd4d08b4dfe3d96d5001eb0c" + "sha256:6d75df3af831b62f0c7baa109728d987e0a8d34bfadf0476eb32e2f29a079a36", + "sha256:9374e16a36f1062c3e27816e8599b53eba99315dfac71cc84fc3aee3f5d3cbe3" ], - "markers": "python_version >= '3.7'", - "version": "==1.31.3" + "markers": "python_version >= '3.8'", + "version": "==1.34.122" }, "botocore-stubs": { "hashes": [ - "sha256:2b46a184e40e3f02632b17cb3170030dad83a906b51d7bb2f60a2bcf54043ba5", - "sha256:50a5b9a961cc45cf68e5d25e31050d373bbb8ea5f45f04af71e18f5a7e98e6d6" + "sha256:a17d4c5b5a3c10e8fab66dc17fbf2a1dbcc9da60b8e09d23a6cf851ccedbfaaf", + "sha256:dda8ea2edb1b5098e6b881a13b0197735c01a2d52ae2916f2abdda3045efbe0b" ], - "markers": "python_version >= '3.7' and python_version < '4.0'", - "version": "==1.31.3" + "markers": "python_version >= '3.8' and python_version < '4.0'", + "version": "==1.34.122" }, "certifi": { "hashes": [ - "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7", - "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716" + "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516", + "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56" ], "markers": "python_version >= '3.6'", - "version": "==2023.5.7" + "version": "==2024.6.2" }, "cffi": { "hashes": [ - "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5", - "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef", - "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104", - "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426", - "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405", - "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375", - "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a", - "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e", - "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc", - "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf", - "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185", - "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497", - "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3", - "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35", - "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c", - "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83", - "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21", - "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca", - "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984", - "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac", - "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd", - "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee", - "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a", - "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2", - "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192", - "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7", - "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585", - "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f", - "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e", - "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27", - "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b", - "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e", - "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e", - "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d", - "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c", - "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415", - "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82", - "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02", - "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314", - "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325", - "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c", - "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3", - "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914", - "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045", - "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d", - "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9", - "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5", - "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2", - "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c", - "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3", - "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2", - "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8", - "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d", - "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d", - "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9", - "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162", - "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76", - "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4", - "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e", - "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9", - "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6", - "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b", - "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01", - "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0" - ], - "version": "==1.15.1" + "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc", + "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a", + "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417", + "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab", + "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520", + "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36", + "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743", + "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8", + "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed", + "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684", + "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56", + "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324", + "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d", + "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235", + "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e", + "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088", + "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000", + "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7", + "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e", + "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673", + "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c", + "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe", + "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2", + "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098", + "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8", + "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a", + "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0", + "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b", + "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896", + "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e", + "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9", + "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2", + "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b", + "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6", + "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404", + "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f", + "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0", + "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4", + "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc", + "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936", + "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba", + "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872", + "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb", + "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614", + "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1", + "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d", + "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969", + "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b", + "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4", + "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627", + "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956", + "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357" + ], + "markers": "platform_python_implementation != 'PyPy'", + "version": "==1.16.0" + }, + "cfgv": { + "hashes": [ + "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", + "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560" + ], + "markers": "python_version >= '3.8'", + "version": "==3.4.0" }, "charset-normalizer": { "hashes": [ - "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96", - "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c", - "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710", - "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706", - "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020", - "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252", - "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad", - "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329", - "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a", - "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f", - "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6", - "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4", - "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a", - "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46", - "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2", - "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23", - "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace", - "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd", - "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982", - "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10", - "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2", - "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea", - "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09", - "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5", - "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149", - "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489", - "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9", - "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80", - "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592", - "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3", - "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6", - "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed", - "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c", - "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200", - "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a", - "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e", - "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d", - "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6", - "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623", - "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669", - "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3", - "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa", - "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9", - "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2", - "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f", - "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1", - "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4", - "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a", - "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8", - "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3", - "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029", - "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f", - "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959", - "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22", - "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7", - "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952", - "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346", - "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e", - "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d", - "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299", - "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd", - "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a", - "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3", - "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037", - "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94", - "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c", - "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858", - "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a", - "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449", - "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c", - "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918", - "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1", - "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c", - "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac", - "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa" + "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027", + "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087", + "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786", + "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8", + "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09", + "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185", + "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574", + "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e", + "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519", + "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898", + "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269", + "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3", + "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f", + "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6", + "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8", + "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a", + "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73", + "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc", + "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714", + "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2", + "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc", + "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce", + "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d", + "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e", + "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6", + "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269", + "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96", + "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d", + "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a", + "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4", + "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77", + "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d", + "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0", + "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed", + "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068", + "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac", + "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25", + "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8", + "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab", + "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26", + "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2", + "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db", + "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f", + "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5", + "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99", + "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c", + "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d", + "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811", + "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa", + "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a", + "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03", + "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b", + "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04", + "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c", + "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001", + "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458", + "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389", + "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99", + "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985", + "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537", + "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238", + "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f", + "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d", + "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796", + "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a", + "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143", + "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8", + "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c", + "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5", + "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5", + "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711", + "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4", + "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6", + "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c", + "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7", + "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4", + "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b", + "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae", + "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12", + "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c", + "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae", + "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8", + "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887", + "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b", + "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4", + "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f", + "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5", + "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33", + "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519", + "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561" ], "markers": "python_full_version >= '3.7.0'", - "version": "==3.2.0" + "version": "==3.3.2" }, "click": { "hashes": [ @@ -691,116 +806,124 @@ "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==8.1.3" }, - "colorama": { - "hashes": [ - "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", - "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" - ], - "markers": "python_version >= '3.5'", - "version": "==0.4.6" - }, "coverage": { - "hashes": [ - "sha256:027018943386e7b942fa832372ebc120155fd970837489896099f5cfa2890f79", - "sha256:11b990d520ea75e7ee8dcab5bc908072aaada194a794db9f6d7d5cfd19661e5a", - "sha256:12adf310e4aafddc58afdb04d686795f33f4d7a6fa67a7a9d4ce7d6ae24d949f", - "sha256:1431986dac3923c5945271f169f59c45b8802a114c8f548d611f2015133df77a", - "sha256:1ef221513e6f68b69ee9e159506d583d31aa3567e0ae84eaad9d6ec1107dddaa", - "sha256:20c8ac5386253717e5ccc827caad43ed66fea0efe255727b1053a8154d952398", - "sha256:2198ea6fc548de52adc826f62cb18554caedfb1d26548c1b7c88d8f7faa8f6ba", - "sha256:255758a1e3b61db372ec2736c8e2a1fdfaf563977eedbdf131de003ca5779b7d", - "sha256:265de0fa6778d07de30bcf4d9dc471c3dc4314a23a3c6603d356a3c9abc2dfcf", - "sha256:33a7da4376d5977fbf0a8ed91c4dffaaa8dbf0ddbf4c8eea500a2486d8bc4d7b", - "sha256:42eafe6778551cf006a7c43153af1211c3aaab658d4d66fa5fcc021613d02518", - "sha256:4433b90fae13f86fafff0b326453dd42fc9a639a0d9e4eec4d366436d1a41b6d", - "sha256:4a5375e28c5191ac38cca59b38edd33ef4cc914732c916f2929029b4bfb50795", - "sha256:4a8dbc1f0fbb2ae3de73eb0bdbb914180c7abfbf258e90b311dcd4f585d44bd2", - "sha256:59f53f1dc5b656cafb1badd0feb428c1e7bc19b867479ff72f7a9dd9b479f10e", - "sha256:5dbec3b9095749390c09ab7c89d314727f18800060d8d24e87f01fb9cfb40b32", - "sha256:633713d70ad6bfc49b34ead4060531658dc6dfc9b3eb7d8a716d5873377ab745", - "sha256:6b07130585d54fe8dff3d97b93b0e20290de974dc8177c320aeaf23459219c0b", - "sha256:6c4459b3de97b75e3bd6b7d4b7f0db13f17f504f3d13e2a7c623786289dd670e", - "sha256:6d4817234349a80dbf03640cec6109cd90cba068330703fa65ddf56b60223a6d", - "sha256:723e8130d4ecc8f56e9a611e73b31219595baa3bb252d539206f7bbbab6ffc1f", - "sha256:784f53ebc9f3fd0e2a3f6a78b2be1bd1f5575d7863e10c6e12504f240fd06660", - "sha256:7b6be138d61e458e18d8e6ddcddd36dd96215edfe5f1168de0b1b32635839b62", - "sha256:7ccf362abd726b0410bf8911c31fbf97f09f8f1061f8c1cf03dfc4b6372848f6", - "sha256:83516205e254a0cb77d2d7bb3632ee019d93d9f4005de31dca0a8c3667d5bc04", - "sha256:851cf4ff24062c6aec510a454b2584f6e998cada52d4cb58c5e233d07172e50c", - "sha256:8f830ed581b45b82451a40faabb89c84e1a998124ee4212d440e9c6cf70083e5", - "sha256:94e2565443291bd778421856bc975d351738963071e9b8839ca1fc08b42d4bef", - "sha256:95203854f974e07af96358c0b261f1048d8e1083f2de9b1c565e1be4a3a48cfc", - "sha256:97117225cdd992a9c2a5515db1f66b59db634f59d0679ca1fa3fe8da32749cae", - "sha256:98e8a10b7a314f454d9eff4216a9a94d143a7ee65018dd12442e898ee2310578", - "sha256:a1170fa54185845505fbfa672f1c1ab175446c887cce8212c44149581cf2d466", - "sha256:a6b7d95969b8845250586f269e81e5dfdd8ff828ddeb8567a4a2eaa7313460c4", - "sha256:a8fb6cf131ac4070c9c5a3e21de0f7dc5a0fbe8bc77c9456ced896c12fcdad91", - "sha256:af4fffaffc4067232253715065e30c5a7ec6faac36f8fc8d6f64263b15f74db0", - "sha256:b4a5be1748d538a710f87542f22c2cad22f80545a847ad91ce45e77417293eb4", - "sha256:b5604380f3415ba69de87a289a2b56687faa4fe04dbee0754bfcae433489316b", - "sha256:b9023e237f4c02ff739581ef35969c3739445fb059b060ca51771e69101efffe", - "sha256:bc8ef5e043a2af066fa8cbfc6e708d58017024dc4345a1f9757b329a249f041b", - "sha256:c4ed2820d919351f4167e52425e096af41bfabacb1857186c1ea32ff9983ed75", - "sha256:cca4435eebea7962a52bdb216dec27215d0df64cf27fc1dd538415f5d2b9da6b", - "sha256:d900bb429fdfd7f511f868cedd03a6bbb142f3f9118c09b99ef8dc9bf9643c3c", - "sha256:d9ecf0829c6a62b9b573c7bb6d4dcd6ba8b6f80be9ba4fc7ed50bf4ac9aecd72", - "sha256:dbdb91cd8c048c2b09eb17713b0c12a54fbd587d79adcebad543bc0cd9a3410b", - "sha256:de3001a203182842a4630e7b8d1a2c7c07ec1b45d3084a83d5d227a3806f530f", - "sha256:e07f4a4a9b41583d6eabec04f8b68076ab3cd44c20bd29332c6572dda36f372e", - "sha256:ef8674b0ee8cc11e2d574e3e2998aea5df5ab242e012286824ea3c6970580e53", - "sha256:f4f05d88d9a80ad3cac6244d36dd89a3c00abc16371769f1340101d3cb899fc3", - "sha256:f642e90754ee3e06b0e7e51bce3379590e76b7f76b708e1a71ff043f87025c84", - "sha256:fc2af30ed0d5ae0b1abdb4ebdce598eafd5b35397d4d75deb341a614d333d987" + "extras": [ + "toml" + ], + "hashes": [ + "sha256:015eddc5ccd5364dcb902eaecf9515636806fa1e0d5bef5769d06d0f31b54523", + "sha256:04aefca5190d1dc7a53a4c1a5a7f8568811306d7a8ee231c42fb69215571944f", + "sha256:05ac5f60faa0c704c0f7e6a5cbfd6f02101ed05e0aee4d2822637a9e672c998d", + "sha256:0bbddc54bbacfc09b3edaec644d4ac90c08ee8ed4844b0f86227dcda2d428fcb", + "sha256:1d2a830ade66d3563bb61d1e3c77c8def97b30ed91e166c67d0632c018f380f0", + "sha256:239a4e75e09c2b12ea478d28815acf83334d32e722e7433471fbf641c606344c", + "sha256:244f509f126dc71369393ce5fea17c0592c40ee44e607b6d855e9c4ac57aac98", + "sha256:25a5caf742c6195e08002d3b6c2dd6947e50efc5fc2c2205f61ecb47592d2d83", + "sha256:296a7d9bbc598e8744c00f7a6cecf1da9b30ae9ad51c566291ff1314e6cbbed8", + "sha256:2e079c9ec772fedbade9d7ebc36202a1d9ef7291bc9b3a024ca395c4d52853d7", + "sha256:33ca90a0eb29225f195e30684ba4a6db05dbef03c2ccd50b9077714c48153cac", + "sha256:33fc65740267222fc02975c061eb7167185fef4cc8f2770267ee8bf7d6a42f84", + "sha256:341dd8f61c26337c37988345ca5c8ccabeff33093a26953a1ac72e7d0103c4fb", + "sha256:34d6d21d8795a97b14d503dcaf74226ae51eb1f2bd41015d3ef332a24d0a17b3", + "sha256:3538d8fb1ee9bdd2e2692b3b18c22bb1c19ffbefd06880f5ac496e42d7bb3884", + "sha256:38a3b98dae8a7c9057bd91fbf3415c05e700a5114c5f1b5b0ea5f8f429ba6614", + "sha256:3d5a67f0da401e105753d474369ab034c7bae51a4c31c77d94030d59e41df5bd", + "sha256:50084d3516aa263791198913a17354bd1dc627d3c1639209640b9cac3fef5807", + "sha256:55f689f846661e3f26efa535071775d0483388a1ccfab899df72924805e9e7cd", + "sha256:5bc5a8c87714b0c67cfeb4c7caa82b2d71e8864d1a46aa990b5588fa953673b8", + "sha256:62bda40da1e68898186f274f832ef3e759ce929da9a9fd9fcf265956de269dbc", + "sha256:705f3d7c2b098c40f5b81790a5fedb274113373d4d1a69e65f8b68b0cc26f6db", + "sha256:75e3f4e86804023e991096b29e147e635f5e2568f77883a1e6eed74512659ab0", + "sha256:7b2a19e13dfb5c8e145c7a6ea959485ee8e2204699903c88c7d25283584bfc08", + "sha256:7cec2af81f9e7569280822be68bd57e51b86d42e59ea30d10ebdbb22d2cb7232", + "sha256:8383a6c8cefba1b7cecc0149415046b6fc38836295bc4c84e820872eb5478b3d", + "sha256:8c836309931839cca658a78a888dab9676b5c988d0dd34ca247f5f3e679f4e7a", + "sha256:8e317953bb4c074c06c798a11dbdd2cf9979dbcaa8ccc0fa4701d80042d4ebf1", + "sha256:923b7b1c717bd0f0f92d862d1ff51d9b2b55dbbd133e05680204465f454bb286", + "sha256:990fb20b32990b2ce2c5f974c3e738c9358b2735bc05075d50a6f36721b8f303", + "sha256:9aad68c3f2566dfae84bf46295a79e79d904e1c21ccfc66de88cd446f8686341", + "sha256:a5812840d1d00eafae6585aba38021f90a705a25b8216ec7f66aebe5b619fb84", + "sha256:a6519d917abb15e12380406d721e37613e2a67d166f9fb7e5a8ce0375744cd45", + "sha256:ab0b028165eea880af12f66086694768f2c3139b2c31ad5e032c8edbafca6ffc", + "sha256:aea7da970f1feccf48be7335f8b2ca64baf9b589d79e05b9397a06696ce1a1ec", + "sha256:b1196e13c45e327d6cd0b6e471530a1882f1017eb83c6229fc613cd1a11b53cd", + "sha256:b368e1aee1b9b75757942d44d7598dcd22a9dbb126affcbba82d15917f0cc155", + "sha256:bde997cac85fcac227b27d4fb2c7608a2c5f6558469b0eb704c5726ae49e1c52", + "sha256:c4c2872b3c91f9baa836147ca33650dc5c172e9273c808c3c3199c75490e709d", + "sha256:c59d2ad092dc0551d9f79d9d44d005c945ba95832a6798f98f9216ede3d5f485", + "sha256:d1da0a2e3b37b745a2b2a678a4c796462cf753aebf94edcc87dcc6b8641eae31", + "sha256:d8b7339180d00de83e930358223c617cc343dd08e1aa5ec7b06c3a121aec4e1d", + "sha256:dd4b3355b01273a56b20c219e74e7549e14370b31a4ffe42706a8cda91f19f6d", + "sha256:e08c470c2eb01977d221fd87495b44867a56d4d594f43739a8028f8646a51e0d", + "sha256:f5102a92855d518b0996eb197772f5ac2a527c0ec617124ad5242a3af5e25f85", + "sha256:f542287b1489c7a860d43a7d8883e27ca62ab84ca53c965d11dac1d3a1fab7ce", + "sha256:f78300789a708ac1f17e134593f577407d52d0417305435b134805c4fb135adb", + "sha256:f81bc26d609bf0fbc622c7122ba6307993c83c795d2d6f6f6fd8c000a770d974", + "sha256:f836c174c3a7f639bded48ec913f348c4761cbf49de4a20a956d3431a7c9cb24", + "sha256:fa21a04112c59ad54f69d80e376f7f9d0f5f9123ab87ecd18fbb9ec3a2beed56", + "sha256:fcf7d1d6f5da887ca04302db8e0e0cf56ce9a5e05f202720e49b3e8157ddb9a9", + "sha256:fd27d8b49e574e50caa65196d908f80e4dff64d7e592d0c59788b45aad7e8b35" ], "index": "pypi", - "version": "==6.5.0" + "markers": "python_version >= '3.8'", + "version": "==7.5.3" }, "coveralls": { "hashes": [ - "sha256:b32a8bb5d2df585207c119d6c01567b81fba690c9c10a753bfe27a335bfc43ea", - "sha256:f42015f31d386b351d4226389b387ae173207058832fbf5c8ec4b40e27b16026" + "sha256:7a6b1fa9848332c7b2221afb20f3df90272ac0167060f41b5fe90429b30b1809", + "sha256:7b2a0a2bcef94f295e3cf28dcc55ca40b71c77d1c2446b538e85f0f7bc21aa69" ], "index": "pypi", - "version": "==3.3.1" + "markers": "python_version < '3.13' and python_version >= '3.8'", + "version": "==4.0.1" }, "cryptography": { "hashes": [ - "sha256:01f1d9e537f9a15b037d5d9ee442b8c22e3ae11ce65ea1f3316a41c78756b711", - "sha256:079347de771f9282fbfe0e0236c716686950c19dee1b76240ab09ce1624d76d7", - "sha256:182be4171f9332b6741ee818ec27daff9fb00349f706629f5cbf417bd50e66fd", - "sha256:192255f539d7a89f2102d07d7375b1e0a81f7478925b3bc2e0549ebf739dae0e", - "sha256:2a034bf7d9ca894720f2ec1d8b7b5832d7e363571828037f9e0c4f18c1b58a58", - "sha256:342f3767e25876751e14f8459ad85e77e660537ca0a066e10e75df9c9e9099f0", - "sha256:439c3cc4c0d42fa999b83ded80a9a1fb54d53c58d6e59234cfe97f241e6c781d", - "sha256:49c3222bb8f8e800aead2e376cbef687bc9e3cb9b58b29a261210456a7783d83", - "sha256:674b669d5daa64206c38e507808aae49904c988fa0a71c935e7006a3e1e83831", - "sha256:7a9a3bced53b7f09da251685224d6a260c3cb291768f54954e28f03ef14e3766", - "sha256:7af244b012711a26196450d34f483357e42aeddb04128885d95a69bd8b14b69b", - "sha256:7d230bf856164de164ecb615ccc14c7fc6de6906ddd5b491f3af90d3514c925c", - "sha256:84609ade00a6ec59a89729e87a503c6e36af98ddcd566d5f3be52e29ba993182", - "sha256:9a6673c1828db6270b76b22cc696f40cde9043eb90373da5c2f8f2158957f42f", - "sha256:9b6d717393dbae53d4e52684ef4f022444fc1cce3c48c38cb74fca29e1f08eaa", - "sha256:9c3fe6534d59d071ee82081ca3d71eed3210f76ebd0361798c74abc2bcf347d4", - "sha256:a719399b99377b218dac6cf547b6ec54e6ef20207b6165126a280b0ce97e0d2a", - "sha256:b332cba64d99a70c1e0836902720887fb4529ea49ea7f5462cf6640e095e11d2", - "sha256:d124682c7a23c9764e54ca9ab5b308b14b18eba02722b8659fb238546de83a76", - "sha256:d73f419a56d74fef257955f51b18d046f3506270a5fd2ac5febbfa259d6c0fa5", - "sha256:f0dc40e6f7aa37af01aba07277d3d64d5a03dc66d682097541ec4da03cc140ee", - "sha256:f14ad275364c8b4e525d018f6716537ae7b6d369c094805cae45300847e0894f", - "sha256:f772610fe364372de33d76edcd313636a25684edb94cee53fd790195f5989d14" + "sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad", + "sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583", + "sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b", + "sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c", + "sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1", + "sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648", + "sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949", + "sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba", + "sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c", + "sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9", + "sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d", + "sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c", + "sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e", + "sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2", + "sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d", + "sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7", + "sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70", + "sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2", + "sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7", + "sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14", + "sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe", + "sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e", + "sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71", + "sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961", + "sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7", + "sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c", + "sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28", + "sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842", + "sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902", + "sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801", + "sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a", + "sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e" ], "markers": "python_version >= '3.7'", - "version": "==41.0.2" + "version": "==42.0.8" }, - "dill": { + "distlib": { "hashes": [ - "sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0", - "sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373" + "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784", + "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64" ], - "markers": "python_version >= '3.11'", - "version": "==0.3.6" + "version": "==0.3.8" }, "docopt": { "hashes": [ @@ -808,60 +931,37 @@ ], "version": "==0.6.2" }, - "eradicate": { - "hashes": [ - "sha256:06df115be3b87d0fc1c483db22a2ebb12bcf40585722810d809cc770f5031c37", - "sha256:2b29b3dd27171f209e4ddd8204b70c02f0682ae95eecb353f10e8d72b149c63e" - ], - "version": "==2.3.0" - }, - "gitdb": { + "filelock": { "hashes": [ - "sha256:6eb990b69df4e15bad899ea868dc46572c3f75339735663b81de79b06f17eb9a", - "sha256:c286cf298426064079ed96a9e4a9d39e7f3e9bf15ba60701e95f5492f28415c7" + "sha256:43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f", + "sha256:6ea72da3be9b8c82afd3edcf99f2fffbb5076335a5ae4d03248bb5b6c3eae78a" ], - "markers": "python_version >= '3.7'", - "version": "==4.0.10" + "markers": "python_version >= '3.8'", + "version": "==3.14.0" }, - "gitpython": { + "identify": { "hashes": [ - "sha256:8d9b8cb1e80b9735e8717c9362079d3ce4c6e5ddeebedd0361b228c3a67a62f6", - "sha256:e3d59b1c2c6ebb9dfa7a184daf3b6dd4914237e7488a1730a6d8f6f5d0b4187f" + "sha256:37d93f380f4de590500d9dba7db359d0d3da95ffe7f9de1753faa159e71e7dfa", + "sha256:e5e00f54165f9047fbebeb4a560f9acfb8af4c88232be60a488e9b68d122745d" ], - "markers": "python_version >= '3.7'", - "version": "==3.1.32" + "markers": "python_version >= '3.8'", + "version": "==2.5.36" }, "idna": { "hashes": [ - "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4", - "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2" + "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc", + "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0" ], "markers": "python_version >= '3.5'", - "version": "==3.4" - }, - "iniconfig": { - "hashes": [ - "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", - "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374" - ], - "markers": "python_version >= '3.7'", - "version": "==2.0.0" - }, - "isort": { - "hashes": [ - "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504", - "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6" - ], - "markers": "python_full_version >= '3.8.0'", - "version": "==5.12.0" + "version": "==3.7" }, "jinja2": { "hashes": [ - "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852", - "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61" + "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369", + "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d" ], "markers": "python_version >= '3.7'", - "version": "==3.1.2" + "version": "==3.1.4" }, "jmespath": { "hashes": [ @@ -871,134 +971,71 @@ "markers": "python_version >= '3.7'", "version": "==1.0.1" }, - "lazy-object-proxy": { - "hashes": [ - "sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382", - "sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82", - "sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9", - "sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494", - "sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46", - "sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30", - "sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63", - "sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4", - "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae", - "sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be", - "sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701", - "sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd", - "sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006", - "sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a", - "sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586", - "sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8", - "sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821", - "sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07", - "sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b", - "sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171", - "sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b", - "sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2", - "sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7", - "sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4", - "sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8", - "sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e", - "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f", - "sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda", - "sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4", - "sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e", - "sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671", - "sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11", - "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455", - "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734", - "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb", - "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59" - ], - "markers": "python_version >= '3.7'", - "version": "==1.9.0" - }, - "mando": { - "hashes": [ - "sha256:18baa999b4b613faefb00eac4efadcf14f510b59b924b66e08289aa1de8c3500", - "sha256:26ef1d70928b6057ee3ca12583d73c63e05c49de8972d620c278a7b206581a8a" - ], - "version": "==0.7.1" - }, - "markdown-it-py": { - "hashes": [ - "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", - "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb" - ], - "markers": "python_version >= '3.8'", - "version": "==3.0.0" - }, "markupsafe": { "hashes": [ - "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e", - "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e", - "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431", - "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686", - "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559", - "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc", - "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c", - "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0", - "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4", - "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9", - "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575", - "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba", - "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d", - "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3", - "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00", - "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155", - "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac", - "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52", - "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f", - "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8", - "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b", - "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24", - "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea", - "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198", - "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0", - "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee", - "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be", - "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2", - "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707", - "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6", - "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58", - "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779", - "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636", - "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c", - "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad", - "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee", - "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc", - "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2", - "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48", - "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7", - "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e", - "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b", - "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa", - "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5", - "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e", - "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb", - "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9", - "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57", - "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc", - "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2" + "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf", + "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff", + "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f", + "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3", + "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532", + "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f", + "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617", + "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df", + "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4", + "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906", + "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f", + "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4", + "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8", + "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371", + "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2", + "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465", + "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52", + "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6", + "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169", + "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad", + "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2", + "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0", + "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029", + "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f", + "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a", + "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced", + "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5", + "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c", + "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf", + "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9", + "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb", + "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad", + "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3", + "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1", + "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46", + "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc", + "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a", + "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee", + "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900", + "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5", + "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea", + "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f", + "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5", + "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e", + "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a", + "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f", + "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50", + "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a", + "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b", + "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4", + "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff", + "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2", + "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46", + "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b", + "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf", + "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5", + "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5", + "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab", + "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd", + "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68" ], "markers": "python_version >= '3.7'", - "version": "==2.1.3" - }, - "mccabe": { - "hashes": [ - "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", - "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e" - ], - "markers": "python_version >= '3.6'", - "version": "==0.7.0" - }, - "mdurl": { - "hashes": [ - "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", - "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba" - ], - "markers": "python_version >= '3.7'", - "version": "==0.1.2" + "version": "==2.1.5" }, "mock-ssh-server": { "hashes": [ @@ -1010,43 +1047,46 @@ }, "moto": { "hashes": [ - "sha256:25577e4cf55f05235f4efe78bcfeb5a7704fb75c16b426a5de2fc1e6b7b8545b", - "sha256:6f40141ff2f3a309c19faa169433afdf48d28733d328b08a843021ae36f005d9" + "sha256:21a13e02f83d6a18cfcd99949c96abb2e889f4bd51c4c6a3ecc8b78765cb854e", + "sha256:eb71f1cba01c70fff1f16086acb24d6d9aeb32830d646d8989f98a29aeae24ba" ], "index": "pypi", - "version": "==4.1.12" + "markers": "python_version >= '3.8'", + "version": "==5.0.9" }, "mypy": { "hashes": [ - "sha256:01fd2e9f85622d981fd9063bfaef1aed6e336eaacca00892cd2d82801ab7c042", - "sha256:0dde1d180cd84f0624c5dcaaa89c89775550a675aff96b5848de78fb11adabcd", - "sha256:141dedfdbfe8a04142881ff30ce6e6653c9685b354876b12e4fe6c78598b45e2", - "sha256:16f0db5b641ba159eff72cff08edc3875f2b62b2fa2bc24f68c1e7a4e8232d01", - "sha256:190b6bab0302cec4e9e6767d3eb66085aef2a1cc98fe04936d8a42ed2ba77bb7", - "sha256:2460a58faeea905aeb1b9b36f5065f2dc9a9c6e4c992a6499a2360c6c74ceca3", - "sha256:34a9239d5b3502c17f07fd7c0b2ae6b7dd7d7f6af35fbb5072c6208e76295816", - "sha256:43b592511672017f5b1a483527fd2684347fdffc041c9ef53428c8dc530f79a3", - "sha256:43d24f6437925ce50139a310a64b2ab048cb2d3694c84c71c3f2a1626d8101dc", - "sha256:45d32cec14e7b97af848bddd97d85ea4f0db4d5a149ed9676caa4eb2f7402bb4", - "sha256:470c969bb3f9a9efcedbadcd19a74ffb34a25f8e6b0e02dae7c0e71f8372f97b", - "sha256:566e72b0cd6598503e48ea610e0052d1b8168e60a46e0bfd34b3acf2d57f96a8", - "sha256:5703097c4936bbb9e9bce41478c8d08edd2865e177dc4c52be759f81ee4dd26c", - "sha256:7549fbf655e5825d787bbc9ecf6028731973f78088fbca3a1f4145c39ef09462", - "sha256:8207b7105829eca6f3d774f64a904190bb2231de91b8b186d21ffd98005f14a7", - "sha256:8c4d8e89aa7de683e2056a581ce63c46a0c41e31bd2b6d34144e2c80f5ea53dc", - "sha256:98324ec3ecf12296e6422939e54763faedbfcc502ea4a4c38502082711867258", - "sha256:9bbcd9ab8ea1f2e1c8031c21445b511442cc45c89951e49bbf852cbb70755b1b", - "sha256:9d40652cc4fe33871ad3338581dca3297ff5f2213d0df345bcfbde5162abf0c9", - "sha256:a2746d69a8196698146a3dbe29104f9eb6a2a4d8a27878d92169a6c0b74435b6", - "sha256:ae704dcfaa180ff7c4cfbad23e74321a2b774f92ca77fd94ce1049175a21c97f", - "sha256:bfdca17c36ae01a21274a3c387a63aa1aafe72bff976522886869ef131b937f1", - "sha256:c482e1246726616088532b5e964e39765b6d1520791348e6c9dc3af25b233828", - "sha256:ca637024ca67ab24a7fd6f65d280572c3794665eaf5edcc7e90a866544076878", - "sha256:e02d700ec8d9b1859790c0475df4e4092c7bf3272a4fd2c9f33d87fac4427b8f", - "sha256:e5952d2d18b79f7dc25e62e014fe5a23eb1a3d2bc66318df8988a01b1a037c5b" + "sha256:075cbf81f3e134eadaf247de187bd604748171d6b79736fa9b6c9685b4083061", + "sha256:12b6bfc1b1a66095ab413160a6e520e1dc076a28f3e22f7fb25ba3b000b4ef99", + "sha256:1ec404a7cbe9fc0e92cb0e67f55ce0c025014e26d33e54d9e506a0f2d07fe5de", + "sha256:28d0e038361b45f099cc086d9dd99c15ff14d0188f44ac883010e172ce86c38a", + "sha256:2b0695d605ddcd3eb2f736cd8b4e388288c21e7de85001e9f85df9187f2b50f9", + "sha256:3236a4c8f535a0631f85f5fcdffba71c7feeef76a6002fcba7c1a8e57c8be1ec", + "sha256:3be66771aa5c97602f382230165b856c231d1277c511c9a8dd058be4784472e1", + "sha256:3d087fcbec056c4ee34974da493a826ce316947485cef3901f511848e687c131", + "sha256:3f298531bca95ff615b6e9f2fc0333aae27fa48052903a0ac90215021cdcfa4f", + "sha256:4a2b5cdbb5dd35aa08ea9114436e0d79aceb2f38e32c21684dcf8e24e1e92821", + "sha256:4cf18f9d0efa1b16478c4c129eabec36148032575391095f73cae2e722fcf9d5", + "sha256:8b2cbaca148d0754a54d44121b5825ae71868c7592a53b7292eeb0f3fdae95ee", + "sha256:8f55583b12156c399dce2df7d16f8a5095291354f1e839c252ec6c0611e86e2e", + "sha256:92f93b21c0fe73dc00abf91022234c79d793318b8a96faac147cd579c1671746", + "sha256:9e36fb078cce9904c7989b9693e41cb9711e0600139ce3970c6ef814b6ebc2b2", + "sha256:9fd50226364cd2737351c79807775136b0abe084433b55b2e29181a4c3c878c0", + "sha256:a781f6ad4bab20eef8b65174a57e5203f4be627b46291f4589879bf4e257b97b", + "sha256:a87dbfa85971e8d59c9cc1fcf534efe664d8949e4c0b6b44e8ca548e746a8d53", + "sha256:b808e12113505b97d9023b0b5e0c0705a90571c6feefc6f215c1df9381256e30", + "sha256:bc6ac273b23c6b82da3bb25f4136c4fd42665f17f2cd850771cb600bdd2ebeda", + "sha256:cd777b780312ddb135bceb9bc8722a73ec95e042f911cc279e2ec3c667076051", + "sha256:da1cbf08fb3b851ab3b9523a884c232774008267b1f83371ace57f412fe308c2", + "sha256:e22e1527dc3d4aa94311d246b59e47f6455b8729f4968765ac1eacf9a4760bc7", + "sha256:f8c083976eb530019175aabadb60921e73b4f45736760826aa1689dda8208aee", + "sha256:f90cff89eea89273727d8783fef5d4a934be2fdca11b47def50cf5d311aff727", + "sha256:fa7ef5244615a2523b56c034becde4e9e3f9b034854c93639adb667ec9ec2976", + "sha256:fcfc70599efde5c67862a07a1aaf50e55bce629ace26bb19dc17cece5dd31ca4" ], "index": "pypi", - "version": "==1.4.1" + "markers": "python_version >= '3.8'", + "version": "==1.10.0" }, "mypy-extensions": { "hashes": [ @@ -1056,68 +1096,63 @@ "markers": "python_version >= '3.5'", "version": "==1.0.0" }, + "nodeenv": { + "hashes": [ + "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", + "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", + "version": "==1.9.1" + }, "packaging": { "hashes": [ - "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61", - "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f" + "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002", + "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124" ], - "markers": "python_version >= '3.7'", - "version": "==23.1" + "markers": "python_version >= '3.8'", + "version": "==24.1" }, "paramiko": { "hashes": [ - "sha256:93cdce625a8a1dc12204439d45033f3261bdb2c201648cfcdc06f9fd0f94ec29", - "sha256:df0f9dd8903bc50f2e10580af687f3015bf592a377cd438d2ec9546467a14eb8" + "sha256:43f0b51115a896f9c00f59618023484cb3a14b98bbceab43394a39c6739b7ee7", + "sha256:aac08f26a31dc4dffd92821527d1682d99d52f9ef6851968114a8728f3c274d3" ], "index": "pypi", - "version": "==3.2.0" + "markers": "python_version >= '3.6'", + "version": "==3.4.0" }, "pathspec": { "hashes": [ - "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687", - "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293" + "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", + "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712" ], - "markers": "python_version >= '3.7'", - "version": "==0.11.1" - }, - "pbr": { - "hashes": [ - "sha256:567f09558bae2b3ab53cb3c1e2e33e726ff3338e7bae3db5dc954b3a44eef12b", - "sha256:aefc51675b0b533d56bb5fd1c8c6c0522fe31896679882e1c4c63d5e4a0fccb3" - ], - "markers": "python_version >= '2.6'", - "version": "==5.11.1" + "markers": "python_version >= '3.8'", + "version": "==0.12.1" }, "platformdirs": { "hashes": [ - "sha256:cec7b889196b9144d088e4c57d9ceef7374f6c39694ad1577a0aab50d27ea28c", - "sha256:f87ca4fcff7d2b0f81c6a748a77973d7af0f4d526f98f308477c3c436c74d528" - ], - "markers": "python_version >= '3.7'", - "version": "==3.8.1" - }, - "pluggy": { - "hashes": [ - "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849", - "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3" + "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee", + "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3" ], - "markers": "python_version >= '3.7'", - "version": "==1.2.0" + "markers": "python_version >= '3.8'", + "version": "==4.2.2" }, - "pycodestyle": { + "pre-commit": { "hashes": [ - "sha256:347187bdb476329d98f695c213d7295a846d1152ff4fe9bacb8a9590b8ee7053", - "sha256:8a4eaf0d0495c7395bdab3589ac2db602797d76207242c17d470186815706610" + "sha256:8ca3ad567bc78a4972a3f1a477e94a79d4597e8140a6e0b651c5e33899c3654a", + "sha256:fae36fd1d7ad7d6a5a1c0b0d5adb2ed1a3bda5a21bf6c3e5372073d7a11cd4c5" ], - "markers": "python_version >= '3.6'", - "version": "==2.10.0" + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==3.7.1" }, "pycparser": { "hashes": [ - "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", - "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206" + "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", + "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc" ], - "version": "==2.21" + "markers": "python_version >= '3.8'", + "version": "==2.22" }, "pydocstyle": { "hashes": [ @@ -1125,41 +1160,8 @@ "sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1" ], "index": "pypi", - "version": "==6.3.0" - }, - "pyflakes": { - "hashes": [ - "sha256:ec55bf7fe21fff7f1ad2f7da62363d749e2a470500eab1b555334b67aa1ef8cf", - "sha256:ec8b276a6b60bd80defed25add7e439881c19e64850afd9b346283d4165fd0fd" - ], "markers": "python_version >= '3.6'", - "version": "==3.0.1" - }, - "pygments": { - "hashes": [ - "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c", - "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1" - ], - "markers": "python_version >= '3.7'", - "version": "==2.15.1" - }, - "pylama": { - "extras": [ - "all" - ], - "hashes": [ - "sha256:2d4f7aecfb5b7466216d48610c7d6bad1c3990c29cdd392ad08259b161e486f6", - "sha256:5bbdbf5b620aba7206d688ed9fc917ecd3d73e15ec1a89647037a09fa3a86e60" - ], - "index": "pypi", - "version": "==8.4.1" - }, - "pylint": { - "hashes": [ - "sha256:5dcf1d9e19f41f38e4e85d10f511e5b9c35e1aa74251bf95cdd8cb23584e2db1", - "sha256:7a1145fb08c251bdb5cca11739722ce64a63db479283d10ce718b2460e54123c" - ], - "version": "==2.17.4" + "version": "==6.3.0" }, "pynacl": { "hashes": [ @@ -1177,113 +1179,128 @@ "markers": "python_version >= '3.6'", "version": "==1.5.0" }, - "pytest": { - "hashes": [ - "sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32", - "sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a" - ], - "version": "==7.4.0" - }, "python-dateutil": { "hashes": [ - "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", - "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" + "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", + "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==2.8.2" + "version": "==2.9.0.post0" }, "pyyaml": { "hashes": [ - "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf", - "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293", - "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b", - "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57", - "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b", - "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4", - "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07", - "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba", - "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9", - "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287", - "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513", - "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0", - "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782", - "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0", - "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92", - "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f", - "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2", - "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc", - "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1", - "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c", - "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86", - "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4", - "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c", - "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34", - "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b", - "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d", - "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c", - "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb", - "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7", - "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737", - "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3", - "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d", - "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358", - "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53", - "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78", - "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803", - "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a", - "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f", - "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174", - "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5" + "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5", + "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc", + "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df", + "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741", + "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206", + "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27", + "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595", + "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62", + "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98", + "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696", + "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290", + "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9", + "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d", + "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6", + "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867", + "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47", + "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486", + "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6", + "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3", + "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007", + "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938", + "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0", + "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c", + "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735", + "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d", + "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28", + "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4", + "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba", + "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8", + "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef", + "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5", + "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd", + "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3", + "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0", + "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515", + "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c", + "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c", + "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924", + "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34", + "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43", + "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859", + "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673", + "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54", + "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a", + "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b", + "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab", + "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa", + "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c", + "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585", + "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d", + "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f" ], "markers": "python_version >= '3.6'", - "version": "==6.0" - }, - "radon": { - "hashes": [ - "sha256:632cc032364a6f8bb1010a2f6a12d0f14bc7e5ede76585ef29dc0cecf4cd8859", - "sha256:d1ac0053943a893878940fedc8b19ace70386fc9c9bf0a09229a44125ebf45b5" - ], "version": "==6.0.1" }, "requests": { "hashes": [ - "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f", - "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1" + "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", + "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6" ], "index": "pypi", - "version": "==2.31.0" + "markers": "python_version >= '3.8'", + "version": "==2.32.3" }, "requests-mock": { "hashes": [ - "sha256:ef10b572b489a5f28e09b708697208c4a3b2b89ef80a9f01584340ea357ec3c4", - "sha256:f7fae383f228633f6bececebdab236c478ace2284d6292c6e7e2867b9ab74d15" + "sha256:b1e37054004cdd5e56c84454cc7df12b25f90f382159087f4b6915aaeef39563", + "sha256:e9e12e333b525156e82a3c852f22016b9158220d2f47454de9cae8a77d371401" ], "index": "pypi", - "version": "==1.11.0" + "markers": "python_version >= '3.5'", + "version": "==1.12.1" }, "responses": { "hashes": [ - "sha256:8a3a5915713483bf353b6f4079ba8b2a29029d1d1090a503c70b0dc5d9d0c7bd", - "sha256:c4d9aa9fc888188f0c673eff79a8dadbe2e75b7fe879dc80a221a06e0a68138f" + "sha256:77a61ad7e6016ed2ac00739b7efa5f35c42351d5b9b5d26bb1be87f197632487", + "sha256:b59707ea25de536d324670791ab073fafd41f3a351cec9c51cb6147089a9a30a" ], - "markers": "python_version >= '3.7'", - "version": "==0.23.1" - }, - "rich": { - "hashes": [ - "sha256:8f87bc7ee54675732fa66a05ebfe489e27264caeeff3728c945d25971b6485ec", - "sha256:d653d6bccede5844304c605d5aac802c7cf9621efd700b46c7ec2b51ea914898" + "markers": "python_version >= '3.8'", + "version": "==0.25.2" + }, + "ruff": { + "hashes": [ + "sha256:14019a06dbe29b608f6b7cbcec300e3170a8d86efaddb7b23405cb7f7dcaf780", + "sha256:16d717b1d57b2e2fd68bd0bf80fb43931b79d05a7131aa477d66fc40fbd86268", + "sha256:284c2e3f3396fb05f5f803c9fffb53ebbe09a3ebe7dda2929ed8d73ded736deb", + "sha256:384154a1c3f4bf537bac69f33720957ee49ac8d484bfc91720cc94172026ceed", + "sha256:6d795d7639212c2dfd01991259460101c22aabf420d9b943f153ab9d9706e6a9", + "sha256:6ea874950daca5697309d976c9afba830d3bf0ed66887481d6bca1673fc5b66a", + "sha256:704977a658131651a22b5ebeb28b717ef42ac6ee3b11e91dc87b633b5d83142b", + "sha256:72584676164e15a68a15778fd1b17c28a519e7a0622161eb2debdcdabdc71883", + "sha256:7663a6d78f6adb0eab270fa9cf1ff2d28618ca3a652b60f2a234d92b9ec89066", + "sha256:9678d5c9b43315f323af2233a04d747409d1e3aa6789620083a82d1066a35199", + "sha256:a7354f921e3fbe04d2a62d46707e569f9315e1a613307f7311a935743c51a764", + "sha256:aad360893e92486662ef3be0a339c5ca3c1b109e0134fcd37d534d4be9fb8de3", + "sha256:d05f8d6f0c3cce5026cecd83b7a143dcad503045857bc49662f736437380ad45", + "sha256:e14a3a095d07560a9d6769a72f781d73259655919d9b396c650fc98a8157555d", + "sha256:e9d5ce97cacc99878aa0d084c626a15cd21e6b3d53fd6f9112b7fc485918e1fa", + "sha256:eeceb78da8afb6de0ddada93112869852d04f1cd0f6b80fe464fd4e35c330913", + "sha256:fc95aac2943ddf360376be9aa3107c8cf9640083940a8c5bd824be692d2216dc" ], - "markers": "python_full_version >= '3.7.0'", - "version": "==13.4.2" + "index": "pypi", + "markers": "python_version >= '3.7'", + "version": "==0.4.8" }, "s3transfer": { "hashes": [ - "sha256:3c0da2d074bf35d6870ef157158641178a4204a6e689e82546083e31e0311346", - "sha256:640bb492711f4c0c0905e1f62b6aaeb771881935ad27884852411f8e9cacbca9" + "sha256:5683916b4c724f799e600f41dd9e10a9ff19871bf87623cc8f491cb4f5fa0a19", + "sha256:ceb252b11bcf87080fb7850a224fb6e05c8a776bab8f2b64b7f25b969464839d" ], - "markers": "python_version >= '3.7'", - "version": "==0.6.1" + "markers": "python_version >= '3.8'", + "version": "==0.10.1" }, "six": { "hashes": [ @@ -1293,14 +1310,6 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.16.0" }, - "smmap": { - "hashes": [ - "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94", - "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936" - ], - "markers": "python_version >= '3.6'", - "version": "==5.0.0" - }, "snowballstemmer": { "hashes": [ "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1", @@ -1308,187 +1317,71 @@ ], "version": "==2.2.0" }, - "stevedore": { - "hashes": [ - "sha256:8cc040628f3cea5d7128f2e76cf486b2251a4e543c7b938f58d9a377f6694a2d", - "sha256:a54534acf9b89bc7ed264807013b505bf07f74dbe4bcfa37d32bd063870b087c" - ], - "markers": "python_version >= '3.8'", - "version": "==5.1.0" - }, - "toml": { - "hashes": [ - "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", - "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" - ], - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==0.10.2" - }, - "tomlkit": { - "hashes": [ - "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171", - "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3" - ], - "markers": "python_version >= '3.7'", - "version": "==0.11.8" - }, "types-awscrt": { "hashes": [ - "sha256:6cdfc458aca186fb73261895efeba1a2a0f3cf8f63f8b6ef32ec43739a64e4ae", - "sha256:cd0d4313fac0859a2b406080782076648524840e26780dbd3b5cbd9cc315834a" + "sha256:3236ba5097176080189135345acfcfeae18bac88869043daf55883649ce6e2ff", + "sha256:ad5ce9fb511414430326f19a513e23d3bc7143c10cdbe1cdaeb2222ad567698f" ], "markers": "python_version >= '3.7' and python_version < '4.0'", - "version": "==0.16.24" + "version": "==0.20.11" }, "types-paramiko": { "hashes": [ - "sha256:35325b21daefffa9aed135217cf60a7c4bf241ee40b8fa437432fd4f65e9af6e", - "sha256:a9b261303a4295042f4879a956ba4967822b6032af60e857f11528bb7bba94d3" + "sha256:aaa98dda232c47886563d66743d3a8b66c432790c596bc3bdd3f17f91be2a8c1", + "sha256:c56e0d43399a1b909901b1e0375e0ff6ee62e16cd6e00695024abc2e9fe02035" ], "index": "pypi", - "version": "==3.2.0.0" - }, - "types-pyyaml": { - "hashes": [ - "sha256:662fa444963eff9b68120d70cda1af5a5f2aa57900003c2006d7626450eaae5f", - "sha256:ebab3d0700b946553724ae6ca636ea932c1b0868701d4af121630e78d695fc97" - ], - "version": "==6.0.12.10" + "markers": "python_version >= '3.8'", + "version": "==3.4.0.20240423" }, "types-requests": { "hashes": [ - "sha256:3de667cffa123ce698591de0ad7db034a5317457a596eb0b4944e5a9d9e8d1ac", - "sha256:afb06ef8f25ba83d59a1d424bd7a5a939082f94b94e90ab5e6116bd2559deaa3" + "sha256:3f98d7bbd0dd94ebd10ff43a7fbe20c3b8528acace6d8efafef0b6a184793f06", + "sha256:ed3946063ea9fbc6b5fc0c44fa279188bae42d582cb63760be6cb4b9d06c3de8" ], "index": "pypi", - "version": "==2.31.0.1" + "markers": "python_version >= '3.8'", + "version": "==2.32.0.20240602" }, "types-s3transfer": { "hashes": [ - "sha256:6d1ac1dedac750d570428362acdf60fdd4f277b0788855c3894d3226756b2bfb", - "sha256:75ac1d7143d58c1e6af467cfd4a96c67ee058a3adf7c249d9309999e1f5f41e4" + "sha256:02154cce46528287ad76ad1a0153840e0492239a0887e8833466eccf84b98da0", + "sha256:49a7c81fa609ac1532f8de3756e64b58afcecad8767933310228002ec7adff74" ], - "markers": "python_version >= '3.7' and python_version < '4.0'", - "version": "==0.6.1" - }, - "types-urllib3": { - "hashes": [ - "sha256:3300538c9dc11dad32eae4827ac313f5d986b8b21494801f1bf97a1ac6c03ae5", - "sha256:5dbd1d2bef14efee43f5318b5d36d805a489f6600252bb53626d4bfafd95e27c" - ], - "version": "==1.26.25.13" + "markers": "python_version >= '3.8' and python_version < '4.0'", + "version": "==0.10.1" }, "typing-extensions": { "hashes": [ - "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36", - "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2" + "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", + "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8" ], - "markers": "python_version >= '3.7'", - "version": "==4.7.1" + "markers": "python_version >= '3.8'", + "version": "==4.12.2" }, "urllib3": { "hashes": [ - "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f", - "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14" + "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d", + "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==1.26.16" + "markers": "python_version >= '3.8'", + "version": "==2.2.1" }, - "vulture": { + "virtualenv": { "hashes": [ - "sha256:67fb80a014ed9fdb599dd44bb96cb54311032a104106fc2e706ef7a6dad88032", - "sha256:bccc51064ed76db15a6b58277cea8885936af047f53d2655fb5de575e93d0bca" + "sha256:82bf0f4eebbb78d36ddaee0283d43fe5736b53880b8a8cdcd37390a07ac3741c", + "sha256:a624db5e94f01ad993d476b9ee5346fdf7b9de43ccaee0e0197012dc838a0e9b" ], - "version": "==2.7" + "markers": "python_version >= '3.7'", + "version": "==20.26.2" }, "werkzeug": { "hashes": [ - "sha256:935539fa1413afbb9195b24880778422ed620c0fc09670945185cce4d91a8890", - "sha256:98c774df2f91b05550078891dee5f0eb0cb797a522c757a2452b9cee5b202330" + "sha256:097e5bfda9f0aba8da6b8545146def481d06aa7d3266e7448e2cccf67dd8bd18", + "sha256:fc9645dc43e03e4d630d23143a04a7f947a9a3b5727cd535fdfe155a17cc48c8" ], "markers": "python_version >= '3.8'", - "version": "==2.3.6" - }, - "wrapt": { - "hashes": [ - "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0", - "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420", - "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a", - "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c", - "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079", - "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923", - "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f", - "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1", - "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8", - "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86", - "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0", - "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364", - "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e", - "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c", - "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e", - "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c", - "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727", - "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff", - "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e", - "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29", - "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7", - "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72", - "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475", - "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a", - "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317", - "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2", - "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd", - "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640", - "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98", - "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248", - "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e", - "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d", - "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec", - "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1", - "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e", - "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9", - "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92", - "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb", - "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094", - "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46", - "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29", - "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd", - "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705", - "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8", - "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975", - "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb", - "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e", - "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b", - "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418", - "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019", - "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1", - "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba", - "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6", - "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2", - "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3", - "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7", - "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752", - "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416", - "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f", - "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1", - "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc", - "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145", - "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee", - "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a", - "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7", - "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b", - "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653", - "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0", - "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90", - "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29", - "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6", - "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034", - "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09", - "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559", - "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639" - ], - "markers": "python_version >= '3.11'", - "version": "==1.15.0" + "version": "==3.0.3" }, "xmltodict": { "hashes": [ diff --git a/README.md b/README.md index 2a2b7b5..80dc5e0 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # sapinvoices -Transmits ready-to-be-paid invoice data from Alma to MIT accounts payable department's SAP system -sets trasmitted invoice to paid in Alma +Transmits ready-to-be-paid invoice data from Alma to MIT accounts payable department's SAP +system and sets transmitted invoices to paid in Alma. ## Development @@ -12,20 +12,24 @@ sets trasmitted invoice to paid in Alma - To run the app: `pipenv run sap --help` ## Required ENV -- `ALMA_API_URL` = Base URL for making Alma API calls -- `ALMA_API_READ_WRITE_KEY` = API key for making Alma API calls -- `SAP_DROPBOX_CLOUDCONNECTOR_JSON` = JSON formatted connection information for accessing SAP dropbox -- `SAP_REPLY_TO_EMAIL` = reply-to email on emails to SAP recipient email lists -- `SAP_FINAL_RECIPIENT_EMAIL` = moira list to recieves final run emails -- `SAP_REVIEW_RECIPIENT_EMAIL` = moira list to recieve review run emails -- `SES_SEND_FROM_EMAIL` = email address that SES sends from -- `SAP_SEQUENCE_NUM` = the SSM path of the current SAP sequence number -- `WORKSPACE` = Set to `dev` for local development, this will be set to `stage` and `prod` in those environments by Terraform. +```shell +ALMA_API_URL=# Base URL for making Alma API calls +ALMA_API_READ_WRITE_KEY=# API key for making Alma API calls +SAP_DROPBOX_CLOUDCONNECTOR_JSON=# JSON formatted connection information for accessing SAP dropbox +SAP_REPLY_TO_EMAIL=# reply-to email on emails to SAP recipient email lists +SAP_FINAL_RECIPIENT_EMAIL=# moira list to recieves final run emails +SAP_REVIEW_RECIPIENT_EMAIL=# moira list to recieve review run emails +SES_SEND_FROM_EMAIL=# email address that SES sends from +SAP_SEQUENCE_NUM=# the SSM path of the current SAP sequence number +WORKSPACE=# Set to `dev` for local development, this will be set to `stage` and `prod` in those environments by Terraform. +``` ## Optional ENV -- `ALMA_API_TIMEOUT`= Request timeout for Alma API calls. Defaults to 30 seconds if not set. -- `LOG_LEVEL` = Set to a valid Python logging level (e.g. DEBUG, case-insensitive) if desired. Can also be passed as an option directly to the ccslips command. Defaults to INFO if not set or passed to the command. -- `SENTRY_DSN` = If set to a valid Sentry DSN, enables Sentry exception monitoring. This is not needed for local development. +```shell +ALMA_API_TIMEOUT=# Request timeout for Alma API calls. Defaults to 30 seconds if not set. +LOG_LEVEL=# Set to a valid Python logging level (e.g. DEBUG, case-insensitive) if desired. Can also be passed as an option directly to the ccslips command. Defaults to INFO if not set or passed to the command. +SENTRY_DSN=# If set to a valid Sentry DSN, enables Sentry exception monitoring. This is not needed for local development. +``` ## Local Testing To test end-to-end with a connection to the test SAP Dropbox, the app must be run as an ECS task in the `stage` environment. diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..d646080 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,70 @@ +# We do our best to sync this template with the latest version in our internal documentation. +# For MIT developers, we strongly recommend copying the pyproject.toml template from: +# https://mitlibraries.atlassian.net/wiki/spaces/IN/pages/3432415247/Python+Project+Linters#Template-for-pyproject.toml + +[tool.black] +line-length = 90 + +[tool.mypy] +disallow_untyped_calls = true +disallow_untyped_defs = true +exclude = ["tests/"] + +[tool.pytest.ini_options] +log_level = "INFO" + +[tool.ruff] +target-version = "py312" + +# set max line length +line-length = 90 + +# enumerate all fixed violations +show-fixes = true + +[tool.ruff.lint] +select = ["ALL", "PT"] +ignore = [ + # default + "ANN101", + "ANN102", + "COM812", + "D107", + "N812", + "PTH", + + # project-specific + "C90", + "D100", + "D101", + "D102", + "D103", + "D104", + "PLR0912", + "PLR0913", + "PLR0915", + "S320", + "S321", +] + +# allow autofix behavior for specified rules +fixable = ["E", "F", "I", "Q"] + +[tool.ruff.lint.flake8-annotations] +mypy-init-return = true + +[tool.ruff.lint.flake8-pytest-style] +fixture-parentheses = false + +[tool.ruff.lint.per-file-ignores] +"tests/**/*" = [ + "ANN", + "ARG001", + "S101", +] + +[tool.ruff.lint.pycodestyle] +max-doc-length = 90 + +[tool.ruff.lint.pydocstyle] +convention = "google" \ No newline at end of file diff --git a/sapinvoices/alma.py b/sapinvoices/alma.py index 5495df7..05a6678 100644 --- a/sapinvoices/alma.py +++ b/sapinvoices/alma.py @@ -1,8 +1,8 @@ import json import logging import time +from collections.abc import Generator from datetime import datetime -from typing import Generator, Optional from urllib.parse import urljoin import requests @@ -103,7 +103,7 @@ def get_paged( self, endpoint: str, record_type: str, - params: Optional[dict] = None, + params: dict | None = None, limit: int = 100, _offset: int = 0, _records_retrieved: int = 0, @@ -140,8 +140,9 @@ def get_paged( total_record_count = response.json()["total_record_count"] records = response.json().get(record_type, []) records_retrieved = _records_retrieved + len(records) - for record in records: - yield record + + yield from records + if records_retrieved < total_record_count: yield from self.get_paged( endpoint, diff --git a/sapinvoices/cli.py b/sapinvoices/cli.py index c24ef42..d002d37 100644 --- a/sapinvoices/cli.py +++ b/sapinvoices/cli.py @@ -1,7 +1,6 @@ import datetime import json import logging -from typing import Optional import click @@ -17,7 +16,7 @@ @click.pass_context def main(ctx: click.Context) -> None: ctx.ensure_object(dict) - ctx.obj["today"] = datetime.datetime.today() + ctx.obj["today"] = datetime.datetime.now(tz=datetime.UTC) @main.command() @@ -28,7 +27,7 @@ def main(ctx: click.Context) -> None: help="Case-insensitive Python log level to use, e.g. debug or warning. Defaults to " "INFO if not provided or found in ENV.", ) -def create_sandbox_data(log_level: Optional[str]) -> None: +def create_sandbox_data(log_level: str | None) -> None: """Create sample data in the Alma sandbox instance. This command will not run in the production environment, and should never be run with @@ -41,10 +40,8 @@ def create_sandbox_data(log_level: Optional[str]) -> None: logger.info(configure_logger(root_logger, log_level)) logger.info(configure_sentry()) if config_values["WORKSPACE"] == "prod": - logger.info( - "This command may not be run in the production environment, aborting" - ) - raise click.Abort() + logger.info("This command may not be run in the production environment, aborting") + raise click.Abort alma_client = AlmaClient() with open( "sample-data/sample-sap-invoice-data.json", encoding="utf-8" @@ -87,8 +84,11 @@ def create_sandbox_data(log_level: Optional[str]) -> None: "INFO if not provided or found in ENV.", ) @click.pass_context -def process_invoices( # noqa pylintR0914 Too many local variables - ctx: click.Context, final_run: bool, real_run: bool, log_level: Optional[str] +def process_invoices( + ctx: click.Context, + final_run: bool, # noqa: FBT001 + real_run: bool, # noqa: FBT001 + log_level: str | None, ) -> None: """Process invoices for payment via SAP. @@ -124,7 +124,7 @@ def process_invoices( # noqa pylintR0914 Too many local variables logger.info( "No invoices waiting to be sent in Alma, aborting SAP invoice process" ) - raise click.Abort() + raise click.Abort # Parse retrieved invoices and extract data needed for SAP problem_invoices, parsed_invoices = sap.parse_invoice_records( alma_client, invoice_records diff --git a/sapinvoices/config.py b/sapinvoices/config.py index e865945..4e72d58 100644 --- a/sapinvoices/config.py +++ b/sapinvoices/config.py @@ -18,9 +18,10 @@ def configure_logger(logger: logging.Logger, log_level_string: str) -> str: if log_level_string.upper() not in logging.getLevelNamesMapping(): - raise ValueError(f"'{log_level_string}' is not a valid Python logging level") + message = f"'{log_level_string}' is not a valid Python logging level" + raise ValueError(message) log_level = logging.getLevelName(log_level_string.upper()) - if log_level < 20: + if log_level < 20: # noqa: PLR2004 logging.basicConfig( format="%(asctime)s %(levelname)s %(name)s.%(funcName)s() line %(lineno)d: " "%(message)s" diff --git a/sapinvoices/email.py b/sapinvoices/email.py index d9acdf7..ad80e4a 100644 --- a/sapinvoices/email.py +++ b/sapinvoices/email.py @@ -1,6 +1,5 @@ from email.message import EmailMessage from email.policy import EmailPolicy, default -from typing import List, Optional import boto3 @@ -12,16 +11,16 @@ def __init__(self, policy: EmailPolicy = default) -> None: """Initialize Email instance.""" super().__init__(policy) - def populate( # noqa pylint R0913 too many arguments + def populate( self, from_address: str, to_addresses: str, subject: str, - attachments: Optional[List[dict]] = None, - body: Optional[str] = None, - bcc: Optional[str] = None, - cc: Optional[str] = None, # noqa pylint C0103 not snake_case - reply_to: Optional[str] = None, + attachments: list[dict] | None = None, + body: str | None = None, + bcc: str | None = None, + cc: str | None = None, + reply_to: str | None = None, ) -> None: """Populate Email message with addresses and subject. @@ -68,11 +67,10 @@ def send(self) -> dict: destinations.extend(self["Cc"].split(",")) if self["Bcc"]: destinations.extend(self["Bcc"].split(",")) - response = ses.send_raw_email( + return ses.send_raw_email( Source=self["From"], Destinations=destinations, RawMessage={ "Data": self.as_bytes(), }, ) - return response diff --git a/sapinvoices/sample_data.py b/sapinvoices/sample_data.py index 418476c..1dc109e 100644 --- a/sapinvoices/sample_data.py +++ b/sapinvoices/sample_data.py @@ -1,7 +1,7 @@ """Sample data loader.""" + import json import logging -from typing import List from requests.exceptions import HTTPError @@ -42,8 +42,8 @@ def create_vendor_if_needed(alma_client: AlmaClient, vendor_data: dict) -> str: response_vendor_code = alma_client.create_vendor(vendor_data)["code"] logger.info("Vendor '%s' created in Alma", response_vendor_code) else: - logger.error(err.response.text) - raise err + logger.exception(err.response.text) + raise return vendor_code @@ -64,7 +64,7 @@ def get_next_vendor_invoice_number(alma_client: AlmaClient, vendor_code: str) -> def create_invoices_with_lines( alma_client: AlmaClient, - invoices: List[dict], + invoices: list[dict], vendor_abbreviation: str, next_invoice_number: int, ) -> list[str]: @@ -91,12 +91,12 @@ def create_invoice(alma_client: AlmaClient, invoice_data: dict) -> str: logger.info("Invoice created with data: %s", json.dumps(response)) return response["id"] except HTTPError as err: - logger.error(err.response.text) - raise err + logger.exception(err.response.text) + raise def create_invoice_lines( - alma_client: AlmaClient, invoice_alma_id: str, invoice_lines: List[dict] + alma_client: AlmaClient, invoice_alma_id: str, invoice_lines: list[dict] ) -> int: """Create invoice lines for a given invoice in Alma.""" created_lines = 0 @@ -110,8 +110,8 @@ def create_invoice_lines( ) created_lines += 1 except HTTPError as err: - logger.error(err.response.text) - raise err + logger.exception(err.response.text) + raise return created_lines @@ -127,6 +127,6 @@ def process_invoices(alma_client: AlmaClient, invoice_alma_ids: list[str]) -> in ) processed += 1 except HTTPError as err: - logger.error(err.response.text) - raise err + logger.exception(err.response.text) + raise return processed diff --git a/sapinvoices/sap.py b/sapinvoices/sap.py index baf787d..128a2db 100644 --- a/sapinvoices/sap.py +++ b/sapinvoices/sap.py @@ -2,15 +2,15 @@ import base64 import collections +import datetime import json import logging -from datetime import datetime from io import StringIO from math import fsum -from typing import Any, List, Literal, Optional, Tuple +from typing import Any, Literal -import fabric -import flatdict # type: ignore +import fabric # type: ignore[import-untyped] +import flatdict # type: ignore[import-untyped] import requests.exceptions from paramiko import RSAKey @@ -37,7 +37,7 @@ class FundError(Exception): def __init__( self, fund_codes: list, - message: str = ("Fund could not be retrieved by " "code, may be overexpended"), + message: str = "Fund could not be retrieved by code, may be overexpended", ) -> None: """Initialize FundError instance.""" self.fund_codes = fund_codes @@ -53,7 +53,7 @@ class SapSequenceError(Exception): """Exception raised when SAP sequence number is less than three digits.""" -def retrieve_sorted_invoices(alma_client: AlmaClient) -> List: +def retrieve_sorted_invoices(alma_client: AlmaClient) -> list: """Retrieve sorted invoices from Alma. Retrieve invoices from Alma with status 'Waiting to be sent' and return them @@ -64,8 +64,8 @@ def retrieve_sorted_invoices(alma_client: AlmaClient) -> List: def parse_invoice_records( - alma_client: AlmaClient, invoice_records: List[dict] -) -> Tuple[List[dict[Any, Any]], List[dict[Any, Any]]]: + alma_client: AlmaClient, invoice_records: list[dict] +) -> tuple[list[dict[Any, Any]], list[dict[Any, Any]]]: """Parse a list of invoice records from Alma and return extracted SAP data.""" parsed_invoices = [] problem_invoices = [] @@ -126,7 +126,7 @@ def check_for_multibyte(invoice: dict) -> list: if isinstance(value, str): for char in value: if len(char.encode("utf-8")) > 1: - multibyte_characters.append( + multibyte_characters.append( # noqa: PERF401 {"field": nested_key, "character": char} ) return multibyte_characters @@ -140,8 +140,10 @@ def extract_invoice_data(invoice_record: dict) -> dict: """ vendor_code = invoice_record["vendor"]["value"] - invoice_data = { - "date": datetime.strptime(invoice_record["invoice_date"], "%Y-%m-%dZ"), + return { + "date": datetime.datetime.strptime( + invoice_record["invoice_date"], "%Y-%m-%dZ" + ).replace(tzinfo=datetime.UTC), "id": invoice_record["id"], "number": invoice_record["number"], "type": get_purchase_type(vendor_code), @@ -149,7 +151,6 @@ def extract_invoice_data(invoice_record: dict) -> dict: "total amount": invoice_record["total_amount"], "currency": invoice_record["currency"]["value"], } - return invoice_data def get_purchase_type(vendor_code: str) -> str: @@ -167,7 +168,7 @@ def populate_vendor_data(alma_client: AlmaClient, vendor_code: str) -> dict: """ vendor_record = alma_client.get_vendor_details(vendor_code) address = determine_vendor_payment_address(vendor_record) - vendor_data = { + return { "name": vendor_record["name"], "code": vendor_code, "address": { @@ -178,7 +179,6 @@ def populate_vendor_data(alma_client: AlmaClient, vendor_code: str) -> dict: "country": country_code_from_address(address), }, } - return vendor_data def determine_vendor_payment_address(vendor_record: dict) -> dict: @@ -191,7 +191,10 @@ def determine_vendor_payment_address(vendor_record: dict) -> dict: """ try: for address in vendor_record["contact_info"]["address"]: - if any("payment" in type.values() for type in address["address_type"]): + if any( + "payment" in address_type.values() + for address_type in address["address_type"] + ): return address return vendor_record["contact_info"]["address"][0] except (IndexError, KeyError) as exc: @@ -205,12 +208,11 @@ def address_lines_from_address(address: dict) -> list: address lines from the address. """ line_names = ["line1", "line2", "line3", "line4", "line5"] - lines = [ + return [ address.get(line_name) for line_name in line_names if address.get(line_name) is not None ] - return lines def country_code_from_address(address: dict) -> str: @@ -230,7 +232,7 @@ def country_code_from_address(address: dict) -> str: def populate_fund_data( alma_client: AlmaClient, invoice_record: dict, retrieved_funds: dict -) -> Tuple[dict, dict]: +) -> tuple[dict, dict]: """Populate a dict with fund data needed for SAP. Given an invoice record, a dict of already retrieved funds, and an authenticated @@ -276,11 +278,11 @@ def populate_fund_data( def split_invoices_by_field_value( - invoices: List[dict], + invoices: list[dict], field: str, first_value: str, - second_value: Optional[str] = None, -) -> Tuple[List[dict[Any, Any]], List[dict[Any, Any]]]: + second_value: str | None = None, +) -> tuple[list[dict[Any, Any]], list[dict[Any, Any]]]: """Split a list of parsed invoices into two based on an invoice field's value. Returns two lists, one of invoice dicts with the first value in the provided @@ -293,21 +295,19 @@ def split_invoices_by_field_value( for invoice in invoices: if invoice[field] == first_value: invoices_with_first_value.append(invoice) - elif second_value is not None and invoice[field] == second_value: + elif second_value is not None and invoice[field] == second_value: # noqa: SIM114 invoices_with_second_value.append(invoice) elif second_value is None: invoices_with_second_value.append(invoice) return invoices_with_first_value, invoices_with_second_value -def generate_report(today: datetime, invoices: List[dict]) -> str: +def generate_report(today: datetime.datetime, invoices: list[dict]) -> str: today_string = today.strftime("%m/%d/%Y") report = "" for invoice in invoices: report += f"\n\n{'':33}MIT LIBRARIES\n\n\n" - report += ( - f"Date: {today_string:<36}Vendor code : {invoice['vendor']['code']}\n" - ) + report += f"Date: {today_string:<36}Vendor code : {invoice['vendor']['code']}\n" report += f"{'Accounting ID :':>57}\n\n" report += f"Vendor: {invoice['vendor']['name']}\n" for line in invoice["vendor"]["address"]["lines"]: @@ -350,8 +350,8 @@ def generate_sap_report_email( summary: str, report: str, purchase_type: Literal["mono", "serial"], - date: datetime, - final: bool, + date: datetime.datetime, + final: bool, # noqa: FBT001 ) -> Email: sap_config = load_config_values() report_email = Email() @@ -383,7 +383,7 @@ def generate_sap_report_email( return report_email -def format_address_for_sap(address_lines: List) -> Tuple[str, str, str]: +def format_address_for_sap(address_lines: list) -> tuple[str, str, str]: """Assign payee address information to SAP data file fields.""" payee_name_line_2 = address_lines[0] @@ -403,7 +403,7 @@ def format_address_for_sap(address_lines: List) -> Tuple[str, str, str]: return payee_name_line_2, street_or_po_box_num, payee_name_line_3 -def generate_sap_data(today: datetime, invoices: List[dict]) -> str: +def generate_sap_data(today: datetime.datetime, invoices: list[dict]) -> str: """Format invoice data for SAP. Given a list of pre-processed invoices and a date, returns a string of invoice @@ -481,8 +481,7 @@ def generate_summary_warning(problem_invoices: list) -> str: if "fund_errors" in invoice: for fund_code in invoice["fund_errors"]: warning += ( - f"There was a problem retrieving data\n" - f"for fund: {fund_code}\n\n" + f"There was a problem retrieving data\nfor fund: {fund_code}\n\n" ) if "multibyte_errors" in invoice: for multibyte in invoice["multibyte_errors"]: @@ -501,7 +500,7 @@ def generate_summary_warning(problem_invoices: list) -> str: def generate_summary( problem_invoices: list, - invoices: List[dict], + invoices: list[dict], data_file_name: str, control_file_name: str, ) -> str: @@ -516,9 +515,7 @@ def generate_summary( for invoice in invoices: if invoice["payment method"] == "ACCOUNTINGDEPARTMENT": summary += f"{invoice['vendor']['name']: <39.39}" - summary += ( - f"{invoice['number'] + invoice['date'].strftime('%y%m%d'): <20.20}" - ) + summary += f"{invoice['number'] + invoice['date'].strftime('%y%m%d'): <20.20}" summary += f"{invoice['total amount']:.2f}\n" sum_of_invoices += float(invoice["total amount"]) invoice_count += 1 @@ -552,16 +549,16 @@ def generate_sap_control(sap_data_file: str, invoice_total: float) -> str: # 33-52 credit total # we don't send credits to SAP so this will always be 20 0's - sap_control_file += "0" * 20 + sap_control_file += "".zfill(20) # 53-72 debit total - convert invoice total to string # remove decimal to convert dollars to cents # and 0-pad to 20 characters - sap_control_file += f"{'{:.2f}'.format(invoice_total).replace('.', ''):0>20}" # noqa pylint C0209 too many arguments + sap_control_file += f"{invoice_total:.2f}".replace(".", "").zfill(20) # 73-92 control 3 summarizing the data file # we just repeat the invoice total here - sap_control_file += f"{'{:.2f}'.format(invoice_total).replace('.', ''):0>20}" # noqa pylint C0209 too many arguments + sap_control_file += f"{invoice_total:.2f}".replace(".", "").zfill(20) # 93-112 control 4 summarizing the data file # Accounts payable told us to use this string @@ -586,35 +583,35 @@ def generate_next_sap_sequence_number() -> str: sap_config = load_config_values() sap_sequence_parameter = ssm.get_parameter_value(sap_config["SAP_SEQUENCE_NUM"]) split_parameter = sap_sequence_parameter.split(",") - if len(split_parameter[0]) < 3: - raise SapSequenceError( - f"Invalid SAP sequence: '{split_parameter[0]}', number must be three or more" - " digits." + if len(split_parameter[0]) < 3: # noqa: PLR2004 + message = ( + f"Invalid SAP sequence: '{split_parameter[0]}', " + "number must be three or more digits." ) + raise SapSequenceError(message) return str(int(split_parameter[0]) + 1) def update_sap_sequence( - sap_sequence_number: str, date: datetime, sequence_type: str + sap_sequence_number: str, date: datetime.datetime, sequence_type: str ) -> dict: """Update SAP sequence and post it to SSM Parameter Store.""" ssm = SSM() sap_config = load_config_values() date_string = date.strftime("%Y%m%d").ljust(14, "0") new_sap_sequence = f"{sap_sequence_number},{date_string},{sequence_type}" - response = ssm.update_parameter_value( + return ssm.update_parameter_value( sap_config["SAP_SEQUENCE_NUM"], new_sap_sequence, "StringList" ) - return response -def calculate_invoices_total_amount(invoices: List[dict]) -> float: - total_amount = 0.0 - total_amount = fsum([invoice["total amount"] for invoice in invoices]) - return total_amount +def calculate_invoices_total_amount(invoices: list[dict]) -> float: + return fsum([invoice["total amount"] for invoice in invoices]) -def generate_sap_file_names(sequence_number: str, date: datetime) -> Tuple[str, str]: +def generate_sap_file_names( + sequence_number: str, date: datetime.datetime +) -> tuple[str, str]: date_string = date.strftime("%Y%m%d000000") data_file_name = f"dlibsapg.{sequence_number}.{date_string}" control_file_name = f"clibsapg.{sequence_number}.{date_string}" @@ -622,7 +619,7 @@ def generate_sap_file_names(sequence_number: str, date: datetime) -> Tuple[str, def mark_invoices_paid( - alma_client: AlmaClient, invoices: List[dict], date: datetime + alma_client: AlmaClient, invoices: list[dict], date: datetime.datetime ) -> int: paid_invoice_count = 0 for invoice in invoices: @@ -638,7 +635,7 @@ def mark_invoices_paid( paid_invoice_count += 1 except (requests.exceptions.RequestException, ValueError): - logger.error( + logger.exception( "Something went wrong marking invoice '%s' paid in Alma.", invoice_id, ) @@ -646,24 +643,21 @@ def mark_invoices_paid( return paid_invoice_count -def run( # noqa pylint R0913 Too many arguments - # noqa pylintR0914 Too many local variables +def run( alma_client: AlmaClient, problem_invoices: list, - invoices: List[dict], + invoices: list[dict], invoices_type: Literal["monograph", "serial"], sap_sequence_number: str, # Just the sequence number, e.g. "0003" - date: datetime, - final_run: bool, - real_run: bool, + date: datetime.datetime, + final_run: bool, # noqa: FBT001 + real_run: bool, # noqa: FBT001 ) -> dict: sap_config = load_config_values() dropbox_connection = json.loads(sap_config["SAP_DROPBOX_CLOUDCONNECTOR_JSON"]) logger.info("Starting file generation process for run %s", invoices_type) - data_file_name, control_file_name = generate_sap_file_names( - sap_sequence_number, date - ) + data_file_name, control_file_name = generate_sap_file_names(sap_sequence_number, date) logger.info( "Generated next SAP file names: %s, %s", data_file_name, control_file_name ) @@ -708,9 +702,7 @@ def run( # noqa pylint R0913 Too many arguments connect_kwargs={ "pkey": pkey, "look_for_keys": False, - "disabled_algorithms": { - "pubkeys": ["rsa-sha2-256", "rsa-sha2-512"] - }, + "disabled_algorithms": {"pubkeys": ["rsa-sha2-256", "rsa-sha2-512"]}, }, ) as sftp_connection: sftp_connection.put( diff --git a/sapinvoices/ssm.py b/sapinvoices/ssm.py index 1050c7a..b4bcb6c 100644 --- a/sapinvoices/ssm.py +++ b/sapinvoices/ssm.py @@ -29,16 +29,14 @@ def get_parameter_history(self, parameter_key: str) -> list: response = self.client.get_parameter_history( Name=parameter_key, WithDecryption=True ) - parameter_history = response["Parameters"] - return parameter_history + return response["Parameters"] def get_parameter_value(self, parameter_key: str) -> str: """Get parameter value based on the specified key.""" parameter_object = self.client.get_parameter( Name=parameter_key, WithDecryption=True ) - parameter_value = parameter_object["Parameter"]["Value"] - return parameter_value + return parameter_object["Parameter"]["Value"] def update_parameter_value( self, parameter_key: str, new_value: str, parameter_type: str diff --git a/tests/conftest.py b/tests/conftest.py index 0885f94..5d6ff3a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,13 +1,14 @@ +# ruff: noqa: PT004, UP015, D205, D209, D403, D415, RET504 + +import datetime import json -import os -from datetime import datetime import boto3 import pytest import requests_mock from click.testing import CliRunner -from fabric.testing.fixtures import sftp as mocked_sftp # noqa -from moto import mock_ses, mock_ssm +from fabric.testing.fixtures import sftp as mocked_sftp # noqa: F401, used as fixture +from moto import mock_aws from requests import HTTPError, Response from sapinvoices.alma import AlmaClient @@ -15,51 +16,48 @@ @pytest.fixture(autouse=True) -def aws_credentials(): - os.environ["AWS_ACCESS_KEY_ID"] = "testing" - os.environ["AWS_SECRET_ACCESS_KEY"] = "testing" - os.environ["AWS_SECURITY_TOKEN"] = "testing" - os.environ["AWS_SESSION_TOKEN"] = "testing" +def aws_credentials(monkeypatch): + monkeypatch.setenv("AWS_ACCESS_KEY_ID", "testing") + monkeypatch.setenv("AWS_SECRET_ACCESS_KEY", "testing") + monkeypatch.setenv("AWS_SECURITY_TOKEN", "testing") + monkeypatch.setenv("AWS_SESSION_TOKEN", "testing") @pytest.fixture(autouse=True) -def test_env(): - os.environ = { - "ALMA_API_URL": "https://example.com", - "ALMA_API_READ_WRITE_KEY": "just-for-testing", - "ALMA_API_TIMEOUT": "10", - "LOG_LEVEL": "INFO", - "SAP_DROPBOX_CLOUDCONNECTOR_JSON": json.dumps({"test": "test"}), - "SAP_REPLY_TO_EMAIL": "replyto@example.com", - "SAP_FINAL_RECIPIENT_EMAIL": "final@example.com", - "SAP_REVIEW_RECIPIENT_EMAIL": "review@example.com", - "SENTRY_DSN": None, - "SES_SEND_FROM_EMAIL": "from@example.com", - "SAP_SEQUENCE_NUM": "/test/example/sap_sequence", - "WORKSPACE": "test", - } - yield - - -@pytest.fixture() +def test_env(monkeypatch): + monkeypatch.setenv("ALMA_API_URL", "https://example.com") + monkeypatch.setenv("ALMA_API_READ_WRITE_KEY", "just-for-testing") + monkeypatch.setenv("ALMA_API_TIMEOUT", "10") + monkeypatch.setenv("LOG_LEVEL", "INFO") + monkeypatch.setenv("SAP_DROPBOX_CLOUDCONNECTOR_JSON", json.dumps({"test": "test"})) + monkeypatch.setenv("SAP_REPLY_TO_EMAIL", "replyto@example.com") + monkeypatch.setenv("SAP_FINAL_RECIPIENT_EMAIL", "final@example.com") + monkeypatch.setenv("SAP_REVIEW_RECIPIENT_EMAIL", "review@example.com") + monkeypatch.setenv("SENTRY_DSN", "None") + monkeypatch.setenv("SES_SEND_FROM_EMAIL", "from@example.com") + monkeypatch.setenv("SAP_SEQUENCE_NUM", "/test/example/sap_sequence") + monkeypatch.setenv("WORKSPACE", "test") + + +@pytest.fixture def runner(): return CliRunner() # API fixtures -@pytest.fixture() +@pytest.fixture def alma_client(): return AlmaClient() -@pytest.fixture() +@pytest.fixture def ssm_client() -> SSM: return SSM() @pytest.fixture(autouse=True) def mocked_ses(): - with mock_ses(): + with mock_aws(): ses = boto3.client("ses", region_name="us-east-1") ses.verify_email_identity(EmailAddress="from@example.com") yield ses @@ -75,7 +73,7 @@ def test_sftp_private_key_fixture(): @pytest.fixture(autouse=True) def mocked_ssm(): - with mock_ssm(): + with mock_aws(): ssm = boto3.client("ssm", region_name="us-east-1") ssm.put_parameter( @@ -91,20 +89,21 @@ def mocked_ssm(): yield ssm -@pytest.fixture() +@pytest.fixture def mocked_ssm_bad_sequence_number(): - with mock_ssm(): + with mock_aws(): ssm = boto3.client("ssm", region_name="us-east-1") ssm.put_parameter( Name="/test/example/sap_sequence", Value="1,20210722000000,ser", Type="StringList", + Overwrite=True, ) yield ssm -@pytest.fixture() +@pytest.fixture def mocked_alma_no_invoices(): with requests_mock.Mocker() as mocker: mocker.get( @@ -115,14 +114,12 @@ def mocked_alma_no_invoices(): yield mocker -@pytest.fixture() +@pytest.fixture def mocked_alma_with_errors(): with requests_mock.Mocker() as mocker: response = Response() - response._content = b"Error message" # noqa W0212 Access to a protected member - mocker.post( - "https://example.com/acq/invoices", exc=HTTPError(response=response) - ) + response._content = b"Error message" # noqa: SLF001 + mocker.post("https://example.com/acq/invoices", exc=HTTPError(response=response)) yield mocker @@ -156,15 +153,11 @@ def mocked_alma(): json={"payment": {"payment_status": {"desc": "string", "value": "PAID"}}}, ) - with open( - "tests/fixtures/vendor_aaa.json", encoding="utf-8" - ) as vendor_aaa_file: + with open("tests/fixtures/vendor_aaa.json", encoding="utf-8") as vendor_aaa_file: mocker.get( "https://example.com/acq/vendors/AAA", json=json.load(vendor_aaa_file) ) - with open( - "tests/fixtures/vendor_vend-s.json", encoding="utf-8" - ) as vendor_s_file: + with open("tests/fixtures/vendor_vend-s.json", encoding="utf-8") as vendor_s_file: mocker.get( "https://example.com/acq/vendors/VEND-S", json=json.load(vendor_s_file) ) @@ -213,12 +206,14 @@ def mocked_alma(): yield mocker -@pytest.fixture() +@pytest.fixture def mocked_alma_sample_data(): with requests_mock.Mocker() as mocker: # Get vendor response1 = Response() - response1._content = b'{"errorList": {"error": [{"errorCode":"402880"}]}}' # noqa W0212 Access to a protected member + response1._content = ( # noqa: SLF001 + b'{"errorList": {"error": [{"errorCode":"402880"}]}}' + ) mocker.get( "https://example.com/acq/vendors/TestSAPVendor1", exc=HTTPError(response=response1), @@ -228,7 +223,9 @@ def mocked_alma_sample_data(): json={"code": "TestSAPVendor2-S"}, ) response2 = Response() - response2._content = b'{"errorList": {"error": [{"errorCode":"a-different-error"}]}}' # noqa W0212 Access to a protected member + response2._content = ( # noqa: SLF001 + b'{"errorList": {"error": [{"errorCode":"a-different-error"}]}}' + ) mocker.get( "https://example.com/acq/vendors/not-a-vendor", exc=HTTPError(response=response2), @@ -276,7 +273,7 @@ def mocked_alma_sample_data(): json={"id": "alma_id_0002"}, ) response3 = Response() - response3._content = b"Error message" # noqa W0212 Access to a protected member + response3._content = b"Error message" # noqa: SLF001 mocker.post( "https://example.com/acq/invoices/error_id/lines", exc=HTTPError(response=response3), @@ -300,7 +297,7 @@ def mocked_alma_sample_data(): json={"id": "alma_id_0004"}, ) response4 = Response() - response4._content = b"Error message" # noqa W0212 Access to a protected member + response4._content = b"Error message" # noqa: SLF001 mocker.post( "https://example.com/acq/invoices/error_id?op=process_invoice", exc=HTTPError(response=response4), @@ -308,14 +305,14 @@ def mocked_alma_sample_data(): yield mocker -@pytest.fixture() +@pytest.fixture def invoices_for_sap_with_different_payment_method(): """a list of invoices which includes an invoice with a payment method other than ACCOUNTINGDEPARTMENT which should get filtered out when generating summary reports""" invoices = [ { - "date": datetime(2021, 5, 12), + "date": datetime.datetime(2021, 5, 12, tzinfo=datetime.UTC), "id": "0000055555000000", "number": "456789", "type": "monograph", @@ -345,7 +342,7 @@ def invoices_for_sap_with_different_payment_method(): }, }, { - "date": datetime(2021, 5, 11), + "date": datetime.datetime(2021, 5, 11, tzinfo=datetime.UTC), "id": "0000055555000002", "number": "444555", "type": "monograph", @@ -389,7 +386,7 @@ def invoices_for_sap_with_different_payment_method(): }, }, { - "date": datetime(2021, 5, 12), + "date": datetime.datetime(2021, 5, 12, tzinfo=datetime.UTC), "id": "0000055555000003", "number": "12345", "type": "monograph", @@ -421,11 +418,11 @@ def invoices_for_sap_with_different_payment_method(): return invoices -@pytest.fixture() +@pytest.fixture def invoices_for_sap(): invoices = [ { - "date": datetime(2021, 5, 12), + "date": datetime.datetime(2021, 5, 12, tzinfo=datetime.UTC), "id": "0000055555000000", "number": "456789", "type": "monograph", @@ -455,7 +452,7 @@ def invoices_for_sap(): }, }, { - "date": datetime(2021, 5, 11), + "date": datetime.datetime(2021, 5, 11, tzinfo=datetime.UTC), "id": "0000055555000000", "number": "444555", "type": "monograph", @@ -499,7 +496,7 @@ def invoices_for_sap(): }, }, { - "date": datetime(2021, 5, 12), + "date": datetime.datetime(2021, 5, 12, tzinfo=datetime.UTC), "id": "0000055555000000", "number": "456789", "type": "monograph", @@ -531,16 +528,19 @@ def invoices_for_sap(): return invoices -@pytest.fixture() +@pytest.fixture def problem_invoices(): problem_invoice_list = [ { "fund_errors": ["over-encumbered", "also-over-encumbered"], "multibyte_errors": [ - {"field": "vendor:address:lines:0", "character": "‑"}, + { + "field": "vendor:address:lines:0", + "character": "‑", # noqa: RUF001 + }, {"field": "vendor:city", "character": "ƒ"}, ], - "date": datetime(2021, 5, 12), + "date": datetime.datetime(2021, 5, 12, tzinfo=datetime.UTC), "id": "9991", "number": "456789", "type": "monograph", @@ -552,7 +552,7 @@ def problem_invoices(): "code": "FOOBAR-M", "address": { "lines": [ - "12‑3 salad Street", + "12‑3 salad Street", # noqa: RUF001 "Second Floor", ], "city": "San ƒrancisco", @@ -564,8 +564,13 @@ def problem_invoices(): }, { "fund_errors": ["also-over-encumbered"], - "multibyte_errors": [{"field": "vendor:address:lines:0", "character": "‑"}], - "date": datetime(2021, 5, 11), + "multibyte_errors": [ + { + "field": "vendor:address:lines:0", + "character": "‑", # noqa: RUF001 + } + ], + "date": datetime.datetime(2021, 5, 11, tzinfo=datetime.UTC), "id": "9992", "number": "444555", "type": "monograph", @@ -581,14 +586,14 @@ def problem_invoices(): ], "city": "Atlanta", "state or province": "GA", - "postal code": "30384‑7991", + "postal code": "30384‑7991", # noqa: RUF001 "country": "US", }, }, }, { "vendor_address_error": "YBP-no-address", - "date": datetime(2021, 5, 11), + "date": datetime.datetime(2021, 5, 11, tzinfo=datetime.UTC), "id": "9993", "number": "444666", "type": "monograph", @@ -600,7 +605,7 @@ def problem_invoices(): return problem_invoice_list -@pytest.fixture() +@pytest.fixture def sap_data_file(): """a string representing a datafile of invoices to send to SAP diff --git a/tests/test_alma.py b/tests/test_alma.py index 1868437..f76bd4d 100644 --- a/tests/test_alma.py +++ b/tests/test_alma.py @@ -1,3 +1,5 @@ +# ruff: noqa: PLR2004 + import datetime import urllib.parse @@ -98,7 +100,7 @@ def test_get_vendor_invoices(alma_client): def test_mark_invoice_paid(alma_client): test_url = "https://example.com/acq/invoices/558809630001021?op=paid" invoice_id = "558809630001021" - payment_date = datetime.datetime(2021, 7, 22) + payment_date = datetime.datetime(2021, 7, 22, tzinfo=datetime.UTC) payment_amount = "120" payment_currency = "USD" test_payload = { @@ -131,7 +133,7 @@ def test_mark_invoice_paid(alma_client): def test_mark_invoice_paid_request_read_timeout(alma_client): test_url = "https://example.com/acq/invoices/558809630001021?op=paid" invoice_id = "558809630001021" - payment_date = datetime.datetime(2021, 7, 22) + payment_date = datetime.datetime(2021, 7, 22, tzinfo=datetime.UTC) payment_amount = "120" payment_currency = "USD" with requests_mock.Mocker(case_sensitive=True) as mocker: @@ -151,7 +153,7 @@ def test_mark_invoice_paid_request_read_timeout(alma_client): def test_mark_invoice_paid_request_status_error(alma_client): test_url = "https://example.com/acq/invoices/558809630001021?op=paid" invoice_id = "558809630001021" - payment_date = datetime.datetime(2021, 7, 22) + payment_date = datetime.datetime(2021, 7, 22, tzinfo=datetime.UTC) payment_amount = "120" payment_currency = "USD" with requests_mock.Mocker(case_sensitive=True) as mocker: @@ -168,13 +170,13 @@ def test_mark_invoice_paid_request_status_error(alma_client): def test_mark_invoice_paid_request_value_error(alma_client): test_url = "https://example.com/acq/invoices/558809630001021?op=paid" invoice_id = "558809630001021" - payment_date = datetime.datetime(2021, 7, 22) + payment_date = datetime.datetime(2021, 7, 22, tzinfo=datetime.UTC) payment_amount = "120" payment_currency = "USD" mocked_response = {"payment": {"payment_status": {"value": "FOO"}}} with requests_mock.Mocker(case_sensitive=True) as mocker: mocker.post(test_url, json=mocked_response) - with pytest.raises(ValueError): + with pytest.raises(ValueError): # noqa: PT011 alma_client.mark_invoice_paid( invoice_id, payment_date=payment_date, diff --git a/tests/test_cli.py b/tests/test_cli.py index 5719cc5..0be05f4 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -28,18 +28,14 @@ def test_sap_invoices_review_run(caplog, runner): result = runner.invoke(main, ["process-invoices"]) assert "Logger 'root' configured with level=INFO" in caplog.text - assert ( - "alma-sapinvoices config settings loaded for environment: test" in caplog.text - ) + assert "alma-sapinvoices config settings loaded for environment: test" in caplog.text assert "Starting SAP invoices process with options" in caplog.text assert "Final run: False" in caplog.text assert "Real run: False" in caplog.text assert result.exit_code == 0 -def test_sap_invoices_review_run_no_invoices( - caplog, runner, mocked_alma_no_invoices # noqa pylint W0613 Unused argument -): +def test_sap_invoices_review_run_no_invoices(caplog, runner, mocked_alma_no_invoices): result = runner.invoke(main, ["process-invoices"]) assert result.exit_code == 1 assert "Real run: False" in caplog.text @@ -52,9 +48,7 @@ def test_sap_invoices_review_run_real_run(caplog, runner): result = runner.invoke(main, ["process-invoices", "--real-run"]) assert result.exit_code == 0 assert "Logger 'root' configured with level=INFO" in caplog.text - assert ( - "alma-sapinvoices config settings loaded for environment: test" in caplog.text - ) + assert "alma-sapinvoices config settings loaded for environment: test" in caplog.text assert "Starting SAP invoices process with options" in caplog.text assert "Final run: False" in caplog.text assert "Real run: True" in caplog.text @@ -64,9 +58,7 @@ def test_sap_invoices_final_run(caplog, runner): result = runner.invoke(main, ["process-invoices", "--final-run"]) assert result.exit_code == 0 assert "Logger 'root' configured with level=INFO" in caplog.text - assert ( - "alma-sapinvoices config settings loaded for environment: test" in caplog.text - ) + assert "alma-sapinvoices config settings loaded for environment: test" in caplog.text assert "Starting SAP invoices process with options" in caplog.text assert "Final run: True" in caplog.text assert "Real run: False" in caplog.text @@ -76,7 +68,7 @@ def test_sap_invoices_final_run_real_run( caplog, monkeypatch, runner, - mocked_sftp, # noqa pylint W0613 Unused argument + mocked_sftp, test_sftp_private_key, ): monkeypatch.setenv( @@ -93,9 +85,7 @@ def test_sap_invoices_final_run_real_run( result = runner.invoke(main, ["process-invoices", "--final-run", "--real-run"]) assert result.exit_code == 0 assert "Logger 'root' configured with level=INFO" in caplog.text - assert ( - "alma-sapinvoices config settings loaded for environment: test" in caplog.text - ) + assert "alma-sapinvoices config settings loaded for environment: test" in caplog.text assert "Starting SAP invoices process with options" in caplog.text assert "Final run: True" in caplog.text assert "Real run: True" in caplog.text diff --git a/tests/test_config.py b/tests/test_config.py index 41b0e30..b2a3180 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -1,3 +1,5 @@ +# ruff: noqa: PLR2004 + import logging import pytest @@ -7,7 +9,7 @@ def test_configure_logger_with_invalid_level_raises_error(): logger = logging.getLogger(__name__) - with pytest.raises(ValueError) as error: + with pytest.raises(ValueError) as error: # noqa: PT011 configure_logger(logger, log_level_string="oops") assert "'oops' is not a valid Python logging level" in str(error) @@ -76,6 +78,6 @@ def test_load_config_values_from_defaults(monkeypatch): def test_load_config_values_missing_config_raises_error(monkeypatch): + monkeypatch.delenv("ALMA_API_URL", raising=False) with pytest.raises(KeyError): - monkeypatch.delenv("ALMA_API_URL", raising=False) load_config_values() diff --git a/tests/test_email.py b/tests/test_email.py index e929512..bd3d4ac 100644 --- a/tests/test_email.py +++ b/tests/test_email.py @@ -1,3 +1,5 @@ +# ruff: noqa: PLR2004 + from email.message import EmailMessage from sapinvoices.email import Email diff --git a/tests/test_sample_data.py b/tests/test_sample_data.py index 1afe2ec..e112324 100644 --- a/tests/test_sample_data.py +++ b/tests/test_sample_data.py @@ -1,3 +1,5 @@ +# ruff: noqa: PLR2004 + import json import pytest @@ -28,8 +30,7 @@ def test_create_vendor_if_needed_vendor_exists(caplog, alma_client): result = sd.create_vendor_if_needed(alma_client, {"code": "TestSAPVendor2-S"}) assert result == "TestSAPVendor2-S" assert ( - "Vendor 'TestSAPVendor2-S' already exists in Alma, not creating it" - in caplog.text + "Vendor 'TestSAPVendor2-S' already exists in Alma, not creating it" in caplog.text ) diff --git a/tests/test_sap.py b/tests/test_sap.py index 3c49efd..30ed5a6 100644 --- a/tests/test_sap.py +++ b/tests/test_sap.py @@ -1,6 +1,8 @@ +# ruff: noqa: PLR2004, FBT003 + import collections +import datetime import json -from datetime import datetime from unittest.mock import MagicMock, call import pytest @@ -36,7 +38,7 @@ def test_parse_invoice_records(alma_client): assert problem_invoices[0]["fund_errors"][0] == "over-encumbered" assert problem_invoices[1]["fund_errors"][0] == "over-encumbered" assert problem_invoices[1]["multibyte_errors"][0] == { - "character": "‑", + "character": "‑", # noqa: RUF001 non-breaking hyphen, not hyphen-minus "field": "vendor:address:lines:0", } @@ -47,9 +49,7 @@ def test_parse_invoice_with_no_address_vendor(alma_client): with open( "tests/fixtures/invoice_with_no_vendor_address.json", encoding="utf-8" ) as invoice_no_vendor_address_file: - invoices_with_no_vendor_address.append( - json.load(invoice_no_vendor_address_file) - ) + invoices_with_no_vendor_address.append(json.load(invoice_no_vendor_address_file)) problem_invoices, parsed_invoices = sap.parse_invoice_records( alma_client, invoices_with_no_vendor_address ) @@ -62,15 +62,15 @@ def test_contains_multibyte(): invoice_with_multibyte = { "id": { "level 2": [ - "this is a multibyte character ‑", - "this is also ‑ a multibyte character", + "this is a multibyte character ‑", # noqa: RUF001 + "this is also ‑ a multibyte character", # noqa: RUF001 "this is not a multibyte character -", ] } } has_multibyte = sap.check_for_multibyte(invoice_with_multibyte) assert has_multibyte[0]["field"] == "id:level 2:0" - assert has_multibyte[0]["character"] == "‑" + assert has_multibyte[0]["character"] == "‑" # noqa: RUF001 assert has_multibyte[1]["field"] == "id:level 2:1" @@ -89,7 +89,7 @@ def test_extract_invoice_data_all_present(): invoice_record = json.load(invoice_waiting_to_be_sent_file) invoice_data = sap.extract_invoice_data(invoice_record) assert invoice_data == { - "date": datetime(2021, 9, 27), + "date": datetime.datetime(2021, 9, 27, tzinfo=datetime.UTC), "id": "00000055555000000", "number": "123456", "type": "monograph", @@ -247,19 +247,19 @@ def test_address_lines_from_address_none_present(): def test_country_code_from_address_code_present(): address = {"country": {"value": "USA"}} code = sap.country_code_from_address(address) - assert "US" == code + assert code == "US" def test_country_code_from_address_code_not_present(): address = {"country": {"value": "Not a Country"}} code = sap.country_code_from_address(address) - assert "US" == code + assert code == "US" def test_country_code_from_address_country_not_present(): address = {} code = sap.country_code_from_address(address) - assert "US" == code + assert code == "US" def test_populate_fund_data_success(alma_client): @@ -300,13 +300,13 @@ def test_populate_fund_data_fund_error(alma_client): retrieved_funds = {} with pytest.raises(sap.FundError) as err: sap.populate_fund_data(alma_client, invoice_record, retrieved_funds) - assert err.value.fund_codes == ["also-over-encumbered", "over-encumbered"] + assert err.value.fund_codes == ["also-over-encumbered", "over-encumbered"] def test_generate_report_success(): invoices = [ { - "date": datetime(2021, 9, 27), + "date": datetime.datetime(2021, 9, 27, tzinfo=datetime.UTC), "id": "00000055555000000", "number": "123456", "type": "monograph", @@ -348,7 +348,7 @@ def test_generate_report_success(): }, } ] - today = datetime(2021, 10, 1) + today = datetime.datetime(2021, 10, 1, tzinfo=datetime.UTC) report = sap.generate_report(today, invoices) assert ( report @@ -391,7 +391,11 @@ def test_generate_report_success(): def test_generate_sap_report_email_final_run(): email = sap.generate_sap_report_email( - "Summary contents", "Report contents", "mono", datetime(2021, 10, 1), True + "Summary contents", + "Report contents", + "mono", + datetime.datetime(2021, 10, 1, tzinfo=datetime.UTC), + True, ) assert email["From"] == "from@example.com" assert email["To"] == "final@example.com" @@ -406,7 +410,11 @@ def test_generate_sap_report_email_final_run(): def test_generate_sap_report_email_review_run(): email = sap.generate_sap_report_email( - "Summary contents", "Report contents", "serial", datetime(2021, 10, 1), False + "Summary contents", + "Report contents", + "serial", + datetime.datetime(2021, 10, 1, tzinfo=datetime.UTC), + False, ) assert email["From"] == "from@example.com" assert email["To"] == "review@example.com" @@ -480,13 +488,13 @@ def test_format_address_po_box_2_lines(): def test_generate_sap_data_success(invoices_for_sap, sap_data_file): - today = datetime(2021, 5, 18) + today = datetime.datetime(2021, 5, 18, tzinfo=datetime.UTC) report = sap.generate_sap_data(today, invoices_for_sap) assert report == sap_data_file def test_calculate_invoices_total_amount(): - invoices = [dict(zip(["total amount"], [0.1])) for x in range(100)] + invoices = [dict(zip(["total amount"], [0.1], strict=True)) for x in range(100)] total_amount = sap.calculate_invoices_total_amount(invoices) assert total_amount == 10 @@ -520,7 +528,7 @@ def test_generate_summary_warning(problem_invoices): Please fix the above before starting a final-run -""" +""" # noqa: RUF001 ) @@ -595,7 +603,9 @@ def test_update_sap_sequence(ssm_client): ssm_client.get_parameter_value("/test/example/sap_sequence") == "1001,20210722000000,ser" ) - response = sap.update_sap_sequence("1002", datetime(2021, 7, 23), "mono") + response = sap.update_sap_sequence( + "1002", datetime.datetime(2021, 7, 23, tzinfo=datetime.UTC), "mono" + ) assert response["ResponseMetadata"]["HTTPStatusCode"] == 200 assert ( ssm_client.get_parameter_value("/test/example/sap_sequence") @@ -605,14 +615,14 @@ def test_update_sap_sequence(ssm_client): def test_generate_sap_file_names(): data_file_name, control_file_name = sap.generate_sap_file_names( - "1002", datetime(2021, 12, 17) + "1002", datetime.datetime(2021, 12, 17, tzinfo=datetime.UTC) ) assert data_file_name == "dlibsapg.1002.20211217000000" assert control_file_name == "clibsapg.1002.20211217000000" def test_mark_invoices_paid_all_successful(alma_client): - date = datetime(2022, 1, 7) + date = datetime.datetime(2022, 1, 7, tzinfo=datetime.UTC) invoices = [ {"id": "1", "total amount": "100", "currency": "USD"}, {"id": "2", "total amount": "200", "currency": "GBH"}, @@ -625,14 +635,14 @@ def test_mark_invoices_paid_all_successful(alma_client): call("3", date, "300", "GBH"), ] paid_invoice_count = sap.mark_invoices_paid( - alma_client, invoices, datetime(2022, 1, 7) + alma_client, invoices, datetime.datetime(2022, 1, 7, tzinfo=datetime.UTC) ) assert alma_client.mark_invoice_paid.call_args_list == expected_calls assert paid_invoice_count == 3 def test_mark_invoices_paid_error(alma_client, caplog): - date = datetime(2022, 1, 7) + date = datetime.datetime(2022, 1, 7, tzinfo=datetime.UTC) invoices = [ {"id": "1", "total amount": "100", "currency": "USD"}, {"id": "2", "total amount": "200", "currency": "GBH"}, @@ -653,7 +663,7 @@ def test_mark_invoices_paid_error(alma_client, caplog): ] paid_invoice_count = sap.mark_invoices_paid( - alma_client, invoices, datetime(2022, 1, 7) + alma_client, invoices, datetime.datetime(2022, 1, 7, tzinfo=datetime.UTC) ) assert alma_client.mark_invoice_paid.call_args_list == expected_calls assert paid_invoice_count == 2 @@ -661,7 +671,7 @@ def test_mark_invoices_paid_error(alma_client, caplog): def test_mark_invoices_paid_handles_request_exception(alma_client, caplog): - date = datetime(2022, 1, 7) + date = datetime.datetime(2022, 1, 7, tzinfo=datetime.UTC) invoices = [ {"id": "1", "total amount": "100", "currency": "USD"}, {"id": "2", "total amount": "200", "currency": "GBH"}, @@ -681,7 +691,7 @@ def test_mark_invoices_paid_handles_request_exception(alma_client, caplog): call("3", date, "300", "GBH"), ] paid_invoice_count = sap.mark_invoices_paid( - alma_client, invoices, datetime(2022, 1, 7) + alma_client, invoices, datetime.datetime(2022, 1, 7, tzinfo=datetime.UTC) ) assert alma_client.mark_invoice_paid.call_args_list == expected_calls assert paid_invoice_count == 2 @@ -700,7 +710,7 @@ def test_run_not_final_not_real( invoices_for_sap_with_different_payment_method, "monograph", "0003", - datetime(2022, 1, 11), + datetime.datetime(2022, 1, 11, tzinfo=datetime.UTC), final_run=False, real_run=False, ) @@ -724,7 +734,7 @@ def test_run_not_final_real( invoices_for_sap, "monograph", "0003", - datetime(2022, 1, 11), + datetime.datetime(2022, 1, 11, tzinfo=datetime.UTC), final_run=False, real_run=True, ) @@ -748,18 +758,18 @@ def test_run_final_not_real( invoices_for_sap, "monograph", "0003", - datetime(2022, 1, 11), + datetime.datetime(2022, 1, 11, tzinfo=datetime.UTC), final_run=True, real_run=False, ) assert "Monographs control file contents:" in caplog.text -def test_run_final_real( # noqa pylint R0913 Too many arguments +def test_run_final_real( alma_client, monkeypatch, caplog, - mocked_sftp, # noqa pylint W0613 Unused argument + mocked_sftp, invoices_for_sap, test_sftp_private_key, problem_invoices, @@ -782,7 +792,7 @@ def test_run_final_real( # noqa pylint R0913 Too many arguments invoices_for_sap, "monograph", "0003", - datetime(2022, 1, 11), + datetime.datetime(2022, 1, 11, tzinfo=datetime.UTC), final_run=True, real_run=True, ) diff --git a/tests/test_ssm.py b/tests/test_ssm.py index 06aedd4..b86f98d 100644 --- a/tests/test_ssm.py +++ b/tests/test_ssm.py @@ -1,3 +1,5 @@ +# ruff: noqa: PLR2004 + from sapinvoices.ssm import SSM From 2abc3bf44e56927f1761a566e064dd7d1453da35 Mon Sep 17 00:00:00 2001 From: Graham Hukill Date: Tue, 11 Jun 2024 10:09:43 -0400 Subject: [PATCH 2/5] Remove setup.cfg file --- setup.cfg | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 setup.cfg diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index addb669..0000000 --- a/setup.cfg +++ /dev/null @@ -1,26 +0,0 @@ -[mypy] -disallow_incomplete_defs = True -disallow_untyped_calls = True -disallow_untyped_defs = True - -[mypy-sentry_sdk.*] -ignore_missing_imports = True - -[mypy-fabric.*] -ignore_missing_imports = True - -[pylama] -ignore = C0114,C0116,D100,D103,W0012 -linters = eradicate,isort,mccabe,pycodestyle,pyflakes,pylint -max_line_length = 90 - -[pylama:isort] -profile = black - -[pydocstyle] -ignore = D100,D103,D213,D203,D407,D406 - - -[tool:pytest] -log_level = DEBUG - From cb42c65180422fa8344c82a02f866d2a6d91fe98 Mon Sep 17 00:00:00 2001 From: Graham Hukill Date: Tue, 11 Jun 2024 11:37:49 -0400 Subject: [PATCH 3/5] Remove dependency and add ValueError message --- Pipfile | 1 - sapinvoices/alma.py | 5 +++-- sapinvoices/config.py | 2 +- tests/test_alma.py | 5 ++++- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Pipfile b/Pipfile index aa29c61..8f60d1e 100644 --- a/Pipfile +++ b/Pipfile @@ -23,7 +23,6 @@ mock-ssh-server = "*" moto = "*" mypy = "*" pre-commit = "*" -pydocstyle = "*" requests-mock = "*" ruff = "*" types-requests = "*" diff --git a/sapinvoices/alma.py b/sapinvoices/alma.py index 05a6678..a8bb065 100644 --- a/sapinvoices/alma.py +++ b/sapinvoices/alma.py @@ -217,8 +217,9 @@ def mark_invoice_paid( ) result.raise_for_status() time.sleep(0.1) - if not result.json()["payment"]["payment_status"]["value"] == "PAID": - raise ValueError + if result.json()["payment"]["payment_status"]["value"] != "PAID": + message = f"Invoice '{invoice_id}' not marked as 'PAID' in Alma." + raise ValueError(message) def process_invoice(self, invoice_id: str) -> dict: """Move an invoice to in process using the invoice process endpoint.""" diff --git a/sapinvoices/config.py b/sapinvoices/config.py index 4e72d58..39031d1 100644 --- a/sapinvoices/config.py +++ b/sapinvoices/config.py @@ -21,7 +21,7 @@ def configure_logger(logger: logging.Logger, log_level_string: str) -> str: message = f"'{log_level_string}' is not a valid Python logging level" raise ValueError(message) log_level = logging.getLevelName(log_level_string.upper()) - if log_level < 20: # noqa: PLR2004 + if log_level < logging.INFO: logging.basicConfig( format="%(asctime)s %(levelname)s %(name)s.%(funcName)s() line %(lineno)d: " "%(message)s" diff --git a/tests/test_alma.py b/tests/test_alma.py index f76bd4d..db82054 100644 --- a/tests/test_alma.py +++ b/tests/test_alma.py @@ -176,7 +176,10 @@ def test_mark_invoice_paid_request_value_error(alma_client): mocked_response = {"payment": {"payment_status": {"value": "FOO"}}} with requests_mock.Mocker(case_sensitive=True) as mocker: mocker.post(test_url, json=mocked_response) - with pytest.raises(ValueError): # noqa: PT011 + with pytest.raises( + ValueError, + match=f"Invoice '{invoice_id}' not marked as 'PAID' in Alma.", + ): alma_client.mark_invoice_paid( invoice_id, payment_date=payment_date, From ebcaf2e79e7c55704f958c2436866c2ab4273add Mon Sep 17 00:00:00 2001 From: Graham Hukill Date: Tue, 11 Jun 2024 11:39:49 -0400 Subject: [PATCH 4/5] Update pre-commit python version and Makefile comments --- .pre-commit-config.yaml | 2 +- Makefile | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d842a91..020e600 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,5 @@ default_language_version: - python: python3.11 # set for project python version + python: python3.12 # set for project python version repos: - repo: local hooks: diff --git a/Makefile b/Makefile index c326e0d..702a238 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,9 @@ help: # preview Makefile commands @awk 'BEGIN { FS = ":.*#"; print "Usage: make \n\nTargets:" } \ /^[-_[:alpha:]]+:.?*#/ { printf " %-15s%s\n", $$1, $$2 }' $(MAKEFILE_LIST) -## ---- Dependency commands ---- ## +####################### +# Dependency commands +####################### install: # Install Python dependencies pipenv install --dev @@ -23,7 +25,9 @@ update: install # Update Python dependencies pipenv clean pipenv update --dev -## ---- Unit test commands ---- ## +###################### +# Unit test commands +###################### test: # Run tests and print a coverage report pipenv run coverage run --source=sapinvoices -m pytest -vv @@ -32,7 +36,9 @@ test: # Run tests and print a coverage report coveralls: test # Write coverage data to an LCOV report pipenv run coverage lcov -o ./coverage/lcov.info -## ---- Code quality and safety commands ---- ## +#################################### +# Code quality and safety commands +#################################### lint: black mypy ruff safety # run linters @@ -57,6 +63,9 @@ black-apply: # apply changes with 'black' ruff-apply: # resolve 'fixable errors' with 'ruff' pipenv run ruff check --fix . +#################################### +# Docker and Terraform commands +#################################### ### Terraform-generated Developer Deploy Commands for Dev environment ### dist-dev: ## Build docker container (intended for developer-based manual build) From 40e4866c2162e854123ba2cfe26a100616aad6ad Mon Sep 17 00:00:00 2001 From: Graham Hukill Date: Tue, 11 Jun 2024 11:43:09 -0400 Subject: [PATCH 5/5] Ignore untyped imports via pyproject.toml --- pyproject.toml | 7 +++++++ sapinvoices/sap.py | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d646080..f3bb840 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,6 +10,13 @@ disallow_untyped_calls = true disallow_untyped_defs = true exclude = ["tests/"] +[[tool.mypy.overrides]] +module = [ + "fabric", + "flatdict" +] +ignore_missing_imports = true + [tool.pytest.ini_options] log_level = "INFO" diff --git a/sapinvoices/sap.py b/sapinvoices/sap.py index 128a2db..91b66cc 100644 --- a/sapinvoices/sap.py +++ b/sapinvoices/sap.py @@ -9,8 +9,8 @@ from math import fsum from typing import Any, Literal -import fabric # type: ignore[import-untyped] -import flatdict # type: ignore[import-untyped] +import fabric +import flatdict import requests.exceptions from paramiko import RSAKey