diff --git a/poetry.lock b/poetry.lock index 0fe4fdf..eba4a11 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2,22 +2,22 @@ [[package]] name = "attrs" -version = "23.2.0" +version = "24.2.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.7" files = [ - {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, - {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, + {file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"}, + {file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"}, ] [package.extras] -cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] -dev = ["attrs[tests]", "pre-commit"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] -tests = ["attrs[tests-no-zope]", "zope-interface"] -tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] -tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] +benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] +tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] [[package]] name = "beautifulsoup4" @@ -40,46 +40,6 @@ charset-normalizer = ["charset-normalizer"] html5lib = ["html5lib"] lxml = ["lxml"] -[[package]] -name = "biopython" -version = "1.81" -description = "Freely available tools for computational molecular biology." -optional = false -python-versions = ">=3.7" -files = [ - {file = "biopython-1.81-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef7c79b65b0b3f3c7dc59e20a7f8ae5758d8e852cb8b9cace590dc5617e348ba"}, - {file = "biopython-1.81-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ebfbce0d91796c7aef422ee9dffe8827e07e5abaa94545e006f1f20e965c80b"}, - {file = "biopython-1.81-cp310-cp310-win32.whl", hash = "sha256:919a2c583cabf9c96d2ae4e1245a6b0376932fb342aca302a0fc198b71ab3275"}, - {file = "biopython-1.81-cp310-cp310-win_amd64.whl", hash = "sha256:b37c0d24191e5c96ca02415a5188551980c83a0d518bbc4ffe3c9a5d1fe0ee81"}, - {file = "biopython-1.81-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7a168709694e10b338718c18d967edd5b56c237dc88642c22275796007a70000"}, - {file = "biopython-1.81-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a51d9c1d1b4b634447535da74a644fae59bc234fbbf9001e2dc6b6fbabb98019"}, - {file = "biopython-1.81-cp311-cp311-win32.whl", hash = "sha256:2f9cfaf16d55ab80d514e7aebe5710dabe4e4ff47ede851031202e33b3249da3"}, - {file = "biopython-1.81-cp311-cp311-win_amd64.whl", hash = "sha256:e41b55edcfd448630e77bf4de66a7235324a8a149621499891da6bd1d5085b9a"}, - {file = "biopython-1.81-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:175fcddc9f22a070aa6db54755d60c4b31090cc39f5f5f4b0a9a5d1ae3b45cd7"}, - {file = "biopython-1.81-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ec149487f3d1e0cf2b52b6071641c161ed545b0855ff51a71506152e14fc5bb"}, - {file = "biopython-1.81-cp312-cp312-win32.whl", hash = "sha256:daeab15274bbcc0455cbd378636e14f53bc7c5b1f383e77021d7222e72cc3418"}, - {file = "biopython-1.81-cp312-cp312-win_amd64.whl", hash = "sha256:22f5741aca91af0a76c0d5617e58e554fd3374bbd16e0c0ac1facf45b107313b"}, - {file = "biopython-1.81-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3b36ba1bf6395c09a365c53530c9d71f3617763fa2c1d452b3d8948368c0f1de"}, - {file = "biopython-1.81-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c5c07123ff5f44c9e6b5369df854a38afd3c0c50ef58498a0ae8f7eb799f3e8"}, - {file = "biopython-1.81-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:97cbdbed01b2512471f36c74b91658d1dfbdcbf39bc038f6ce5a41c3e60a8fc6"}, - {file = "biopython-1.81-cp37-cp37m-win32.whl", hash = "sha256:35506e39822c52d11cf09a3951e82375ca1bb9303960b4286acf02c9a6f6c4cc"}, - {file = "biopython-1.81-cp37-cp37m-win_amd64.whl", hash = "sha256:793c42a376cd63f62f8a088ce39b7dc6b5c55e4e9031d887c434de1595bfa4b8"}, - {file = "biopython-1.81-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:11d673698b3d0d6589292ea951fb62cb24ea27d273eca0d08dbbd956690f97f5"}, - {file = "biopython-1.81-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:655df416936662c0c8a06a549cb25e1560e1fea5067d850f34fb714b8a3fae6c"}, - {file = "biopython-1.81-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:762c6c43a8486b5fcd07f136a3217b87d24755618b9ea9da1f17124ff44c2ad6"}, - {file = "biopython-1.81-cp38-cp38-win32.whl", hash = "sha256:ee51bb1cd7decffd24da6b76d5e01b7e2fd818ab85cf0c180226cbb5793a3abd"}, - {file = "biopython-1.81-cp38-cp38-win_amd64.whl", hash = "sha256:ccd729249fd5f586dd4c2a3507c2ea2456825d7e615e97c07c409c850eaf4594"}, - {file = "biopython-1.81-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9ba33244f0eff830beaa7240065bdb5095d96fded6599b76bbb9ddab45cd2bbd"}, - {file = "biopython-1.81-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8bb0c690c7368f255ed45236bf0f5464b476b8c083c8f634533921af78278261"}, - {file = "biopython-1.81-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65b93b513ce9dd7b2ce058720eadf42cd03f312db3409356efeb93123d1320aa"}, - {file = "biopython-1.81-cp39-cp39-win32.whl", hash = "sha256:811796f8d222aa3869a50e31e54ce62b69106b47cd8bb06934867c0d843297b5"}, - {file = "biopython-1.81-cp39-cp39-win_amd64.whl", hash = "sha256:b09efcb4733c8770f25eab5fe555a96a08f5ab9e1bc36939e08ebf2ffbf3e0f1"}, - {file = "biopython-1.81.tar.gz", hash = "sha256:2cf38112b6d8415ad39d6a611988cd11fb5f33eb09346666a87263beba9614e0"}, -] - -[package.dependencies] -numpy = "*" - [[package]] name = "black" version = "24.10.0" @@ -128,450 +88,54 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "boto3" -version = "1.28.47" +version = "1.35.81" description = "The AWS SDK for Python" optional = false -python-versions = ">= 3.7" +python-versions = ">=3.8" files = [ - {file = "boto3-1.28.47-py3-none-any.whl", hash = "sha256:27560da44099e7e2ee961d3971d8ea659de2e0dc24e78043d1c3027d89b2d8a2"}, - {file = "boto3-1.28.47.tar.gz", hash = "sha256:be69cd28e3732b63ad61f6d2429b1eac92428588911a5a7367faa4e129a4738d"}, + {file = "boto3-1.35.81-py3-none-any.whl", hash = "sha256:742941b2424c0223d2d94a08c3485462fa7c58d816b62ca80f08e555243acee1"}, + {file = "boto3-1.35.81.tar.gz", hash = "sha256:d2e95fa06f095b8e0c545dd678c6269d253809b2997c30f5ce8a956c410b4e86"}, ] [package.dependencies] -botocore = ">=1.31.47,<1.32.0" +botocore = ">=1.35.81,<1.36.0" jmespath = ">=0.7.1,<2.0.0" -s3transfer = ">=0.6.0,<0.7.0" +s3transfer = ">=0.10.0,<0.11.0" [package.extras] crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] -[[package]] -name = "boto3-stubs" -version = "1.34.43" -description = "Type annotations for boto3 1.34.43 generated with mypy-boto3-builder 7.23.1" -optional = false -python-versions = ">=3.8" -files = [ - {file = "boto3-stubs-1.34.43.tar.gz", hash = "sha256:0a0bdf96eb42f3b12b9bf159d97c407cf272e0430e5f7b42581ce7124ce9bb78"}, - {file = "boto3_stubs-1.34.43-py3-none-any.whl", hash = "sha256:5698322a22e54dbebc6f0010dc0f08271f0c911d7f4c5880af341d5f0323748a"}, -] - -[package.dependencies] -botocore-stubs = "*" -types-s3transfer = "*" -typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.12\""} - -[package.extras] -accessanalyzer = ["mypy-boto3-accessanalyzer (>=1.34.0,<1.35.0)"] -account = ["mypy-boto3-account (>=1.34.0,<1.35.0)"] -acm = ["mypy-boto3-acm (>=1.34.0,<1.35.0)"] -acm-pca = ["mypy-boto3-acm-pca (>=1.34.0,<1.35.0)"] -alexaforbusiness = ["mypy-boto3-alexaforbusiness (>=1.34.0,<1.35.0)"] -all = ["mypy-boto3-accessanalyzer (>=1.34.0,<1.35.0)", "mypy-boto3-account (>=1.34.0,<1.35.0)", "mypy-boto3-acm (>=1.34.0,<1.35.0)", "mypy-boto3-acm-pca (>=1.34.0,<1.35.0)", "mypy-boto3-alexaforbusiness (>=1.34.0,<1.35.0)", "mypy-boto3-amp (>=1.34.0,<1.35.0)", "mypy-boto3-amplify (>=1.34.0,<1.35.0)", "mypy-boto3-amplifybackend (>=1.34.0,<1.35.0)", "mypy-boto3-amplifyuibuilder (>=1.34.0,<1.35.0)", "mypy-boto3-apigateway (>=1.34.0,<1.35.0)", "mypy-boto3-apigatewaymanagementapi (>=1.34.0,<1.35.0)", "mypy-boto3-apigatewayv2 (>=1.34.0,<1.35.0)", "mypy-boto3-appconfig (>=1.34.0,<1.35.0)", "mypy-boto3-appconfigdata (>=1.34.0,<1.35.0)", "mypy-boto3-appfabric (>=1.34.0,<1.35.0)", "mypy-boto3-appflow (>=1.34.0,<1.35.0)", "mypy-boto3-appintegrations (>=1.34.0,<1.35.0)", "mypy-boto3-application-autoscaling (>=1.34.0,<1.35.0)", "mypy-boto3-application-insights (>=1.34.0,<1.35.0)", "mypy-boto3-applicationcostprofiler (>=1.34.0,<1.35.0)", "mypy-boto3-appmesh (>=1.34.0,<1.35.0)", "mypy-boto3-apprunner (>=1.34.0,<1.35.0)", "mypy-boto3-appstream (>=1.34.0,<1.35.0)", "mypy-boto3-appsync (>=1.34.0,<1.35.0)", "mypy-boto3-arc-zonal-shift (>=1.34.0,<1.35.0)", "mypy-boto3-artifact (>=1.34.0,<1.35.0)", "mypy-boto3-athena (>=1.34.0,<1.35.0)", "mypy-boto3-auditmanager (>=1.34.0,<1.35.0)", "mypy-boto3-autoscaling (>=1.34.0,<1.35.0)", "mypy-boto3-autoscaling-plans (>=1.34.0,<1.35.0)", "mypy-boto3-b2bi (>=1.34.0,<1.35.0)", "mypy-boto3-backup (>=1.34.0,<1.35.0)", "mypy-boto3-backup-gateway (>=1.34.0,<1.35.0)", "mypy-boto3-backupstorage (>=1.34.0,<1.35.0)", "mypy-boto3-batch (>=1.34.0,<1.35.0)", "mypy-boto3-bcm-data-exports (>=1.34.0,<1.35.0)", "mypy-boto3-bedrock (>=1.34.0,<1.35.0)", "mypy-boto3-bedrock-agent (>=1.34.0,<1.35.0)", "mypy-boto3-bedrock-agent-runtime (>=1.34.0,<1.35.0)", "mypy-boto3-bedrock-runtime (>=1.34.0,<1.35.0)", "mypy-boto3-billingconductor (>=1.34.0,<1.35.0)", "mypy-boto3-braket (>=1.34.0,<1.35.0)", "mypy-boto3-budgets (>=1.34.0,<1.35.0)", "mypy-boto3-ce (>=1.34.0,<1.35.0)", "mypy-boto3-chime (>=1.34.0,<1.35.0)", "mypy-boto3-chime-sdk-identity (>=1.34.0,<1.35.0)", "mypy-boto3-chime-sdk-media-pipelines (>=1.34.0,<1.35.0)", "mypy-boto3-chime-sdk-meetings (>=1.34.0,<1.35.0)", "mypy-boto3-chime-sdk-messaging (>=1.34.0,<1.35.0)", "mypy-boto3-chime-sdk-voice (>=1.34.0,<1.35.0)", "mypy-boto3-cleanrooms (>=1.34.0,<1.35.0)", "mypy-boto3-cleanroomsml (>=1.34.0,<1.35.0)", "mypy-boto3-cloud9 (>=1.34.0,<1.35.0)", "mypy-boto3-cloudcontrol (>=1.34.0,<1.35.0)", "mypy-boto3-clouddirectory (>=1.34.0,<1.35.0)", "mypy-boto3-cloudformation (>=1.34.0,<1.35.0)", "mypy-boto3-cloudfront (>=1.34.0,<1.35.0)", "mypy-boto3-cloudfront-keyvaluestore (>=1.34.0,<1.35.0)", "mypy-boto3-cloudhsm (>=1.34.0,<1.35.0)", "mypy-boto3-cloudhsmv2 (>=1.34.0,<1.35.0)", "mypy-boto3-cloudsearch (>=1.34.0,<1.35.0)", "mypy-boto3-cloudsearchdomain (>=1.34.0,<1.35.0)", "mypy-boto3-cloudtrail (>=1.34.0,<1.35.0)", "mypy-boto3-cloudtrail-data (>=1.34.0,<1.35.0)", "mypy-boto3-cloudwatch (>=1.34.0,<1.35.0)", "mypy-boto3-codeartifact (>=1.34.0,<1.35.0)", "mypy-boto3-codebuild (>=1.34.0,<1.35.0)", "mypy-boto3-codecatalyst (>=1.34.0,<1.35.0)", "mypy-boto3-codecommit (>=1.34.0,<1.35.0)", "mypy-boto3-codedeploy (>=1.34.0,<1.35.0)", "mypy-boto3-codeguru-reviewer (>=1.34.0,<1.35.0)", "mypy-boto3-codeguru-security (>=1.34.0,<1.35.0)", "mypy-boto3-codeguruprofiler (>=1.34.0,<1.35.0)", "mypy-boto3-codepipeline (>=1.34.0,<1.35.0)", "mypy-boto3-codestar (>=1.34.0,<1.35.0)", "mypy-boto3-codestar-connections (>=1.34.0,<1.35.0)", "mypy-boto3-codestar-notifications (>=1.34.0,<1.35.0)", "mypy-boto3-cognito-identity (>=1.34.0,<1.35.0)", "mypy-boto3-cognito-idp (>=1.34.0,<1.35.0)", "mypy-boto3-cognito-sync (>=1.34.0,<1.35.0)", "mypy-boto3-comprehend (>=1.34.0,<1.35.0)", "mypy-boto3-comprehendmedical (>=1.34.0,<1.35.0)", "mypy-boto3-compute-optimizer (>=1.34.0,<1.35.0)", "mypy-boto3-config (>=1.34.0,<1.35.0)", "mypy-boto3-connect (>=1.34.0,<1.35.0)", "mypy-boto3-connect-contact-lens (>=1.34.0,<1.35.0)", "mypy-boto3-connectcampaigns (>=1.34.0,<1.35.0)", "mypy-boto3-connectcases (>=1.34.0,<1.35.0)", "mypy-boto3-connectparticipant (>=1.34.0,<1.35.0)", "mypy-boto3-controltower (>=1.34.0,<1.35.0)", "mypy-boto3-cost-optimization-hub (>=1.34.0,<1.35.0)", "mypy-boto3-cur (>=1.34.0,<1.35.0)", "mypy-boto3-customer-profiles (>=1.34.0,<1.35.0)", "mypy-boto3-databrew (>=1.34.0,<1.35.0)", "mypy-boto3-dataexchange (>=1.34.0,<1.35.0)", "mypy-boto3-datapipeline (>=1.34.0,<1.35.0)", "mypy-boto3-datasync (>=1.34.0,<1.35.0)", "mypy-boto3-datazone (>=1.34.0,<1.35.0)", "mypy-boto3-dax (>=1.34.0,<1.35.0)", "mypy-boto3-detective (>=1.34.0,<1.35.0)", "mypy-boto3-devicefarm (>=1.34.0,<1.35.0)", "mypy-boto3-devops-guru (>=1.34.0,<1.35.0)", "mypy-boto3-directconnect (>=1.34.0,<1.35.0)", "mypy-boto3-discovery (>=1.34.0,<1.35.0)", "mypy-boto3-dlm (>=1.34.0,<1.35.0)", "mypy-boto3-dms (>=1.34.0,<1.35.0)", "mypy-boto3-docdb (>=1.34.0,<1.35.0)", "mypy-boto3-docdb-elastic (>=1.34.0,<1.35.0)", "mypy-boto3-drs (>=1.34.0,<1.35.0)", "mypy-boto3-ds (>=1.34.0,<1.35.0)", "mypy-boto3-dynamodb (>=1.34.0,<1.35.0)", "mypy-boto3-dynamodbstreams (>=1.34.0,<1.35.0)", "mypy-boto3-ebs (>=1.34.0,<1.35.0)", "mypy-boto3-ec2 (>=1.34.0,<1.35.0)", "mypy-boto3-ec2-instance-connect (>=1.34.0,<1.35.0)", "mypy-boto3-ecr (>=1.34.0,<1.35.0)", "mypy-boto3-ecr-public (>=1.34.0,<1.35.0)", "mypy-boto3-ecs (>=1.34.0,<1.35.0)", "mypy-boto3-efs (>=1.34.0,<1.35.0)", "mypy-boto3-eks (>=1.34.0,<1.35.0)", "mypy-boto3-eks-auth (>=1.34.0,<1.35.0)", "mypy-boto3-elastic-inference (>=1.34.0,<1.35.0)", "mypy-boto3-elasticache (>=1.34.0,<1.35.0)", "mypy-boto3-elasticbeanstalk (>=1.34.0,<1.35.0)", "mypy-boto3-elastictranscoder (>=1.34.0,<1.35.0)", "mypy-boto3-elb (>=1.34.0,<1.35.0)", "mypy-boto3-elbv2 (>=1.34.0,<1.35.0)", "mypy-boto3-emr (>=1.34.0,<1.35.0)", "mypy-boto3-emr-containers (>=1.34.0,<1.35.0)", "mypy-boto3-emr-serverless (>=1.34.0,<1.35.0)", "mypy-boto3-entityresolution (>=1.34.0,<1.35.0)", "mypy-boto3-es (>=1.34.0,<1.35.0)", "mypy-boto3-events (>=1.34.0,<1.35.0)", "mypy-boto3-evidently (>=1.34.0,<1.35.0)", "mypy-boto3-finspace (>=1.34.0,<1.35.0)", "mypy-boto3-finspace-data (>=1.34.0,<1.35.0)", "mypy-boto3-firehose (>=1.34.0,<1.35.0)", "mypy-boto3-fis (>=1.34.0,<1.35.0)", "mypy-boto3-fms (>=1.34.0,<1.35.0)", "mypy-boto3-forecast (>=1.34.0,<1.35.0)", "mypy-boto3-forecastquery (>=1.34.0,<1.35.0)", "mypy-boto3-frauddetector (>=1.34.0,<1.35.0)", "mypy-boto3-freetier (>=1.34.0,<1.35.0)", "mypy-boto3-fsx (>=1.34.0,<1.35.0)", "mypy-boto3-gamelift (>=1.34.0,<1.35.0)", "mypy-boto3-glacier (>=1.34.0,<1.35.0)", "mypy-boto3-globalaccelerator (>=1.34.0,<1.35.0)", "mypy-boto3-glue (>=1.34.0,<1.35.0)", "mypy-boto3-grafana (>=1.34.0,<1.35.0)", "mypy-boto3-greengrass (>=1.34.0,<1.35.0)", "mypy-boto3-greengrassv2 (>=1.34.0,<1.35.0)", "mypy-boto3-groundstation (>=1.34.0,<1.35.0)", "mypy-boto3-guardduty (>=1.34.0,<1.35.0)", "mypy-boto3-health (>=1.34.0,<1.35.0)", "mypy-boto3-healthlake (>=1.34.0,<1.35.0)", "mypy-boto3-honeycode (>=1.34.0,<1.35.0)", "mypy-boto3-iam (>=1.34.0,<1.35.0)", "mypy-boto3-identitystore (>=1.34.0,<1.35.0)", "mypy-boto3-imagebuilder (>=1.34.0,<1.35.0)", "mypy-boto3-importexport (>=1.34.0,<1.35.0)", "mypy-boto3-inspector (>=1.34.0,<1.35.0)", "mypy-boto3-inspector-scan (>=1.34.0,<1.35.0)", "mypy-boto3-inspector2 (>=1.34.0,<1.35.0)", "mypy-boto3-internetmonitor (>=1.34.0,<1.35.0)", "mypy-boto3-iot (>=1.34.0,<1.35.0)", "mypy-boto3-iot-data (>=1.34.0,<1.35.0)", "mypy-boto3-iot-jobs-data (>=1.34.0,<1.35.0)", "mypy-boto3-iot-roborunner (>=1.34.0,<1.35.0)", "mypy-boto3-iot1click-devices (>=1.34.0,<1.35.0)", "mypy-boto3-iot1click-projects (>=1.34.0,<1.35.0)", "mypy-boto3-iotanalytics (>=1.34.0,<1.35.0)", "mypy-boto3-iotdeviceadvisor (>=1.34.0,<1.35.0)", "mypy-boto3-iotevents (>=1.34.0,<1.35.0)", "mypy-boto3-iotevents-data (>=1.34.0,<1.35.0)", "mypy-boto3-iotfleethub (>=1.34.0,<1.35.0)", "mypy-boto3-iotfleetwise (>=1.34.0,<1.35.0)", "mypy-boto3-iotsecuretunneling (>=1.34.0,<1.35.0)", "mypy-boto3-iotsitewise (>=1.34.0,<1.35.0)", "mypy-boto3-iotthingsgraph (>=1.34.0,<1.35.0)", "mypy-boto3-iottwinmaker (>=1.34.0,<1.35.0)", "mypy-boto3-iotwireless (>=1.34.0,<1.35.0)", "mypy-boto3-ivs (>=1.34.0,<1.35.0)", "mypy-boto3-ivs-realtime (>=1.34.0,<1.35.0)", "mypy-boto3-ivschat (>=1.34.0,<1.35.0)", "mypy-boto3-kafka (>=1.34.0,<1.35.0)", "mypy-boto3-kafkaconnect (>=1.34.0,<1.35.0)", "mypy-boto3-kendra (>=1.34.0,<1.35.0)", "mypy-boto3-kendra-ranking (>=1.34.0,<1.35.0)", "mypy-boto3-keyspaces (>=1.34.0,<1.35.0)", "mypy-boto3-kinesis (>=1.34.0,<1.35.0)", "mypy-boto3-kinesis-video-archived-media (>=1.34.0,<1.35.0)", "mypy-boto3-kinesis-video-media (>=1.34.0,<1.35.0)", "mypy-boto3-kinesis-video-signaling (>=1.34.0,<1.35.0)", "mypy-boto3-kinesis-video-webrtc-storage (>=1.34.0,<1.35.0)", "mypy-boto3-kinesisanalytics (>=1.34.0,<1.35.0)", "mypy-boto3-kinesisanalyticsv2 (>=1.34.0,<1.35.0)", "mypy-boto3-kinesisvideo (>=1.34.0,<1.35.0)", "mypy-boto3-kms (>=1.34.0,<1.35.0)", "mypy-boto3-lakeformation (>=1.34.0,<1.35.0)", "mypy-boto3-lambda (>=1.34.0,<1.35.0)", "mypy-boto3-launch-wizard (>=1.34.0,<1.35.0)", "mypy-boto3-lex-models (>=1.34.0,<1.35.0)", "mypy-boto3-lex-runtime (>=1.34.0,<1.35.0)", "mypy-boto3-lexv2-models (>=1.34.0,<1.35.0)", "mypy-boto3-lexv2-runtime (>=1.34.0,<1.35.0)", "mypy-boto3-license-manager (>=1.34.0,<1.35.0)", "mypy-boto3-license-manager-linux-subscriptions (>=1.34.0,<1.35.0)", "mypy-boto3-license-manager-user-subscriptions (>=1.34.0,<1.35.0)", "mypy-boto3-lightsail (>=1.34.0,<1.35.0)", "mypy-boto3-location (>=1.34.0,<1.35.0)", "mypy-boto3-logs (>=1.34.0,<1.35.0)", "mypy-boto3-lookoutequipment (>=1.34.0,<1.35.0)", "mypy-boto3-lookoutmetrics (>=1.34.0,<1.35.0)", "mypy-boto3-lookoutvision (>=1.34.0,<1.35.0)", "mypy-boto3-m2 (>=1.34.0,<1.35.0)", "mypy-boto3-machinelearning (>=1.34.0,<1.35.0)", "mypy-boto3-macie2 (>=1.34.0,<1.35.0)", "mypy-boto3-managedblockchain (>=1.34.0,<1.35.0)", "mypy-boto3-managedblockchain-query (>=1.34.0,<1.35.0)", "mypy-boto3-marketplace-agreement (>=1.34.0,<1.35.0)", "mypy-boto3-marketplace-catalog (>=1.34.0,<1.35.0)", "mypy-boto3-marketplace-deployment (>=1.34.0,<1.35.0)", "mypy-boto3-marketplace-entitlement (>=1.34.0,<1.35.0)", "mypy-boto3-marketplacecommerceanalytics (>=1.34.0,<1.35.0)", "mypy-boto3-mediaconnect (>=1.34.0,<1.35.0)", "mypy-boto3-mediaconvert (>=1.34.0,<1.35.0)", "mypy-boto3-medialive (>=1.34.0,<1.35.0)", "mypy-boto3-mediapackage (>=1.34.0,<1.35.0)", "mypy-boto3-mediapackage-vod (>=1.34.0,<1.35.0)", "mypy-boto3-mediapackagev2 (>=1.34.0,<1.35.0)", "mypy-boto3-mediastore (>=1.34.0,<1.35.0)", "mypy-boto3-mediastore-data (>=1.34.0,<1.35.0)", "mypy-boto3-mediatailor (>=1.34.0,<1.35.0)", "mypy-boto3-medical-imaging (>=1.34.0,<1.35.0)", "mypy-boto3-memorydb (>=1.34.0,<1.35.0)", "mypy-boto3-meteringmarketplace (>=1.34.0,<1.35.0)", "mypy-boto3-mgh (>=1.34.0,<1.35.0)", "mypy-boto3-mgn (>=1.34.0,<1.35.0)", "mypy-boto3-migration-hub-refactor-spaces (>=1.34.0,<1.35.0)", "mypy-boto3-migrationhub-config (>=1.34.0,<1.35.0)", "mypy-boto3-migrationhuborchestrator (>=1.34.0,<1.35.0)", "mypy-boto3-migrationhubstrategy (>=1.34.0,<1.35.0)", "mypy-boto3-mobile (>=1.34.0,<1.35.0)", "mypy-boto3-mq (>=1.34.0,<1.35.0)", "mypy-boto3-mturk (>=1.34.0,<1.35.0)", "mypy-boto3-mwaa (>=1.34.0,<1.35.0)", "mypy-boto3-neptune (>=1.34.0,<1.35.0)", "mypy-boto3-neptune-graph (>=1.34.0,<1.35.0)", "mypy-boto3-neptunedata (>=1.34.0,<1.35.0)", "mypy-boto3-network-firewall (>=1.34.0,<1.35.0)", "mypy-boto3-networkmanager (>=1.34.0,<1.35.0)", "mypy-boto3-networkmonitor (>=1.34.0,<1.35.0)", "mypy-boto3-nimble (>=1.34.0,<1.35.0)", "mypy-boto3-oam (>=1.34.0,<1.35.0)", "mypy-boto3-omics (>=1.34.0,<1.35.0)", "mypy-boto3-opensearch (>=1.34.0,<1.35.0)", "mypy-boto3-opensearchserverless (>=1.34.0,<1.35.0)", "mypy-boto3-opsworks (>=1.34.0,<1.35.0)", "mypy-boto3-opsworkscm (>=1.34.0,<1.35.0)", "mypy-boto3-organizations (>=1.34.0,<1.35.0)", "mypy-boto3-osis (>=1.34.0,<1.35.0)", "mypy-boto3-outposts (>=1.34.0,<1.35.0)", "mypy-boto3-panorama (>=1.34.0,<1.35.0)", "mypy-boto3-payment-cryptography (>=1.34.0,<1.35.0)", "mypy-boto3-payment-cryptography-data (>=1.34.0,<1.35.0)", "mypy-boto3-pca-connector-ad (>=1.34.0,<1.35.0)", "mypy-boto3-personalize (>=1.34.0,<1.35.0)", "mypy-boto3-personalize-events (>=1.34.0,<1.35.0)", "mypy-boto3-personalize-runtime (>=1.34.0,<1.35.0)", "mypy-boto3-pi (>=1.34.0,<1.35.0)", "mypy-boto3-pinpoint (>=1.34.0,<1.35.0)", "mypy-boto3-pinpoint-email (>=1.34.0,<1.35.0)", "mypy-boto3-pinpoint-sms-voice (>=1.34.0,<1.35.0)", "mypy-boto3-pinpoint-sms-voice-v2 (>=1.34.0,<1.35.0)", "mypy-boto3-pipes (>=1.34.0,<1.35.0)", "mypy-boto3-polly (>=1.34.0,<1.35.0)", "mypy-boto3-pricing (>=1.34.0,<1.35.0)", "mypy-boto3-privatenetworks (>=1.34.0,<1.35.0)", "mypy-boto3-proton (>=1.34.0,<1.35.0)", "mypy-boto3-qbusiness (>=1.34.0,<1.35.0)", "mypy-boto3-qconnect (>=1.34.0,<1.35.0)", "mypy-boto3-qldb (>=1.34.0,<1.35.0)", "mypy-boto3-qldb-session (>=1.34.0,<1.35.0)", "mypy-boto3-quicksight (>=1.34.0,<1.35.0)", "mypy-boto3-ram (>=1.34.0,<1.35.0)", "mypy-boto3-rbin (>=1.34.0,<1.35.0)", "mypy-boto3-rds (>=1.34.0,<1.35.0)", "mypy-boto3-rds-data (>=1.34.0,<1.35.0)", "mypy-boto3-redshift (>=1.34.0,<1.35.0)", "mypy-boto3-redshift-data (>=1.34.0,<1.35.0)", "mypy-boto3-redshift-serverless (>=1.34.0,<1.35.0)", "mypy-boto3-rekognition (>=1.34.0,<1.35.0)", "mypy-boto3-repostspace (>=1.34.0,<1.35.0)", "mypy-boto3-resiliencehub (>=1.34.0,<1.35.0)", "mypy-boto3-resource-explorer-2 (>=1.34.0,<1.35.0)", "mypy-boto3-resource-groups (>=1.34.0,<1.35.0)", "mypy-boto3-resourcegroupstaggingapi (>=1.34.0,<1.35.0)", "mypy-boto3-robomaker (>=1.34.0,<1.35.0)", "mypy-boto3-rolesanywhere (>=1.34.0,<1.35.0)", "mypy-boto3-route53 (>=1.34.0,<1.35.0)", "mypy-boto3-route53-recovery-cluster (>=1.34.0,<1.35.0)", "mypy-boto3-route53-recovery-control-config (>=1.34.0,<1.35.0)", "mypy-boto3-route53-recovery-readiness (>=1.34.0,<1.35.0)", "mypy-boto3-route53domains (>=1.34.0,<1.35.0)", "mypy-boto3-route53resolver (>=1.34.0,<1.35.0)", "mypy-boto3-rum (>=1.34.0,<1.35.0)", "mypy-boto3-s3 (>=1.34.0,<1.35.0)", "mypy-boto3-s3control (>=1.34.0,<1.35.0)", "mypy-boto3-s3outposts (>=1.34.0,<1.35.0)", "mypy-boto3-sagemaker (>=1.34.0,<1.35.0)", "mypy-boto3-sagemaker-a2i-runtime (>=1.34.0,<1.35.0)", "mypy-boto3-sagemaker-edge (>=1.34.0,<1.35.0)", "mypy-boto3-sagemaker-featurestore-runtime (>=1.34.0,<1.35.0)", "mypy-boto3-sagemaker-geospatial (>=1.34.0,<1.35.0)", "mypy-boto3-sagemaker-metrics (>=1.34.0,<1.35.0)", "mypy-boto3-sagemaker-runtime (>=1.34.0,<1.35.0)", "mypy-boto3-savingsplans (>=1.34.0,<1.35.0)", "mypy-boto3-scheduler (>=1.34.0,<1.35.0)", "mypy-boto3-schemas (>=1.34.0,<1.35.0)", "mypy-boto3-sdb (>=1.34.0,<1.35.0)", "mypy-boto3-secretsmanager (>=1.34.0,<1.35.0)", "mypy-boto3-securityhub (>=1.34.0,<1.35.0)", "mypy-boto3-securitylake (>=1.34.0,<1.35.0)", "mypy-boto3-serverlessrepo (>=1.34.0,<1.35.0)", "mypy-boto3-service-quotas (>=1.34.0,<1.35.0)", "mypy-boto3-servicecatalog (>=1.34.0,<1.35.0)", "mypy-boto3-servicecatalog-appregistry (>=1.34.0,<1.35.0)", "mypy-boto3-servicediscovery (>=1.34.0,<1.35.0)", "mypy-boto3-ses (>=1.34.0,<1.35.0)", "mypy-boto3-sesv2 (>=1.34.0,<1.35.0)", "mypy-boto3-shield (>=1.34.0,<1.35.0)", "mypy-boto3-signer (>=1.34.0,<1.35.0)", "mypy-boto3-simspaceweaver (>=1.34.0,<1.35.0)", "mypy-boto3-sms (>=1.34.0,<1.35.0)", "mypy-boto3-sms-voice (>=1.34.0,<1.35.0)", "mypy-boto3-snow-device-management (>=1.34.0,<1.35.0)", "mypy-boto3-snowball (>=1.34.0,<1.35.0)", "mypy-boto3-sns (>=1.34.0,<1.35.0)", "mypy-boto3-sqs (>=1.34.0,<1.35.0)", "mypy-boto3-ssm (>=1.34.0,<1.35.0)", "mypy-boto3-ssm-contacts (>=1.34.0,<1.35.0)", "mypy-boto3-ssm-incidents (>=1.34.0,<1.35.0)", "mypy-boto3-ssm-sap (>=1.34.0,<1.35.0)", "mypy-boto3-sso (>=1.34.0,<1.35.0)", "mypy-boto3-sso-admin (>=1.34.0,<1.35.0)", "mypy-boto3-sso-oidc (>=1.34.0,<1.35.0)", "mypy-boto3-stepfunctions (>=1.34.0,<1.35.0)", "mypy-boto3-storagegateway (>=1.34.0,<1.35.0)", "mypy-boto3-sts (>=1.34.0,<1.35.0)", "mypy-boto3-supplychain (>=1.34.0,<1.35.0)", "mypy-boto3-support (>=1.34.0,<1.35.0)", "mypy-boto3-support-app (>=1.34.0,<1.35.0)", "mypy-boto3-swf (>=1.34.0,<1.35.0)", "mypy-boto3-synthetics (>=1.34.0,<1.35.0)", "mypy-boto3-textract (>=1.34.0,<1.35.0)", "mypy-boto3-timestream-query (>=1.34.0,<1.35.0)", "mypy-boto3-timestream-write (>=1.34.0,<1.35.0)", "mypy-boto3-tnb (>=1.34.0,<1.35.0)", "mypy-boto3-transcribe (>=1.34.0,<1.35.0)", "mypy-boto3-transfer (>=1.34.0,<1.35.0)", "mypy-boto3-translate (>=1.34.0,<1.35.0)", "mypy-boto3-trustedadvisor (>=1.34.0,<1.35.0)", "mypy-boto3-verifiedpermissions (>=1.34.0,<1.35.0)", "mypy-boto3-voice-id (>=1.34.0,<1.35.0)", "mypy-boto3-vpc-lattice (>=1.34.0,<1.35.0)", "mypy-boto3-waf (>=1.34.0,<1.35.0)", "mypy-boto3-waf-regional (>=1.34.0,<1.35.0)", "mypy-boto3-wafv2 (>=1.34.0,<1.35.0)", "mypy-boto3-wellarchitected (>=1.34.0,<1.35.0)", "mypy-boto3-wisdom (>=1.34.0,<1.35.0)", "mypy-boto3-workdocs (>=1.34.0,<1.35.0)", "mypy-boto3-worklink (>=1.34.0,<1.35.0)", "mypy-boto3-workmail (>=1.34.0,<1.35.0)", "mypy-boto3-workmailmessageflow (>=1.34.0,<1.35.0)", "mypy-boto3-workspaces (>=1.34.0,<1.35.0)", "mypy-boto3-workspaces-thin-client (>=1.34.0,<1.35.0)", "mypy-boto3-workspaces-web (>=1.34.0,<1.35.0)", "mypy-boto3-xray (>=1.34.0,<1.35.0)"] -amp = ["mypy-boto3-amp (>=1.34.0,<1.35.0)"] -amplify = ["mypy-boto3-amplify (>=1.34.0,<1.35.0)"] -amplifybackend = ["mypy-boto3-amplifybackend (>=1.34.0,<1.35.0)"] -amplifyuibuilder = ["mypy-boto3-amplifyuibuilder (>=1.34.0,<1.35.0)"] -apigateway = ["mypy-boto3-apigateway (>=1.34.0,<1.35.0)"] -apigatewaymanagementapi = ["mypy-boto3-apigatewaymanagementapi (>=1.34.0,<1.35.0)"] -apigatewayv2 = ["mypy-boto3-apigatewayv2 (>=1.34.0,<1.35.0)"] -appconfig = ["mypy-boto3-appconfig (>=1.34.0,<1.35.0)"] -appconfigdata = ["mypy-boto3-appconfigdata (>=1.34.0,<1.35.0)"] -appfabric = ["mypy-boto3-appfabric (>=1.34.0,<1.35.0)"] -appflow = ["mypy-boto3-appflow (>=1.34.0,<1.35.0)"] -appintegrations = ["mypy-boto3-appintegrations (>=1.34.0,<1.35.0)"] -application-autoscaling = ["mypy-boto3-application-autoscaling (>=1.34.0,<1.35.0)"] -application-insights = ["mypy-boto3-application-insights (>=1.34.0,<1.35.0)"] -applicationcostprofiler = ["mypy-boto3-applicationcostprofiler (>=1.34.0,<1.35.0)"] -appmesh = ["mypy-boto3-appmesh (>=1.34.0,<1.35.0)"] -apprunner = ["mypy-boto3-apprunner (>=1.34.0,<1.35.0)"] -appstream = ["mypy-boto3-appstream (>=1.34.0,<1.35.0)"] -appsync = ["mypy-boto3-appsync (>=1.34.0,<1.35.0)"] -arc-zonal-shift = ["mypy-boto3-arc-zonal-shift (>=1.34.0,<1.35.0)"] -artifact = ["mypy-boto3-artifact (>=1.34.0,<1.35.0)"] -athena = ["mypy-boto3-athena (>=1.34.0,<1.35.0)"] -auditmanager = ["mypy-boto3-auditmanager (>=1.34.0,<1.35.0)"] -autoscaling = ["mypy-boto3-autoscaling (>=1.34.0,<1.35.0)"] -autoscaling-plans = ["mypy-boto3-autoscaling-plans (>=1.34.0,<1.35.0)"] -b2bi = ["mypy-boto3-b2bi (>=1.34.0,<1.35.0)"] -backup = ["mypy-boto3-backup (>=1.34.0,<1.35.0)"] -backup-gateway = ["mypy-boto3-backup-gateway (>=1.34.0,<1.35.0)"] -backupstorage = ["mypy-boto3-backupstorage (>=1.34.0,<1.35.0)"] -batch = ["mypy-boto3-batch (>=1.34.0,<1.35.0)"] -bcm-data-exports = ["mypy-boto3-bcm-data-exports (>=1.34.0,<1.35.0)"] -bedrock = ["mypy-boto3-bedrock (>=1.34.0,<1.35.0)"] -bedrock-agent = ["mypy-boto3-bedrock-agent (>=1.34.0,<1.35.0)"] -bedrock-agent-runtime = ["mypy-boto3-bedrock-agent-runtime (>=1.34.0,<1.35.0)"] -bedrock-runtime = ["mypy-boto3-bedrock-runtime (>=1.34.0,<1.35.0)"] -billingconductor = ["mypy-boto3-billingconductor (>=1.34.0,<1.35.0)"] -boto3 = ["boto3 (==1.34.43)", "botocore (==1.34.43)"] -braket = ["mypy-boto3-braket (>=1.34.0,<1.35.0)"] -budgets = ["mypy-boto3-budgets (>=1.34.0,<1.35.0)"] -ce = ["mypy-boto3-ce (>=1.34.0,<1.35.0)"] -chime = ["mypy-boto3-chime (>=1.34.0,<1.35.0)"] -chime-sdk-identity = ["mypy-boto3-chime-sdk-identity (>=1.34.0,<1.35.0)"] -chime-sdk-media-pipelines = ["mypy-boto3-chime-sdk-media-pipelines (>=1.34.0,<1.35.0)"] -chime-sdk-meetings = ["mypy-boto3-chime-sdk-meetings (>=1.34.0,<1.35.0)"] -chime-sdk-messaging = ["mypy-boto3-chime-sdk-messaging (>=1.34.0,<1.35.0)"] -chime-sdk-voice = ["mypy-boto3-chime-sdk-voice (>=1.34.0,<1.35.0)"] -cleanrooms = ["mypy-boto3-cleanrooms (>=1.34.0,<1.35.0)"] -cleanroomsml = ["mypy-boto3-cleanroomsml (>=1.34.0,<1.35.0)"] -cloud9 = ["mypy-boto3-cloud9 (>=1.34.0,<1.35.0)"] -cloudcontrol = ["mypy-boto3-cloudcontrol (>=1.34.0,<1.35.0)"] -clouddirectory = ["mypy-boto3-clouddirectory (>=1.34.0,<1.35.0)"] -cloudformation = ["mypy-boto3-cloudformation (>=1.34.0,<1.35.0)"] -cloudfront = ["mypy-boto3-cloudfront (>=1.34.0,<1.35.0)"] -cloudfront-keyvaluestore = ["mypy-boto3-cloudfront-keyvaluestore (>=1.34.0,<1.35.0)"] -cloudhsm = ["mypy-boto3-cloudhsm (>=1.34.0,<1.35.0)"] -cloudhsmv2 = ["mypy-boto3-cloudhsmv2 (>=1.34.0,<1.35.0)"] -cloudsearch = ["mypy-boto3-cloudsearch (>=1.34.0,<1.35.0)"] -cloudsearchdomain = ["mypy-boto3-cloudsearchdomain (>=1.34.0,<1.35.0)"] -cloudtrail = ["mypy-boto3-cloudtrail (>=1.34.0,<1.35.0)"] -cloudtrail-data = ["mypy-boto3-cloudtrail-data (>=1.34.0,<1.35.0)"] -cloudwatch = ["mypy-boto3-cloudwatch (>=1.34.0,<1.35.0)"] -codeartifact = ["mypy-boto3-codeartifact (>=1.34.0,<1.35.0)"] -codebuild = ["mypy-boto3-codebuild (>=1.34.0,<1.35.0)"] -codecatalyst = ["mypy-boto3-codecatalyst (>=1.34.0,<1.35.0)"] -codecommit = ["mypy-boto3-codecommit (>=1.34.0,<1.35.0)"] -codedeploy = ["mypy-boto3-codedeploy (>=1.34.0,<1.35.0)"] -codeguru-reviewer = ["mypy-boto3-codeguru-reviewer (>=1.34.0,<1.35.0)"] -codeguru-security = ["mypy-boto3-codeguru-security (>=1.34.0,<1.35.0)"] -codeguruprofiler = ["mypy-boto3-codeguruprofiler (>=1.34.0,<1.35.0)"] -codepipeline = ["mypy-boto3-codepipeline (>=1.34.0,<1.35.0)"] -codestar = ["mypy-boto3-codestar (>=1.34.0,<1.35.0)"] -codestar-connections = ["mypy-boto3-codestar-connections (>=1.34.0,<1.35.0)"] -codestar-notifications = ["mypy-boto3-codestar-notifications (>=1.34.0,<1.35.0)"] -cognito-identity = ["mypy-boto3-cognito-identity (>=1.34.0,<1.35.0)"] -cognito-idp = ["mypy-boto3-cognito-idp (>=1.34.0,<1.35.0)"] -cognito-sync = ["mypy-boto3-cognito-sync (>=1.34.0,<1.35.0)"] -comprehend = ["mypy-boto3-comprehend (>=1.34.0,<1.35.0)"] -comprehendmedical = ["mypy-boto3-comprehendmedical (>=1.34.0,<1.35.0)"] -compute-optimizer = ["mypy-boto3-compute-optimizer (>=1.34.0,<1.35.0)"] -config = ["mypy-boto3-config (>=1.34.0,<1.35.0)"] -connect = ["mypy-boto3-connect (>=1.34.0,<1.35.0)"] -connect-contact-lens = ["mypy-boto3-connect-contact-lens (>=1.34.0,<1.35.0)"] -connectcampaigns = ["mypy-boto3-connectcampaigns (>=1.34.0,<1.35.0)"] -connectcases = ["mypy-boto3-connectcases (>=1.34.0,<1.35.0)"] -connectparticipant = ["mypy-boto3-connectparticipant (>=1.34.0,<1.35.0)"] -controltower = ["mypy-boto3-controltower (>=1.34.0,<1.35.0)"] -cost-optimization-hub = ["mypy-boto3-cost-optimization-hub (>=1.34.0,<1.35.0)"] -cur = ["mypy-boto3-cur (>=1.34.0,<1.35.0)"] -customer-profiles = ["mypy-boto3-customer-profiles (>=1.34.0,<1.35.0)"] -databrew = ["mypy-boto3-databrew (>=1.34.0,<1.35.0)"] -dataexchange = ["mypy-boto3-dataexchange (>=1.34.0,<1.35.0)"] -datapipeline = ["mypy-boto3-datapipeline (>=1.34.0,<1.35.0)"] -datasync = ["mypy-boto3-datasync (>=1.34.0,<1.35.0)"] -datazone = ["mypy-boto3-datazone (>=1.34.0,<1.35.0)"] -dax = ["mypy-boto3-dax (>=1.34.0,<1.35.0)"] -detective = ["mypy-boto3-detective (>=1.34.0,<1.35.0)"] -devicefarm = ["mypy-boto3-devicefarm (>=1.34.0,<1.35.0)"] -devops-guru = ["mypy-boto3-devops-guru (>=1.34.0,<1.35.0)"] -directconnect = ["mypy-boto3-directconnect (>=1.34.0,<1.35.0)"] -discovery = ["mypy-boto3-discovery (>=1.34.0,<1.35.0)"] -dlm = ["mypy-boto3-dlm (>=1.34.0,<1.35.0)"] -dms = ["mypy-boto3-dms (>=1.34.0,<1.35.0)"] -docdb = ["mypy-boto3-docdb (>=1.34.0,<1.35.0)"] -docdb-elastic = ["mypy-boto3-docdb-elastic (>=1.34.0,<1.35.0)"] -drs = ["mypy-boto3-drs (>=1.34.0,<1.35.0)"] -ds = ["mypy-boto3-ds (>=1.34.0,<1.35.0)"] -dynamodb = ["mypy-boto3-dynamodb (>=1.34.0,<1.35.0)"] -dynamodbstreams = ["mypy-boto3-dynamodbstreams (>=1.34.0,<1.35.0)"] -ebs = ["mypy-boto3-ebs (>=1.34.0,<1.35.0)"] -ec2 = ["mypy-boto3-ec2 (>=1.34.0,<1.35.0)"] -ec2-instance-connect = ["mypy-boto3-ec2-instance-connect (>=1.34.0,<1.35.0)"] -ecr = ["mypy-boto3-ecr (>=1.34.0,<1.35.0)"] -ecr-public = ["mypy-boto3-ecr-public (>=1.34.0,<1.35.0)"] -ecs = ["mypy-boto3-ecs (>=1.34.0,<1.35.0)"] -efs = ["mypy-boto3-efs (>=1.34.0,<1.35.0)"] -eks = ["mypy-boto3-eks (>=1.34.0,<1.35.0)"] -eks-auth = ["mypy-boto3-eks-auth (>=1.34.0,<1.35.0)"] -elastic-inference = ["mypy-boto3-elastic-inference (>=1.34.0,<1.35.0)"] -elasticache = ["mypy-boto3-elasticache (>=1.34.0,<1.35.0)"] -elasticbeanstalk = ["mypy-boto3-elasticbeanstalk (>=1.34.0,<1.35.0)"] -elastictranscoder = ["mypy-boto3-elastictranscoder (>=1.34.0,<1.35.0)"] -elb = ["mypy-boto3-elb (>=1.34.0,<1.35.0)"] -elbv2 = ["mypy-boto3-elbv2 (>=1.34.0,<1.35.0)"] -emr = ["mypy-boto3-emr (>=1.34.0,<1.35.0)"] -emr-containers = ["mypy-boto3-emr-containers (>=1.34.0,<1.35.0)"] -emr-serverless = ["mypy-boto3-emr-serverless (>=1.34.0,<1.35.0)"] -entityresolution = ["mypy-boto3-entityresolution (>=1.34.0,<1.35.0)"] -es = ["mypy-boto3-es (>=1.34.0,<1.35.0)"] -essential = ["mypy-boto3-cloudformation (>=1.34.0,<1.35.0)", "mypy-boto3-dynamodb (>=1.34.0,<1.35.0)", "mypy-boto3-ec2 (>=1.34.0,<1.35.0)", "mypy-boto3-lambda (>=1.34.0,<1.35.0)", "mypy-boto3-rds (>=1.34.0,<1.35.0)", "mypy-boto3-s3 (>=1.34.0,<1.35.0)", "mypy-boto3-sqs (>=1.34.0,<1.35.0)"] -events = ["mypy-boto3-events (>=1.34.0,<1.35.0)"] -evidently = ["mypy-boto3-evidently (>=1.34.0,<1.35.0)"] -finspace = ["mypy-boto3-finspace (>=1.34.0,<1.35.0)"] -finspace-data = ["mypy-boto3-finspace-data (>=1.34.0,<1.35.0)"] -firehose = ["mypy-boto3-firehose (>=1.34.0,<1.35.0)"] -fis = ["mypy-boto3-fis (>=1.34.0,<1.35.0)"] -fms = ["mypy-boto3-fms (>=1.34.0,<1.35.0)"] -forecast = ["mypy-boto3-forecast (>=1.34.0,<1.35.0)"] -forecastquery = ["mypy-boto3-forecastquery (>=1.34.0,<1.35.0)"] -frauddetector = ["mypy-boto3-frauddetector (>=1.34.0,<1.35.0)"] -freetier = ["mypy-boto3-freetier (>=1.34.0,<1.35.0)"] -fsx = ["mypy-boto3-fsx (>=1.34.0,<1.35.0)"] -gamelift = ["mypy-boto3-gamelift (>=1.34.0,<1.35.0)"] -glacier = ["mypy-boto3-glacier (>=1.34.0,<1.35.0)"] -globalaccelerator = ["mypy-boto3-globalaccelerator (>=1.34.0,<1.35.0)"] -glue = ["mypy-boto3-glue (>=1.34.0,<1.35.0)"] -grafana = ["mypy-boto3-grafana (>=1.34.0,<1.35.0)"] -greengrass = ["mypy-boto3-greengrass (>=1.34.0,<1.35.0)"] -greengrassv2 = ["mypy-boto3-greengrassv2 (>=1.34.0,<1.35.0)"] -groundstation = ["mypy-boto3-groundstation (>=1.34.0,<1.35.0)"] -guardduty = ["mypy-boto3-guardduty (>=1.34.0,<1.35.0)"] -health = ["mypy-boto3-health (>=1.34.0,<1.35.0)"] -healthlake = ["mypy-boto3-healthlake (>=1.34.0,<1.35.0)"] -honeycode = ["mypy-boto3-honeycode (>=1.34.0,<1.35.0)"] -iam = ["mypy-boto3-iam (>=1.34.0,<1.35.0)"] -identitystore = ["mypy-boto3-identitystore (>=1.34.0,<1.35.0)"] -imagebuilder = ["mypy-boto3-imagebuilder (>=1.34.0,<1.35.0)"] -importexport = ["mypy-boto3-importexport (>=1.34.0,<1.35.0)"] -inspector = ["mypy-boto3-inspector (>=1.34.0,<1.35.0)"] -inspector-scan = ["mypy-boto3-inspector-scan (>=1.34.0,<1.35.0)"] -inspector2 = ["mypy-boto3-inspector2 (>=1.34.0,<1.35.0)"] -internetmonitor = ["mypy-boto3-internetmonitor (>=1.34.0,<1.35.0)"] -iot = ["mypy-boto3-iot (>=1.34.0,<1.35.0)"] -iot-data = ["mypy-boto3-iot-data (>=1.34.0,<1.35.0)"] -iot-jobs-data = ["mypy-boto3-iot-jobs-data (>=1.34.0,<1.35.0)"] -iot-roborunner = ["mypy-boto3-iot-roborunner (>=1.34.0,<1.35.0)"] -iot1click-devices = ["mypy-boto3-iot1click-devices (>=1.34.0,<1.35.0)"] -iot1click-projects = ["mypy-boto3-iot1click-projects (>=1.34.0,<1.35.0)"] -iotanalytics = ["mypy-boto3-iotanalytics (>=1.34.0,<1.35.0)"] -iotdeviceadvisor = ["mypy-boto3-iotdeviceadvisor (>=1.34.0,<1.35.0)"] -iotevents = ["mypy-boto3-iotevents (>=1.34.0,<1.35.0)"] -iotevents-data = ["mypy-boto3-iotevents-data (>=1.34.0,<1.35.0)"] -iotfleethub = ["mypy-boto3-iotfleethub (>=1.34.0,<1.35.0)"] -iotfleetwise = ["mypy-boto3-iotfleetwise (>=1.34.0,<1.35.0)"] -iotsecuretunneling = ["mypy-boto3-iotsecuretunneling (>=1.34.0,<1.35.0)"] -iotsitewise = ["mypy-boto3-iotsitewise (>=1.34.0,<1.35.0)"] -iotthingsgraph = ["mypy-boto3-iotthingsgraph (>=1.34.0,<1.35.0)"] -iottwinmaker = ["mypy-boto3-iottwinmaker (>=1.34.0,<1.35.0)"] -iotwireless = ["mypy-boto3-iotwireless (>=1.34.0,<1.35.0)"] -ivs = ["mypy-boto3-ivs (>=1.34.0,<1.35.0)"] -ivs-realtime = ["mypy-boto3-ivs-realtime (>=1.34.0,<1.35.0)"] -ivschat = ["mypy-boto3-ivschat (>=1.34.0,<1.35.0)"] -kafka = ["mypy-boto3-kafka (>=1.34.0,<1.35.0)"] -kafkaconnect = ["mypy-boto3-kafkaconnect (>=1.34.0,<1.35.0)"] -kendra = ["mypy-boto3-kendra (>=1.34.0,<1.35.0)"] -kendra-ranking = ["mypy-boto3-kendra-ranking (>=1.34.0,<1.35.0)"] -keyspaces = ["mypy-boto3-keyspaces (>=1.34.0,<1.35.0)"] -kinesis = ["mypy-boto3-kinesis (>=1.34.0,<1.35.0)"] -kinesis-video-archived-media = ["mypy-boto3-kinesis-video-archived-media (>=1.34.0,<1.35.0)"] -kinesis-video-media = ["mypy-boto3-kinesis-video-media (>=1.34.0,<1.35.0)"] -kinesis-video-signaling = ["mypy-boto3-kinesis-video-signaling (>=1.34.0,<1.35.0)"] -kinesis-video-webrtc-storage = ["mypy-boto3-kinesis-video-webrtc-storage (>=1.34.0,<1.35.0)"] -kinesisanalytics = ["mypy-boto3-kinesisanalytics (>=1.34.0,<1.35.0)"] -kinesisanalyticsv2 = ["mypy-boto3-kinesisanalyticsv2 (>=1.34.0,<1.35.0)"] -kinesisvideo = ["mypy-boto3-kinesisvideo (>=1.34.0,<1.35.0)"] -kms = ["mypy-boto3-kms (>=1.34.0,<1.35.0)"] -lakeformation = ["mypy-boto3-lakeformation (>=1.34.0,<1.35.0)"] -lambda = ["mypy-boto3-lambda (>=1.34.0,<1.35.0)"] -launch-wizard = ["mypy-boto3-launch-wizard (>=1.34.0,<1.35.0)"] -lex-models = ["mypy-boto3-lex-models (>=1.34.0,<1.35.0)"] -lex-runtime = ["mypy-boto3-lex-runtime (>=1.34.0,<1.35.0)"] -lexv2-models = ["mypy-boto3-lexv2-models (>=1.34.0,<1.35.0)"] -lexv2-runtime = ["mypy-boto3-lexv2-runtime (>=1.34.0,<1.35.0)"] -license-manager = ["mypy-boto3-license-manager (>=1.34.0,<1.35.0)"] -license-manager-linux-subscriptions = ["mypy-boto3-license-manager-linux-subscriptions (>=1.34.0,<1.35.0)"] -license-manager-user-subscriptions = ["mypy-boto3-license-manager-user-subscriptions (>=1.34.0,<1.35.0)"] -lightsail = ["mypy-boto3-lightsail (>=1.34.0,<1.35.0)"] -location = ["mypy-boto3-location (>=1.34.0,<1.35.0)"] -logs = ["mypy-boto3-logs (>=1.34.0,<1.35.0)"] -lookoutequipment = ["mypy-boto3-lookoutequipment (>=1.34.0,<1.35.0)"] -lookoutmetrics = ["mypy-boto3-lookoutmetrics (>=1.34.0,<1.35.0)"] -lookoutvision = ["mypy-boto3-lookoutvision (>=1.34.0,<1.35.0)"] -m2 = ["mypy-boto3-m2 (>=1.34.0,<1.35.0)"] -machinelearning = ["mypy-boto3-machinelearning (>=1.34.0,<1.35.0)"] -macie2 = ["mypy-boto3-macie2 (>=1.34.0,<1.35.0)"] -managedblockchain = ["mypy-boto3-managedblockchain (>=1.34.0,<1.35.0)"] -managedblockchain-query = ["mypy-boto3-managedblockchain-query (>=1.34.0,<1.35.0)"] -marketplace-agreement = ["mypy-boto3-marketplace-agreement (>=1.34.0,<1.35.0)"] -marketplace-catalog = ["mypy-boto3-marketplace-catalog (>=1.34.0,<1.35.0)"] -marketplace-deployment = ["mypy-boto3-marketplace-deployment (>=1.34.0,<1.35.0)"] -marketplace-entitlement = ["mypy-boto3-marketplace-entitlement (>=1.34.0,<1.35.0)"] -marketplacecommerceanalytics = ["mypy-boto3-marketplacecommerceanalytics (>=1.34.0,<1.35.0)"] -mediaconnect = ["mypy-boto3-mediaconnect (>=1.34.0,<1.35.0)"] -mediaconvert = ["mypy-boto3-mediaconvert (>=1.34.0,<1.35.0)"] -medialive = ["mypy-boto3-medialive (>=1.34.0,<1.35.0)"] -mediapackage = ["mypy-boto3-mediapackage (>=1.34.0,<1.35.0)"] -mediapackage-vod = ["mypy-boto3-mediapackage-vod (>=1.34.0,<1.35.0)"] -mediapackagev2 = ["mypy-boto3-mediapackagev2 (>=1.34.0,<1.35.0)"] -mediastore = ["mypy-boto3-mediastore (>=1.34.0,<1.35.0)"] -mediastore-data = ["mypy-boto3-mediastore-data (>=1.34.0,<1.35.0)"] -mediatailor = ["mypy-boto3-mediatailor (>=1.34.0,<1.35.0)"] -medical-imaging = ["mypy-boto3-medical-imaging (>=1.34.0,<1.35.0)"] -memorydb = ["mypy-boto3-memorydb (>=1.34.0,<1.35.0)"] -meteringmarketplace = ["mypy-boto3-meteringmarketplace (>=1.34.0,<1.35.0)"] -mgh = ["mypy-boto3-mgh (>=1.34.0,<1.35.0)"] -mgn = ["mypy-boto3-mgn (>=1.34.0,<1.35.0)"] -migration-hub-refactor-spaces = ["mypy-boto3-migration-hub-refactor-spaces (>=1.34.0,<1.35.0)"] -migrationhub-config = ["mypy-boto3-migrationhub-config (>=1.34.0,<1.35.0)"] -migrationhuborchestrator = ["mypy-boto3-migrationhuborchestrator (>=1.34.0,<1.35.0)"] -migrationhubstrategy = ["mypy-boto3-migrationhubstrategy (>=1.34.0,<1.35.0)"] -mobile = ["mypy-boto3-mobile (>=1.34.0,<1.35.0)"] -mq = ["mypy-boto3-mq (>=1.34.0,<1.35.0)"] -mturk = ["mypy-boto3-mturk (>=1.34.0,<1.35.0)"] -mwaa = ["mypy-boto3-mwaa (>=1.34.0,<1.35.0)"] -neptune = ["mypy-boto3-neptune (>=1.34.0,<1.35.0)"] -neptune-graph = ["mypy-boto3-neptune-graph (>=1.34.0,<1.35.0)"] -neptunedata = ["mypy-boto3-neptunedata (>=1.34.0,<1.35.0)"] -network-firewall = ["mypy-boto3-network-firewall (>=1.34.0,<1.35.0)"] -networkmanager = ["mypy-boto3-networkmanager (>=1.34.0,<1.35.0)"] -networkmonitor = ["mypy-boto3-networkmonitor (>=1.34.0,<1.35.0)"] -nimble = ["mypy-boto3-nimble (>=1.34.0,<1.35.0)"] -oam = ["mypy-boto3-oam (>=1.34.0,<1.35.0)"] -omics = ["mypy-boto3-omics (>=1.34.0,<1.35.0)"] -opensearch = ["mypy-boto3-opensearch (>=1.34.0,<1.35.0)"] -opensearchserverless = ["mypy-boto3-opensearchserverless (>=1.34.0,<1.35.0)"] -opsworks = ["mypy-boto3-opsworks (>=1.34.0,<1.35.0)"] -opsworkscm = ["mypy-boto3-opsworkscm (>=1.34.0,<1.35.0)"] -organizations = ["mypy-boto3-organizations (>=1.34.0,<1.35.0)"] -osis = ["mypy-boto3-osis (>=1.34.0,<1.35.0)"] -outposts = ["mypy-boto3-outposts (>=1.34.0,<1.35.0)"] -panorama = ["mypy-boto3-panorama (>=1.34.0,<1.35.0)"] -payment-cryptography = ["mypy-boto3-payment-cryptography (>=1.34.0,<1.35.0)"] -payment-cryptography-data = ["mypy-boto3-payment-cryptography-data (>=1.34.0,<1.35.0)"] -pca-connector-ad = ["mypy-boto3-pca-connector-ad (>=1.34.0,<1.35.0)"] -personalize = ["mypy-boto3-personalize (>=1.34.0,<1.35.0)"] -personalize-events = ["mypy-boto3-personalize-events (>=1.34.0,<1.35.0)"] -personalize-runtime = ["mypy-boto3-personalize-runtime (>=1.34.0,<1.35.0)"] -pi = ["mypy-boto3-pi (>=1.34.0,<1.35.0)"] -pinpoint = ["mypy-boto3-pinpoint (>=1.34.0,<1.35.0)"] -pinpoint-email = ["mypy-boto3-pinpoint-email (>=1.34.0,<1.35.0)"] -pinpoint-sms-voice = ["mypy-boto3-pinpoint-sms-voice (>=1.34.0,<1.35.0)"] -pinpoint-sms-voice-v2 = ["mypy-boto3-pinpoint-sms-voice-v2 (>=1.34.0,<1.35.0)"] -pipes = ["mypy-boto3-pipes (>=1.34.0,<1.35.0)"] -polly = ["mypy-boto3-polly (>=1.34.0,<1.35.0)"] -pricing = ["mypy-boto3-pricing (>=1.34.0,<1.35.0)"] -privatenetworks = ["mypy-boto3-privatenetworks (>=1.34.0,<1.35.0)"] -proton = ["mypy-boto3-proton (>=1.34.0,<1.35.0)"] -qbusiness = ["mypy-boto3-qbusiness (>=1.34.0,<1.35.0)"] -qconnect = ["mypy-boto3-qconnect (>=1.34.0,<1.35.0)"] -qldb = ["mypy-boto3-qldb (>=1.34.0,<1.35.0)"] -qldb-session = ["mypy-boto3-qldb-session (>=1.34.0,<1.35.0)"] -quicksight = ["mypy-boto3-quicksight (>=1.34.0,<1.35.0)"] -ram = ["mypy-boto3-ram (>=1.34.0,<1.35.0)"] -rbin = ["mypy-boto3-rbin (>=1.34.0,<1.35.0)"] -rds = ["mypy-boto3-rds (>=1.34.0,<1.35.0)"] -rds-data = ["mypy-boto3-rds-data (>=1.34.0,<1.35.0)"] -redshift = ["mypy-boto3-redshift (>=1.34.0,<1.35.0)"] -redshift-data = ["mypy-boto3-redshift-data (>=1.34.0,<1.35.0)"] -redshift-serverless = ["mypy-boto3-redshift-serverless (>=1.34.0,<1.35.0)"] -rekognition = ["mypy-boto3-rekognition (>=1.34.0,<1.35.0)"] -repostspace = ["mypy-boto3-repostspace (>=1.34.0,<1.35.0)"] -resiliencehub = ["mypy-boto3-resiliencehub (>=1.34.0,<1.35.0)"] -resource-explorer-2 = ["mypy-boto3-resource-explorer-2 (>=1.34.0,<1.35.0)"] -resource-groups = ["mypy-boto3-resource-groups (>=1.34.0,<1.35.0)"] -resourcegroupstaggingapi = ["mypy-boto3-resourcegroupstaggingapi (>=1.34.0,<1.35.0)"] -robomaker = ["mypy-boto3-robomaker (>=1.34.0,<1.35.0)"] -rolesanywhere = ["mypy-boto3-rolesanywhere (>=1.34.0,<1.35.0)"] -route53 = ["mypy-boto3-route53 (>=1.34.0,<1.35.0)"] -route53-recovery-cluster = ["mypy-boto3-route53-recovery-cluster (>=1.34.0,<1.35.0)"] -route53-recovery-control-config = ["mypy-boto3-route53-recovery-control-config (>=1.34.0,<1.35.0)"] -route53-recovery-readiness = ["mypy-boto3-route53-recovery-readiness (>=1.34.0,<1.35.0)"] -route53domains = ["mypy-boto3-route53domains (>=1.34.0,<1.35.0)"] -route53resolver = ["mypy-boto3-route53resolver (>=1.34.0,<1.35.0)"] -rum = ["mypy-boto3-rum (>=1.34.0,<1.35.0)"] -s3 = ["mypy-boto3-s3 (>=1.34.0,<1.35.0)"] -s3control = ["mypy-boto3-s3control (>=1.34.0,<1.35.0)"] -s3outposts = ["mypy-boto3-s3outposts (>=1.34.0,<1.35.0)"] -sagemaker = ["mypy-boto3-sagemaker (>=1.34.0,<1.35.0)"] -sagemaker-a2i-runtime = ["mypy-boto3-sagemaker-a2i-runtime (>=1.34.0,<1.35.0)"] -sagemaker-edge = ["mypy-boto3-sagemaker-edge (>=1.34.0,<1.35.0)"] -sagemaker-featurestore-runtime = ["mypy-boto3-sagemaker-featurestore-runtime (>=1.34.0,<1.35.0)"] -sagemaker-geospatial = ["mypy-boto3-sagemaker-geospatial (>=1.34.0,<1.35.0)"] -sagemaker-metrics = ["mypy-boto3-sagemaker-metrics (>=1.34.0,<1.35.0)"] -sagemaker-runtime = ["mypy-boto3-sagemaker-runtime (>=1.34.0,<1.35.0)"] -savingsplans = ["mypy-boto3-savingsplans (>=1.34.0,<1.35.0)"] -scheduler = ["mypy-boto3-scheduler (>=1.34.0,<1.35.0)"] -schemas = ["mypy-boto3-schemas (>=1.34.0,<1.35.0)"] -sdb = ["mypy-boto3-sdb (>=1.34.0,<1.35.0)"] -secretsmanager = ["mypy-boto3-secretsmanager (>=1.34.0,<1.35.0)"] -securityhub = ["mypy-boto3-securityhub (>=1.34.0,<1.35.0)"] -securitylake = ["mypy-boto3-securitylake (>=1.34.0,<1.35.0)"] -serverlessrepo = ["mypy-boto3-serverlessrepo (>=1.34.0,<1.35.0)"] -service-quotas = ["mypy-boto3-service-quotas (>=1.34.0,<1.35.0)"] -servicecatalog = ["mypy-boto3-servicecatalog (>=1.34.0,<1.35.0)"] -servicecatalog-appregistry = ["mypy-boto3-servicecatalog-appregistry (>=1.34.0,<1.35.0)"] -servicediscovery = ["mypy-boto3-servicediscovery (>=1.34.0,<1.35.0)"] -ses = ["mypy-boto3-ses (>=1.34.0,<1.35.0)"] -sesv2 = ["mypy-boto3-sesv2 (>=1.34.0,<1.35.0)"] -shield = ["mypy-boto3-shield (>=1.34.0,<1.35.0)"] -signer = ["mypy-boto3-signer (>=1.34.0,<1.35.0)"] -simspaceweaver = ["mypy-boto3-simspaceweaver (>=1.34.0,<1.35.0)"] -sms = ["mypy-boto3-sms (>=1.34.0,<1.35.0)"] -sms-voice = ["mypy-boto3-sms-voice (>=1.34.0,<1.35.0)"] -snow-device-management = ["mypy-boto3-snow-device-management (>=1.34.0,<1.35.0)"] -snowball = ["mypy-boto3-snowball (>=1.34.0,<1.35.0)"] -sns = ["mypy-boto3-sns (>=1.34.0,<1.35.0)"] -sqs = ["mypy-boto3-sqs (>=1.34.0,<1.35.0)"] -ssm = ["mypy-boto3-ssm (>=1.34.0,<1.35.0)"] -ssm-contacts = ["mypy-boto3-ssm-contacts (>=1.34.0,<1.35.0)"] -ssm-incidents = ["mypy-boto3-ssm-incidents (>=1.34.0,<1.35.0)"] -ssm-sap = ["mypy-boto3-ssm-sap (>=1.34.0,<1.35.0)"] -sso = ["mypy-boto3-sso (>=1.34.0,<1.35.0)"] -sso-admin = ["mypy-boto3-sso-admin (>=1.34.0,<1.35.0)"] -sso-oidc = ["mypy-boto3-sso-oidc (>=1.34.0,<1.35.0)"] -stepfunctions = ["mypy-boto3-stepfunctions (>=1.34.0,<1.35.0)"] -storagegateway = ["mypy-boto3-storagegateway (>=1.34.0,<1.35.0)"] -sts = ["mypy-boto3-sts (>=1.34.0,<1.35.0)"] -supplychain = ["mypy-boto3-supplychain (>=1.34.0,<1.35.0)"] -support = ["mypy-boto3-support (>=1.34.0,<1.35.0)"] -support-app = ["mypy-boto3-support-app (>=1.34.0,<1.35.0)"] -swf = ["mypy-boto3-swf (>=1.34.0,<1.35.0)"] -synthetics = ["mypy-boto3-synthetics (>=1.34.0,<1.35.0)"] -textract = ["mypy-boto3-textract (>=1.34.0,<1.35.0)"] -timestream-query = ["mypy-boto3-timestream-query (>=1.34.0,<1.35.0)"] -timestream-write = ["mypy-boto3-timestream-write (>=1.34.0,<1.35.0)"] -tnb = ["mypy-boto3-tnb (>=1.34.0,<1.35.0)"] -transcribe = ["mypy-boto3-transcribe (>=1.34.0,<1.35.0)"] -transfer = ["mypy-boto3-transfer (>=1.34.0,<1.35.0)"] -translate = ["mypy-boto3-translate (>=1.34.0,<1.35.0)"] -trustedadvisor = ["mypy-boto3-trustedadvisor (>=1.34.0,<1.35.0)"] -verifiedpermissions = ["mypy-boto3-verifiedpermissions (>=1.34.0,<1.35.0)"] -voice-id = ["mypy-boto3-voice-id (>=1.34.0,<1.35.0)"] -vpc-lattice = ["mypy-boto3-vpc-lattice (>=1.34.0,<1.35.0)"] -waf = ["mypy-boto3-waf (>=1.34.0,<1.35.0)"] -waf-regional = ["mypy-boto3-waf-regional (>=1.34.0,<1.35.0)"] -wafv2 = ["mypy-boto3-wafv2 (>=1.34.0,<1.35.0)"] -wellarchitected = ["mypy-boto3-wellarchitected (>=1.34.0,<1.35.0)"] -wisdom = ["mypy-boto3-wisdom (>=1.34.0,<1.35.0)"] -workdocs = ["mypy-boto3-workdocs (>=1.34.0,<1.35.0)"] -worklink = ["mypy-boto3-worklink (>=1.34.0,<1.35.0)"] -workmail = ["mypy-boto3-workmail (>=1.34.0,<1.35.0)"] -workmailmessageflow = ["mypy-boto3-workmailmessageflow (>=1.34.0,<1.35.0)"] -workspaces = ["mypy-boto3-workspaces (>=1.34.0,<1.35.0)"] -workspaces-thin-client = ["mypy-boto3-workspaces-thin-client (>=1.34.0,<1.35.0)"] -workspaces-web = ["mypy-boto3-workspaces-web (>=1.34.0,<1.35.0)"] -xray = ["mypy-boto3-xray (>=1.34.0,<1.35.0)"] - [[package]] name = "botocore" -version = "1.31.47" +version = "1.35.81" description = "Low-level, data-driven core of boto 3." optional = false -python-versions = ">= 3.7" +python-versions = ">=3.8" files = [ - {file = "botocore-1.31.47-py3-none-any.whl", hash = "sha256:6a60f9601270458102529b17fdcba5551b918f9eedc32bbc2f467e63edfb2662"}, - {file = "botocore-1.31.47.tar.gz", hash = "sha256:a0ba5629eb17a37bf449bccda9df6ae652d5755f73145519d5eb244f6963b31b"}, + {file = "botocore-1.35.81-py3-none-any.whl", hash = "sha256:a7b13bbd959bf2d6f38f681676aab408be01974c46802ab997617b51399239f7"}, + {file = "botocore-1.35.81.tar.gz", hash = "sha256:564c2478e50179e0b766e6a87e5e0cdd35e1bc37eb375c1cf15511f5dd13600d"}, ] [package.dependencies] jmespath = ">=0.7.1,<2.0.0" python-dateutil = ">=2.1,<3.0.0" -urllib3 = ">=1.25.4,<1.27" +urllib3 = [ + {version = ">=1.25.4,<1.27", markers = "python_version < \"3.10\""}, + {version = ">=1.25.4,<2.2.0 || >2.2.0,<3", markers = "python_version >= \"3.10\""}, +] [package.extras] -crt = ["awscrt (==0.16.26)"] +crt = ["awscrt (==0.22.0)"] [[package]] name = "botocore-stubs" -version = "1.34.43" +version = "1.35.81" description = "Type annotations and code completion for botocore" optional = false -python-versions = ">=3.8,<4.0" +python-versions = ">=3.8" files = [ - {file = "botocore_stubs-1.34.43-py3-none-any.whl", hash = "sha256:6da6730071a83a57200d71bab6b5c2d0033adec5bbb59396113e498de9136aed"}, - {file = "botocore_stubs-1.34.43.tar.gz", hash = "sha256:c30aded65547eb339ea4438e7662c4111aee09f360132202bd09e3130f7be956"}, + {file = "botocore_stubs-1.35.81-py3-none-any.whl", hash = "sha256:818e1ec37d6a97e1aa7955f85a45c6b5d7e4d7599b00658529e0f070330791d7"}, + {file = "botocore_stubs-1.35.81.tar.gz", hash = "sha256:d3759683a7834053d074d75fab12fb09fdb6ba73e491db37a3ff97ef3dff5d12"}, ] [package.dependencies] @@ -582,74 +146,89 @@ botocore = ["botocore"] [[package]] name = "certifi" -version = "2023.7.22" +version = "2024.12.14" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, - {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, + {file = "certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56"}, + {file = "certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db"}, ] [[package]] name = "cffi" -version = "1.16.0" +version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" files = [ - {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, - {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, - {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, - {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, - {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, - {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, - {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, - {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, - {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, - {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, - {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, - {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, - {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, - {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, - {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, - {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, - {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, - {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, - {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, - {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, - {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, - {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, - {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, - {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, - {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, - {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, - {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, + {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, + {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, + {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, + {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, + {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, + {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, + {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, + {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, + {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, + {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, + {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, + {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, + {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, + {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, ] [package.dependencies] @@ -657,86 +236,116 @@ pycparser = "*" [[package]] name = "charset-normalizer" -version = "3.2.0" +version = "3.4.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7.0" files = [ - {file = "charset-normalizer-3.2.0.tar.gz", hash = "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-win32.whl", hash = "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96"}, - {file = "charset_normalizer-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-win32.whl", hash = "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1"}, - {file = "charset_normalizer-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-win32.whl", hash = "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1"}, - {file = "charset_normalizer-3.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-win32.whl", hash = "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706"}, - {file = "charset_normalizer-3.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-win32.whl", hash = "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9"}, - {file = "charset_normalizer-3.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80"}, - {file = "charset_normalizer-3.2.0-py3-none-any.whl", hash = "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc"}, + {file = "charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99"}, + {file = "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"}, + {file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"}, + {file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-win32.whl", hash = "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149"}, + {file = "charset_normalizer-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-win32.whl", hash = "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613"}, + {file = "charset_normalizer-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-win32.whl", hash = "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2"}, + {file = "charset_normalizer-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca"}, + {file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"}, + {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"}, ] [[package]] @@ -766,13 +375,13 @@ files = [ [[package]] name = "exceptiongroup" -version = "1.2.1" +version = "1.2.2" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"}, - {file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"}, + {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, + {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, ] [package.extras] @@ -791,31 +400,31 @@ files = [ [[package]] name = "idna" -version = "3.4" +version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" files = [ - {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, - {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, + {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, + {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, ] +[package.extras] +all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] + [[package]] name = "isort" -version = "5.12.0" +version = "5.13.2" description = "A Python utility / library to sort Python imports." optional = false python-versions = ">=3.8.0" files = [ - {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"}, - {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"}, + {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, + {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, ] [package.extras] -colors = ["colorama (>=0.4.3)"] -pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] -plugins = ["setuptools"] -requirements-deprecated-finder = ["pip-api", "pipreqs"] +colors = ["colorama (>=0.4.6)"] [[package]] name = "jmespath" @@ -865,47 +474,53 @@ files = [ [[package]] name = "mypy" -version = "1.8.0" +version = "1.13.0" description = "Optional static typing for Python" optional = false python-versions = ">=3.8" files = [ - {file = "mypy-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:485a8942f671120f76afffff70f259e1cd0f0cfe08f81c05d8816d958d4577d3"}, - {file = "mypy-1.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:df9824ac11deaf007443e7ed2a4a26bebff98d2bc43c6da21b2b64185da011c4"}, - {file = "mypy-1.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2afecd6354bbfb6e0160f4e4ad9ba6e4e003b767dd80d85516e71f2e955ab50d"}, - {file = "mypy-1.8.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8963b83d53ee733a6e4196954502b33567ad07dfd74851f32be18eb932fb1cb9"}, - {file = "mypy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:e46f44b54ebddbeedbd3d5b289a893219065ef805d95094d16a0af6630f5d410"}, - {file = "mypy-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:855fe27b80375e5c5878492f0729540db47b186509c98dae341254c8f45f42ae"}, - {file = "mypy-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4c886c6cce2d070bd7df4ec4a05a13ee20c0aa60cb587e8d1265b6c03cf91da3"}, - {file = "mypy-1.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d19c413b3c07cbecf1f991e2221746b0d2a9410b59cb3f4fb9557f0365a1a817"}, - {file = "mypy-1.8.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9261ed810972061388918c83c3f5cd46079d875026ba97380f3e3978a72f503d"}, - {file = "mypy-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:51720c776d148bad2372ca21ca29256ed483aa9a4cdefefcef49006dff2a6835"}, - {file = "mypy-1.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:52825b01f5c4c1c4eb0db253ec09c7aa17e1a7304d247c48b6f3599ef40db8bd"}, - {file = "mypy-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f5ac9a4eeb1ec0f1ccdc6f326bcdb464de5f80eb07fb38b5ddd7b0de6bc61e55"}, - {file = "mypy-1.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afe3fe972c645b4632c563d3f3eff1cdca2fa058f730df2b93a35e3b0c538218"}, - {file = "mypy-1.8.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:42c6680d256ab35637ef88891c6bd02514ccb7e1122133ac96055ff458f93fc3"}, - {file = "mypy-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:720a5ca70e136b675af3af63db533c1c8c9181314d207568bbe79051f122669e"}, - {file = "mypy-1.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:028cf9f2cae89e202d7b6593cd98db6759379f17a319b5faf4f9978d7084cdc6"}, - {file = "mypy-1.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4e6d97288757e1ddba10dd9549ac27982e3e74a49d8d0179fc14d4365c7add66"}, - {file = "mypy-1.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f1478736fcebb90f97e40aff11a5f253af890c845ee0c850fe80aa060a267c6"}, - {file = "mypy-1.8.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42419861b43e6962a649068a61f4a4839205a3ef525b858377a960b9e2de6e0d"}, - {file = "mypy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:2b5b6c721bd4aabaadead3a5e6fa85c11c6c795e0c81a7215776ef8afc66de02"}, - {file = "mypy-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5c1538c38584029352878a0466f03a8ee7547d7bd9f641f57a0f3017a7c905b8"}, - {file = "mypy-1.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ef4be7baf08a203170f29e89d79064463b7fc7a0908b9d0d5114e8009c3a259"}, - {file = "mypy-1.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7178def594014aa6c35a8ff411cf37d682f428b3b5617ca79029d8ae72f5402b"}, - {file = "mypy-1.8.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ab3c84fa13c04aeeeabb2a7f67a25ef5d77ac9d6486ff33ded762ef353aa5592"}, - {file = "mypy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:99b00bc72855812a60d253420d8a2eae839b0afa4938f09f4d2aa9bb4654263a"}, - {file = "mypy-1.8.0-py3-none-any.whl", hash = "sha256:538fd81bb5e430cc1381a443971c0475582ff9f434c16cd46d2c66763ce85d9d"}, - {file = "mypy-1.8.0.tar.gz", hash = "sha256:6ff8b244d7085a0b425b56d327b480c3b29cafbd2eff27316a004f9a7391ae07"}, + {file = "mypy-1.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6607e0f1dd1fb7f0aca14d936d13fd19eba5e17e1cd2a14f808fa5f8f6d8f60a"}, + {file = "mypy-1.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8a21be69bd26fa81b1f80a61ee7ab05b076c674d9b18fb56239d72e21d9f4c80"}, + {file = "mypy-1.13.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7b2353a44d2179846a096e25691d54d59904559f4232519d420d64da6828a3a7"}, + {file = "mypy-1.13.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0730d1c6a2739d4511dc4253f8274cdd140c55c32dfb0a4cf8b7a43f40abfa6f"}, + {file = "mypy-1.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:c5fc54dbb712ff5e5a0fca797e6e0aa25726c7e72c6a5850cfd2adbc1eb0a372"}, + {file = "mypy-1.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:581665e6f3a8a9078f28d5502f4c334c0c8d802ef55ea0e7276a6e409bc0d82d"}, + {file = "mypy-1.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3ddb5b9bf82e05cc9a627e84707b528e5c7caaa1c55c69e175abb15a761cec2d"}, + {file = "mypy-1.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20c7ee0bc0d5a9595c46f38beb04201f2620065a93755704e141fcac9f59db2b"}, + {file = "mypy-1.13.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3790ded76f0b34bc9c8ba4def8f919dd6a46db0f5a6610fb994fe8efdd447f73"}, + {file = "mypy-1.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:51f869f4b6b538229c1d1bcc1dd7d119817206e2bc54e8e374b3dfa202defcca"}, + {file = "mypy-1.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5c7051a3461ae84dfb5dd15eff5094640c61c5f22257c8b766794e6dd85e72d5"}, + {file = "mypy-1.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:39bb21c69a5d6342f4ce526e4584bc5c197fd20a60d14a8624d8743fffb9472e"}, + {file = "mypy-1.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:164f28cb9d6367439031f4c81e84d3ccaa1e19232d9d05d37cb0bd880d3f93c2"}, + {file = "mypy-1.13.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a4c1bfcdbce96ff5d96fc9b08e3831acb30dc44ab02671eca5953eadad07d6d0"}, + {file = "mypy-1.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:a0affb3a79a256b4183ba09811e3577c5163ed06685e4d4b46429a271ba174d2"}, + {file = "mypy-1.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a7b44178c9760ce1a43f544e595d35ed61ac2c3de306599fa59b38a6048e1aa7"}, + {file = "mypy-1.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5d5092efb8516d08440e36626f0153b5006d4088c1d663d88bf79625af3d1d62"}, + {file = "mypy-1.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de2904956dac40ced10931ac967ae63c5089bd498542194b436eb097a9f77bc8"}, + {file = "mypy-1.13.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:7bfd8836970d33c2105562650656b6846149374dc8ed77d98424b40b09340ba7"}, + {file = "mypy-1.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:9f73dba9ec77acb86457a8fc04b5239822df0c14a082564737833d2963677dbc"}, + {file = "mypy-1.13.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:100fac22ce82925f676a734af0db922ecfea991e1d7ec0ceb1e115ebe501301a"}, + {file = "mypy-1.13.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7bcb0bb7f42a978bb323a7c88f1081d1b5dee77ca86f4100735a6f541299d8fb"}, + {file = "mypy-1.13.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bde31fc887c213e223bbfc34328070996061b0833b0a4cfec53745ed61f3519b"}, + {file = "mypy-1.13.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:07de989f89786f62b937851295ed62e51774722e5444a27cecca993fc3f9cd74"}, + {file = "mypy-1.13.0-cp38-cp38-win_amd64.whl", hash = "sha256:4bde84334fbe19bad704b3f5b78c4abd35ff1026f8ba72b29de70dda0916beb6"}, + {file = "mypy-1.13.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0246bcb1b5de7f08f2826451abd947bf656945209b140d16ed317f65a17dc7dc"}, + {file = "mypy-1.13.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7f5b7deae912cf8b77e990b9280f170381fdfbddf61b4ef80927edd813163732"}, + {file = "mypy-1.13.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7029881ec6ffb8bc233a4fa364736789582c738217b133f1b55967115288a2bc"}, + {file = "mypy-1.13.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3e38b980e5681f28f033f3be86b099a247b13c491f14bb8b1e1e134d23bb599d"}, + {file = "mypy-1.13.0-cp39-cp39-win_amd64.whl", hash = "sha256:a6789be98a2017c912ae6ccb77ea553bbaf13d27605d2ca20a76dfbced631b24"}, + {file = "mypy-1.13.0-py3-none-any.whl", hash = "sha256:9c250883f9fd81d212e0952c92dbfcc96fc237f4b7c92f56ac81fd48460b3e5a"}, + {file = "mypy-1.13.0.tar.gz", hash = "sha256:0291a61b6fbf3e6673e3405cfcc0e7650bebc7939659fdca2702958038bd835e"}, ] [package.dependencies] mypy-extensions = ">=1.0.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = ">=4.1.0" +typing-extensions = ">=4.6.0" [package.extras] dmypy = ["psutil (>=4.0)"] +faster-cache = ["orjson"] install-types = ["pip"] mypyc = ["setuptools (>=50)"] reports = ["lxml"] @@ -982,40 +597,41 @@ attrs = ">=19.2.0" [[package]] name = "packaging" -version = "23.1" +version = "24.2" description = "Core utilities for Python packages" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, - {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, + {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, + {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, ] [[package]] name = "pathspec" -version = "0.11.2" +version = "0.12.1" description = "Utility library for gitignore style pattern matching of file paths." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, - {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, + {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, + {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, ] [[package]] name = "platformdirs" -version = "3.10.0" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +version = "4.3.6" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"}, - {file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"}, + {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, + {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, ] [package.extras] -docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.11.2)"] [[package]] name = "py-fasta-validator" @@ -1040,17 +656,17 @@ files = [ [[package]] name = "pygments" -version = "2.16.1" +version = "2.18.0" description = "Pygments is a syntax highlighting package written in Python." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"}, - {file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"}, + {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, + {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, ] [package.extras] -plugins = ["importlib-metadata"] +windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pysocks" @@ -1066,13 +682,13 @@ files = [ [[package]] name = "python-dateutil" -version = "2.8.2" +version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ - {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, - {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, ] [package.dependencies] @@ -1080,13 +696,13 @@ six = ">=1.5" [[package]] name = "python-dotenv" -version = "1.0.0" +version = "1.0.1" description = "Read key-value pairs from a .env file and set them as environment variables" optional = false python-versions = ">=3.8" files = [ - {file = "python-dotenv-1.0.0.tar.gz", hash = "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba"}, - {file = "python_dotenv-1.0.0-py3-none-any.whl", hash = "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a"}, + {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, + {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, ] [package.extras] @@ -1094,73 +710,75 @@ cli = ["click (>=5.0)"] [[package]] name = "pyyaml" -version = "6.0.1" +version = "6.0.2" description = "YAML parser and emitter for Python" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, - {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, - {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, - {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, - {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, - {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, - {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, - {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, - {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, - {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, - {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, - {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, - {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, - {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, + {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, + {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, + {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, + {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, + {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, + {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, + {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, + {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, + {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, + {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, + {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, + {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, + {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, + {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, + {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, + {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, + {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, ] [[package]] name = "requests" -version = "2.32.2" +version = "2.32.3" description = "Python HTTP for Humans." optional = false python-versions = ">=3.8" files = [ - {file = "requests-2.32.2-py3-none-any.whl", hash = "sha256:fc06670dd0ed212426dfeb94fc1b983d917c4f9847c863f313c9dfaaffb7c23c"}, - {file = "requests-2.32.2.tar.gz", hash = "sha256:dd951ff5ecf3e3b3aa26b40703ba77495dab41da839ae72ef3c8e5d8e2433289"}, + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, ] [package.dependencies] @@ -1175,82 +793,83 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "rich" -version = "13.5.2" +version = "13.9.4" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" optional = false -python-versions = ">=3.7.0" +python-versions = ">=3.8.0" files = [ - {file = "rich-13.5.2-py3-none-any.whl", hash = "sha256:146a90b3b6b47cac4a73c12866a499e9817426423f57c5a66949c086191a8808"}, - {file = "rich-13.5.2.tar.gz", hash = "sha256:fb9d6c0a0f643c99eed3875b5377a184132ba9be4d61516a55273d3554d75a39"}, + {file = "rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90"}, + {file = "rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098"}, ] [package.dependencies] markdown-it-py = ">=2.2.0" pygments = ">=2.13.0,<3.0.0" +typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.11\""} [package.extras] jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "s3transfer" -version = "0.6.2" +version = "0.10.4" description = "An Amazon S3 Transfer Manager" optional = false -python-versions = ">= 3.7" +python-versions = ">=3.8" files = [ - {file = "s3transfer-0.6.2-py3-none-any.whl", hash = "sha256:b014be3a8a2aab98cfe1abc7229cc5a9a0cf05eb9c1f2b86b230fd8df3f78084"}, - {file = "s3transfer-0.6.2.tar.gz", hash = "sha256:cab66d3380cca3e70939ef2255d01cd8aece6a4907a9528740f668c4b0611861"}, + {file = "s3transfer-0.10.4-py3-none-any.whl", hash = "sha256:244a76a24355363a68164241438de1b72f8781664920260c48465896b712a41e"}, + {file = "s3transfer-0.10.4.tar.gz", hash = "sha256:29edc09801743c21eb5ecbc617a152df41d3c287f67b615f73e5f750583666a7"}, ] [package.dependencies] -botocore = ">=1.12.36,<2.0a.0" +botocore = ">=1.33.2,<2.0a.0" [package.extras] -crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"] +crt = ["botocore[crt] (>=1.33.2,<2.0a.0)"] [[package]] name = "selenium" -version = "4.20.0" -description = "" +version = "4.27.1" +description = "Official Python bindings for Selenium WebDriver" optional = false python-versions = ">=3.8" files = [ - {file = "selenium-4.20.0-py3-none-any.whl", hash = "sha256:b1d0c33b38ca27d0499183e48e1dd09ff26973481f5d3ef2983073813ae6588d"}, - {file = "selenium-4.20.0.tar.gz", hash = "sha256:0bd564ee166980d419a8aaf4ac00289bc152afcf2eadca5efe8c8e36711853fd"}, + {file = "selenium-4.27.1-py3-none-any.whl", hash = "sha256:b89b1f62b5cfe8025868556fe82360d6b649d464f75d2655cb966c8f8447ea18"}, + {file = "selenium-4.27.1.tar.gz", hash = "sha256:5296c425a75ff1b44d0d5199042b36a6d1ef76c04fb775b97b40be739a9caae2"}, ] [package.dependencies] certifi = ">=2021.10.8" trio = ">=0.17,<1.0" trio-websocket = ">=0.9,<1.0" -typing_extensions = ">=4.9.0" +typing_extensions = ">=4.9,<5.0" urllib3 = {version = ">=1.26,<3", extras = ["socks"]} +websocket-client = ">=1.8,<2.0" [[package]] name = "six" -version = "1.16.0" +version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, + {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, + {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, ] [[package]] name = "slack-sdk" -version = "3.23.0" +version = "3.33.5" description = "The Slack API Platform SDK for Python" optional = false -python-versions = ">=3.6.0" +python-versions = ">=3.6" files = [ - {file = "slack_sdk-3.23.0-py2.py3-none-any.whl", hash = "sha256:2a8513505cced20ceee22b5b49c11d9545caa6234b56bf0ad47133ea5b357d10"}, - {file = "slack_sdk-3.23.0.tar.gz", hash = "sha256:9d6ebc4ff74e7983e1b27dbdb0f2bb6fc3c2a2451694686eaa2be23bbb085a73"}, + {file = "slack_sdk-3.33.5-py2.py3-none-any.whl", hash = "sha256:b8cccadfa3d4005a5e6529f52000d25c583f46173fda8e9136fdd2bc58923ff6"}, + {file = "slack_sdk-3.33.5.tar.gz", hash = "sha256:a5e74c00c99dc844ad93e501ab764a20d86fa8184bbc9432af217496f632c4ee"}, ] [package.extras] -optional = ["SQLAlchemy (>=1.4,<3)", "aiodns (>1.0)", "aiohttp (>=3.7.3,<4)", "boto3 (<=2)", "websocket-client (>=1,<2)", "websockets (>=10,<11)"] -testing = ["Flask (>=1,<2)", "Flask-Sockets (>=0.2,<1)", "Jinja2 (==3.0.3)", "Werkzeug (<2)", "black (==22.8.0)", "boto3 (<=2)", "click (==8.0.4)", "flake8 (>=5,<6)", "itsdangerous (==1.1.0)", "moto (>=3,<4)", "psutil (>=5,<6)", "pytest (>=6.2.5,<7)", "pytest-asyncio (<1)", "pytest-cov (>=2,<3)"] +optional = ["SQLAlchemy (>=1.4,<3)", "aiodns (>1.0)", "aiohttp (>=3.7.3,<4)", "boto3 (<=2)", "websocket-client (>=1,<2)", "websockets (>=9.1,<15)"] [[package]] name = "sniffio" @@ -1276,55 +895,86 @@ files = [ [[package]] name = "soupsieve" -version = "2.5" +version = "2.6" description = "A modern CSS selector implementation for Beautiful Soup." optional = false python-versions = ">=3.8" files = [ - {file = "soupsieve-2.5-py3-none-any.whl", hash = "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7"}, - {file = "soupsieve-2.5.tar.gz", hash = "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690"}, + {file = "soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9"}, + {file = "soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb"}, ] [[package]] name = "tomli" -version = "2.0.1" +version = "2.2.1" description = "A lil' TOML parser" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, + {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, + {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, + {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, + {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, + {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, + {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, + {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, + {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, ] [[package]] name = "tqdm" -version = "4.66.3" +version = "4.67.1" description = "Fast, Extensible Progress Meter" optional = false python-versions = ">=3.7" files = [ - {file = "tqdm-4.66.3-py3-none-any.whl", hash = "sha256:4f41d54107ff9a223dca80b53efe4fb654c67efaba7f47bada3ee9d50e05bd53"}, - {file = "tqdm-4.66.3.tar.gz", hash = "sha256:23097a41eba115ba99ecae40d06444c15d1c0c698d527a01c6c8bd1c5d0647e5"}, + {file = "tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2"}, + {file = "tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2"}, ] [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} [package.extras] -dev = ["pytest (>=6)", "pytest-cov", "pytest-timeout", "pytest-xdist"] +dev = ["nbval", "pytest (>=6)", "pytest-asyncio (>=0.24)", "pytest-cov", "pytest-timeout"] +discord = ["requests"] notebook = ["ipywidgets (>=6)"] slack = ["slack-sdk"] telegram = ["requests"] [[package]] name = "trio" -version = "0.25.0" +version = "0.27.0" description = "A friendly Python library for async concurrency and I/O" optional = false python-versions = ">=3.8" files = [ - {file = "trio-0.25.0-py3-none-any.whl", hash = "sha256:e6458efe29cc543e557a91e614e2b51710eba2961669329ce9c862d50c6e8e81"}, - {file = "trio-0.25.0.tar.gz", hash = "sha256:9b41f5993ad2c0e5f62d0acca320ec657fdb6b2a2c22b8c7aed6caf154475c4e"}, + {file = "trio-0.27.0-py3-none-any.whl", hash = "sha256:68eabbcf8f457d925df62da780eff15ff5dc68fd6b367e2dde59f7aaf2a0b884"}, + {file = "trio-0.27.0.tar.gz", hash = "sha256:1dcc95ab1726b2da054afea8fd761af74bad79bd52381b84eae408e983c76831"}, ] [package.dependencies] @@ -1354,81 +1004,529 @@ wsproto = ">=0.14" [[package]] name = "types-awscrt" -version = "0.20.3" +version = "0.23.4" description = "Type annotations and code completion for awscrt" optional = false -python-versions = ">=3.7,<4.0" +python-versions = ">=3.8" files = [ - {file = "types_awscrt-0.20.3-py3-none-any.whl", hash = "sha256:f61a120d3e98ee1387bc5ca4b93437f258cc5c2af1f55f8634ec4cee5729f178"}, - {file = "types_awscrt-0.20.3.tar.gz", hash = "sha256:06a859189a329ca8e66d56ceeef2391488e39b878fbd2141f115eab4d416fe22"}, + {file = "types_awscrt-0.23.4-py3-none-any.whl", hash = "sha256:eeb4bd596100927704c8b9f964ec8a246be4943d546f3fd2a8efdddebea422ea"}, + {file = "types_awscrt-0.23.4.tar.gz", hash = "sha256:b1b9bb10f337e3fe8f5f508860eb354d9fe093f02e1485955a9e0bdd4e250074"}, ] [[package]] name = "types-boto3" -version = "1.0.2" -description = "Proxy package for boto3-stubs" +version = "1.35.81" +description = "Type annotations for boto3 1.35.81 generated with mypy-boto3-builder 8.6.3" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "types-boto3-1.0.2.tar.gz", hash = "sha256:15f3ffad0314e40a0708fec25f94891414f93260202422bf8b19b6913853c983"}, - {file = "types_boto3-1.0.2-py3-none-any.whl", hash = "sha256:a6a88e94d59d887839863a64095493956efc148e747206880a7eb47d90ae8398"}, + {file = "types_boto3-1.35.81-py3-none-any.whl", hash = "sha256:d302a9b7b4461fd7b5970cfbaa180d604d655310c770a835d5cec941ce1dc9f8"}, + {file = "types_boto3-1.35.81.tar.gz", hash = "sha256:dfb08fbd236fbd6e748f3f884169a191ccffc86ba781470d69990d8a02c68148"}, ] [package.dependencies] -boto3-stubs = "*" +botocore-stubs = "*" +types-s3transfer = "*" +typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.12\""} + +[package.extras] +accessanalyzer = ["types-boto3-accessanalyzer (>=1.35.0,<1.36.0)"] +account = ["types-boto3-account (>=1.35.0,<1.36.0)"] +acm = ["types-boto3-acm (>=1.35.0,<1.36.0)"] +acm-pca = ["types-boto3-acm-pca (>=1.35.0,<1.36.0)"] +all = ["types-boto3-accessanalyzer (>=1.35.0,<1.36.0)", "types-boto3-account (>=1.35.0,<1.36.0)", "types-boto3-acm (>=1.35.0,<1.36.0)", "types-boto3-acm-pca (>=1.35.0,<1.36.0)", "types-boto3-amp (>=1.35.0,<1.36.0)", "types-boto3-amplify (>=1.35.0,<1.36.0)", "types-boto3-amplifybackend (>=1.35.0,<1.36.0)", "types-boto3-amplifyuibuilder (>=1.35.0,<1.36.0)", "types-boto3-apigateway (>=1.35.0,<1.36.0)", "types-boto3-apigatewaymanagementapi (>=1.35.0,<1.36.0)", "types-boto3-apigatewayv2 (>=1.35.0,<1.36.0)", "types-boto3-appconfig (>=1.35.0,<1.36.0)", "types-boto3-appconfigdata (>=1.35.0,<1.36.0)", "types-boto3-appfabric (>=1.35.0,<1.36.0)", "types-boto3-appflow (>=1.35.0,<1.36.0)", "types-boto3-appintegrations (>=1.35.0,<1.36.0)", "types-boto3-application-autoscaling (>=1.35.0,<1.36.0)", "types-boto3-application-insights (>=1.35.0,<1.36.0)", "types-boto3-application-signals (>=1.35.0,<1.36.0)", "types-boto3-applicationcostprofiler (>=1.35.0,<1.36.0)", "types-boto3-appmesh (>=1.35.0,<1.36.0)", "types-boto3-apprunner (>=1.35.0,<1.36.0)", "types-boto3-appstream (>=1.35.0,<1.36.0)", "types-boto3-appsync (>=1.35.0,<1.36.0)", "types-boto3-apptest (>=1.35.0,<1.36.0)", "types-boto3-arc-zonal-shift (>=1.35.0,<1.36.0)", "types-boto3-artifact (>=1.35.0,<1.36.0)", "types-boto3-athena (>=1.35.0,<1.36.0)", "types-boto3-auditmanager (>=1.35.0,<1.36.0)", "types-boto3-autoscaling (>=1.35.0,<1.36.0)", "types-boto3-autoscaling-plans (>=1.35.0,<1.36.0)", "types-boto3-b2bi (>=1.35.0,<1.36.0)", "types-boto3-backup (>=1.35.0,<1.36.0)", "types-boto3-backup-gateway (>=1.35.0,<1.36.0)", "types-boto3-batch (>=1.35.0,<1.36.0)", "types-boto3-bcm-data-exports (>=1.35.0,<1.36.0)", "types-boto3-bcm-pricing-calculator (>=1.35.0,<1.36.0)", "types-boto3-bedrock (>=1.35.0,<1.36.0)", "types-boto3-bedrock-agent (>=1.35.0,<1.36.0)", "types-boto3-bedrock-agent-runtime (>=1.35.0,<1.36.0)", "types-boto3-bedrock-data-automation (>=1.35.0,<1.36.0)", "types-boto3-bedrock-data-automation-runtime (>=1.35.0,<1.36.0)", "types-boto3-bedrock-runtime (>=1.35.0,<1.36.0)", "types-boto3-billing (>=1.35.0,<1.36.0)", "types-boto3-billingconductor (>=1.35.0,<1.36.0)", "types-boto3-braket (>=1.35.0,<1.36.0)", "types-boto3-budgets (>=1.35.0,<1.36.0)", "types-boto3-ce (>=1.35.0,<1.36.0)", "types-boto3-chatbot (>=1.35.0,<1.36.0)", "types-boto3-chime (>=1.35.0,<1.36.0)", "types-boto3-chime-sdk-identity (>=1.35.0,<1.36.0)", "types-boto3-chime-sdk-media-pipelines (>=1.35.0,<1.36.0)", "types-boto3-chime-sdk-meetings (>=1.35.0,<1.36.0)", "types-boto3-chime-sdk-messaging (>=1.35.0,<1.36.0)", "types-boto3-chime-sdk-voice (>=1.35.0,<1.36.0)", "types-boto3-cleanrooms (>=1.35.0,<1.36.0)", "types-boto3-cleanroomsml (>=1.35.0,<1.36.0)", "types-boto3-cloud9 (>=1.35.0,<1.36.0)", "types-boto3-cloudcontrol (>=1.35.0,<1.36.0)", "types-boto3-clouddirectory (>=1.35.0,<1.36.0)", "types-boto3-cloudformation (>=1.35.0,<1.36.0)", "types-boto3-cloudfront (>=1.35.0,<1.36.0)", "types-boto3-cloudfront-keyvaluestore (>=1.35.0,<1.36.0)", "types-boto3-cloudhsm (>=1.35.0,<1.36.0)", "types-boto3-cloudhsmv2 (>=1.35.0,<1.36.0)", "types-boto3-cloudsearch (>=1.35.0,<1.36.0)", "types-boto3-cloudsearchdomain (>=1.35.0,<1.36.0)", "types-boto3-cloudtrail (>=1.35.0,<1.36.0)", "types-boto3-cloudtrail-data (>=1.35.0,<1.36.0)", "types-boto3-cloudwatch (>=1.35.0,<1.36.0)", "types-boto3-codeartifact (>=1.35.0,<1.36.0)", "types-boto3-codebuild (>=1.35.0,<1.36.0)", "types-boto3-codecatalyst (>=1.35.0,<1.36.0)", "types-boto3-codecommit (>=1.35.0,<1.36.0)", "types-boto3-codeconnections (>=1.35.0,<1.36.0)", "types-boto3-codedeploy (>=1.35.0,<1.36.0)", "types-boto3-codeguru-reviewer (>=1.35.0,<1.36.0)", "types-boto3-codeguru-security (>=1.35.0,<1.36.0)", "types-boto3-codeguruprofiler (>=1.35.0,<1.36.0)", "types-boto3-codepipeline (>=1.35.0,<1.36.0)", "types-boto3-codestar-connections (>=1.35.0,<1.36.0)", "types-boto3-codestar-notifications (>=1.35.0,<1.36.0)", "types-boto3-cognito-identity (>=1.35.0,<1.36.0)", "types-boto3-cognito-idp (>=1.35.0,<1.36.0)", "types-boto3-cognito-sync (>=1.35.0,<1.36.0)", "types-boto3-comprehend (>=1.35.0,<1.36.0)", "types-boto3-comprehendmedical (>=1.35.0,<1.36.0)", "types-boto3-compute-optimizer (>=1.35.0,<1.36.0)", "types-boto3-config (>=1.35.0,<1.36.0)", "types-boto3-connect (>=1.35.0,<1.36.0)", "types-boto3-connect-contact-lens (>=1.35.0,<1.36.0)", "types-boto3-connectcampaigns (>=1.35.0,<1.36.0)", "types-boto3-connectcampaignsv2 (>=1.35.0,<1.36.0)", "types-boto3-connectcases (>=1.35.0,<1.36.0)", "types-boto3-connectparticipant (>=1.35.0,<1.36.0)", "types-boto3-controlcatalog (>=1.35.0,<1.36.0)", "types-boto3-controltower (>=1.35.0,<1.36.0)", "types-boto3-cost-optimization-hub (>=1.35.0,<1.36.0)", "types-boto3-cur (>=1.35.0,<1.36.0)", "types-boto3-customer-profiles (>=1.35.0,<1.36.0)", "types-boto3-databrew (>=1.35.0,<1.36.0)", "types-boto3-dataexchange (>=1.35.0,<1.36.0)", "types-boto3-datapipeline (>=1.35.0,<1.36.0)", "types-boto3-datasync (>=1.35.0,<1.36.0)", "types-boto3-datazone (>=1.35.0,<1.36.0)", "types-boto3-dax (>=1.35.0,<1.36.0)", "types-boto3-deadline (>=1.35.0,<1.36.0)", "types-boto3-detective (>=1.35.0,<1.36.0)", "types-boto3-devicefarm (>=1.35.0,<1.36.0)", "types-boto3-devops-guru (>=1.35.0,<1.36.0)", "types-boto3-directconnect (>=1.35.0,<1.36.0)", "types-boto3-discovery (>=1.35.0,<1.36.0)", "types-boto3-dlm (>=1.35.0,<1.36.0)", "types-boto3-dms (>=1.35.0,<1.36.0)", "types-boto3-docdb (>=1.35.0,<1.36.0)", "types-boto3-docdb-elastic (>=1.35.0,<1.36.0)", "types-boto3-drs (>=1.35.0,<1.36.0)", "types-boto3-ds (>=1.35.0,<1.36.0)", "types-boto3-ds-data (>=1.35.0,<1.36.0)", "types-boto3-dsql (>=1.35.0,<1.36.0)", "types-boto3-dynamodb (>=1.35.0,<1.36.0)", "types-boto3-dynamodbstreams (>=1.35.0,<1.36.0)", "types-boto3-ebs (>=1.35.0,<1.36.0)", "types-boto3-ec2 (>=1.35.0,<1.36.0)", "types-boto3-ec2-instance-connect (>=1.35.0,<1.36.0)", "types-boto3-ecr (>=1.35.0,<1.36.0)", "types-boto3-ecr-public (>=1.35.0,<1.36.0)", "types-boto3-ecs (>=1.35.0,<1.36.0)", "types-boto3-efs (>=1.35.0,<1.36.0)", "types-boto3-eks (>=1.35.0,<1.36.0)", "types-boto3-eks-auth (>=1.35.0,<1.36.0)", "types-boto3-elastic-inference (>=1.35.0,<1.36.0)", "types-boto3-elasticache (>=1.35.0,<1.36.0)", "types-boto3-elasticbeanstalk (>=1.35.0,<1.36.0)", "types-boto3-elastictranscoder (>=1.35.0,<1.36.0)", "types-boto3-elb (>=1.35.0,<1.36.0)", "types-boto3-elbv2 (>=1.35.0,<1.36.0)", "types-boto3-emr (>=1.35.0,<1.36.0)", "types-boto3-emr-containers (>=1.35.0,<1.36.0)", "types-boto3-emr-serverless (>=1.35.0,<1.36.0)", "types-boto3-entityresolution (>=1.35.0,<1.36.0)", "types-boto3-es (>=1.35.0,<1.36.0)", "types-boto3-events (>=1.35.0,<1.36.0)", "types-boto3-evidently (>=1.35.0,<1.36.0)", "types-boto3-finspace (>=1.35.0,<1.36.0)", "types-boto3-finspace-data (>=1.35.0,<1.36.0)", "types-boto3-firehose (>=1.35.0,<1.36.0)", "types-boto3-fis (>=1.35.0,<1.36.0)", "types-boto3-fms (>=1.35.0,<1.36.0)", "types-boto3-forecast (>=1.35.0,<1.36.0)", "types-boto3-forecastquery (>=1.35.0,<1.36.0)", "types-boto3-frauddetector (>=1.35.0,<1.36.0)", "types-boto3-freetier (>=1.35.0,<1.36.0)", "types-boto3-fsx (>=1.35.0,<1.36.0)", "types-boto3-gamelift (>=1.35.0,<1.36.0)", "types-boto3-geo-maps (>=1.35.0,<1.36.0)", "types-boto3-geo-places (>=1.35.0,<1.36.0)", "types-boto3-geo-routes (>=1.35.0,<1.36.0)", "types-boto3-glacier (>=1.35.0,<1.36.0)", "types-boto3-globalaccelerator (>=1.35.0,<1.36.0)", "types-boto3-glue (>=1.35.0,<1.36.0)", "types-boto3-grafana (>=1.35.0,<1.36.0)", "types-boto3-greengrass (>=1.35.0,<1.36.0)", "types-boto3-greengrassv2 (>=1.35.0,<1.36.0)", "types-boto3-groundstation (>=1.35.0,<1.36.0)", "types-boto3-guardduty (>=1.35.0,<1.36.0)", "types-boto3-health (>=1.35.0,<1.36.0)", "types-boto3-healthlake (>=1.35.0,<1.36.0)", "types-boto3-iam (>=1.35.0,<1.36.0)", "types-boto3-identitystore (>=1.35.0,<1.36.0)", "types-boto3-imagebuilder (>=1.35.0,<1.36.0)", "types-boto3-importexport (>=1.35.0,<1.36.0)", "types-boto3-inspector (>=1.35.0,<1.36.0)", "types-boto3-inspector-scan (>=1.35.0,<1.36.0)", "types-boto3-inspector2 (>=1.35.0,<1.36.0)", "types-boto3-internetmonitor (>=1.35.0,<1.36.0)", "types-boto3-invoicing (>=1.35.0,<1.36.0)", "types-boto3-iot (>=1.35.0,<1.36.0)", "types-boto3-iot-data (>=1.35.0,<1.36.0)", "types-boto3-iot-jobs-data (>=1.35.0,<1.36.0)", "types-boto3-iot1click-devices (>=1.35.0,<1.36.0)", "types-boto3-iot1click-projects (>=1.35.0,<1.36.0)", "types-boto3-iotanalytics (>=1.35.0,<1.36.0)", "types-boto3-iotdeviceadvisor (>=1.35.0,<1.36.0)", "types-boto3-iotevents (>=1.35.0,<1.36.0)", "types-boto3-iotevents-data (>=1.35.0,<1.36.0)", "types-boto3-iotfleethub (>=1.35.0,<1.36.0)", "types-boto3-iotfleetwise (>=1.35.0,<1.36.0)", "types-boto3-iotsecuretunneling (>=1.35.0,<1.36.0)", "types-boto3-iotsitewise (>=1.35.0,<1.36.0)", "types-boto3-iotthingsgraph (>=1.35.0,<1.36.0)", "types-boto3-iottwinmaker (>=1.35.0,<1.36.0)", "types-boto3-iotwireless (>=1.35.0,<1.36.0)", "types-boto3-ivs (>=1.35.0,<1.36.0)", "types-boto3-ivs-realtime (>=1.35.0,<1.36.0)", "types-boto3-ivschat (>=1.35.0,<1.36.0)", "types-boto3-kafka (>=1.35.0,<1.36.0)", "types-boto3-kafkaconnect (>=1.35.0,<1.36.0)", "types-boto3-kendra (>=1.35.0,<1.36.0)", "types-boto3-kendra-ranking (>=1.35.0,<1.36.0)", "types-boto3-keyspaces (>=1.35.0,<1.36.0)", "types-boto3-kinesis (>=1.35.0,<1.36.0)", "types-boto3-kinesis-video-archived-media (>=1.35.0,<1.36.0)", "types-boto3-kinesis-video-media (>=1.35.0,<1.36.0)", "types-boto3-kinesis-video-signaling (>=1.35.0,<1.36.0)", "types-boto3-kinesis-video-webrtc-storage (>=1.35.0,<1.36.0)", "types-boto3-kinesisanalytics (>=1.35.0,<1.36.0)", "types-boto3-kinesisanalyticsv2 (>=1.35.0,<1.36.0)", "types-boto3-kinesisvideo (>=1.35.0,<1.36.0)", "types-boto3-kms (>=1.35.0,<1.36.0)", "types-boto3-lakeformation (>=1.35.0,<1.36.0)", "types-boto3-lambda (>=1.35.0,<1.36.0)", "types-boto3-launch-wizard (>=1.35.0,<1.36.0)", "types-boto3-lex-models (>=1.35.0,<1.36.0)", "types-boto3-lex-runtime (>=1.35.0,<1.36.0)", "types-boto3-lexv2-models (>=1.35.0,<1.36.0)", "types-boto3-lexv2-runtime (>=1.35.0,<1.36.0)", "types-boto3-license-manager (>=1.35.0,<1.36.0)", "types-boto3-license-manager-linux-subscriptions (>=1.35.0,<1.36.0)", "types-boto3-license-manager-user-subscriptions (>=1.35.0,<1.36.0)", "types-boto3-lightsail (>=1.35.0,<1.36.0)", "types-boto3-location (>=1.35.0,<1.36.0)", "types-boto3-logs (>=1.35.0,<1.36.0)", "types-boto3-lookoutequipment (>=1.35.0,<1.36.0)", "types-boto3-lookoutmetrics (>=1.35.0,<1.36.0)", "types-boto3-lookoutvision (>=1.35.0,<1.36.0)", "types-boto3-m2 (>=1.35.0,<1.36.0)", "types-boto3-machinelearning (>=1.35.0,<1.36.0)", "types-boto3-macie2 (>=1.35.0,<1.36.0)", "types-boto3-mailmanager (>=1.35.0,<1.36.0)", "types-boto3-managedblockchain (>=1.35.0,<1.36.0)", "types-boto3-managedblockchain-query (>=1.35.0,<1.36.0)", "types-boto3-marketplace-agreement (>=1.35.0,<1.36.0)", "types-boto3-marketplace-catalog (>=1.35.0,<1.36.0)", "types-boto3-marketplace-deployment (>=1.35.0,<1.36.0)", "types-boto3-marketplace-entitlement (>=1.35.0,<1.36.0)", "types-boto3-marketplace-reporting (>=1.35.0,<1.36.0)", "types-boto3-marketplacecommerceanalytics (>=1.35.0,<1.36.0)", "types-boto3-mediaconnect (>=1.35.0,<1.36.0)", "types-boto3-mediaconvert (>=1.35.0,<1.36.0)", "types-boto3-medialive (>=1.35.0,<1.36.0)", "types-boto3-mediapackage (>=1.35.0,<1.36.0)", "types-boto3-mediapackage-vod (>=1.35.0,<1.36.0)", "types-boto3-mediapackagev2 (>=1.35.0,<1.36.0)", "types-boto3-mediastore (>=1.35.0,<1.36.0)", "types-boto3-mediastore-data (>=1.35.0,<1.36.0)", "types-boto3-mediatailor (>=1.35.0,<1.36.0)", "types-boto3-medical-imaging (>=1.35.0,<1.36.0)", "types-boto3-memorydb (>=1.35.0,<1.36.0)", "types-boto3-meteringmarketplace (>=1.35.0,<1.36.0)", "types-boto3-mgh (>=1.35.0,<1.36.0)", "types-boto3-mgn (>=1.35.0,<1.36.0)", "types-boto3-migration-hub-refactor-spaces (>=1.35.0,<1.36.0)", "types-boto3-migrationhub-config (>=1.35.0,<1.36.0)", "types-boto3-migrationhuborchestrator (>=1.35.0,<1.36.0)", "types-boto3-migrationhubstrategy (>=1.35.0,<1.36.0)", "types-boto3-mq (>=1.35.0,<1.36.0)", "types-boto3-mturk (>=1.35.0,<1.36.0)", "types-boto3-mwaa (>=1.35.0,<1.36.0)", "types-boto3-neptune (>=1.35.0,<1.36.0)", "types-boto3-neptune-graph (>=1.35.0,<1.36.0)", "types-boto3-neptunedata (>=1.35.0,<1.36.0)", "types-boto3-network-firewall (>=1.35.0,<1.36.0)", "types-boto3-networkflowmonitor (>=1.35.0,<1.36.0)", "types-boto3-networkmanager (>=1.35.0,<1.36.0)", "types-boto3-networkmonitor (>=1.35.0,<1.36.0)", "types-boto3-notifications (>=1.35.0,<1.36.0)", "types-boto3-notificationscontacts (>=1.35.0,<1.36.0)", "types-boto3-oam (>=1.35.0,<1.36.0)", "types-boto3-observabilityadmin (>=1.35.0,<1.36.0)", "types-boto3-omics (>=1.35.0,<1.36.0)", "types-boto3-opensearch (>=1.35.0,<1.36.0)", "types-boto3-opensearchserverless (>=1.35.0,<1.36.0)", "types-boto3-opsworks (>=1.35.0,<1.36.0)", "types-boto3-opsworkscm (>=1.35.0,<1.36.0)", "types-boto3-organizations (>=1.35.0,<1.36.0)", "types-boto3-osis (>=1.35.0,<1.36.0)", "types-boto3-outposts (>=1.35.0,<1.36.0)", "types-boto3-panorama (>=1.35.0,<1.36.0)", "types-boto3-partnercentral-selling (>=1.35.0,<1.36.0)", "types-boto3-payment-cryptography (>=1.35.0,<1.36.0)", "types-boto3-payment-cryptography-data (>=1.35.0,<1.36.0)", "types-boto3-pca-connector-ad (>=1.35.0,<1.36.0)", "types-boto3-pca-connector-scep (>=1.35.0,<1.36.0)", "types-boto3-pcs (>=1.35.0,<1.36.0)", "types-boto3-personalize (>=1.35.0,<1.36.0)", "types-boto3-personalize-events (>=1.35.0,<1.36.0)", "types-boto3-personalize-runtime (>=1.35.0,<1.36.0)", "types-boto3-pi (>=1.35.0,<1.36.0)", "types-boto3-pinpoint (>=1.35.0,<1.36.0)", "types-boto3-pinpoint-email (>=1.35.0,<1.36.0)", "types-boto3-pinpoint-sms-voice (>=1.35.0,<1.36.0)", "types-boto3-pinpoint-sms-voice-v2 (>=1.35.0,<1.36.0)", "types-boto3-pipes (>=1.35.0,<1.36.0)", "types-boto3-polly (>=1.35.0,<1.36.0)", "types-boto3-pricing (>=1.35.0,<1.36.0)", "types-boto3-privatenetworks (>=1.35.0,<1.36.0)", "types-boto3-proton (>=1.35.0,<1.36.0)", "types-boto3-qapps (>=1.35.0,<1.36.0)", "types-boto3-qbusiness (>=1.35.0,<1.36.0)", "types-boto3-qconnect (>=1.35.0,<1.36.0)", "types-boto3-qldb (>=1.35.0,<1.36.0)", "types-boto3-qldb-session (>=1.35.0,<1.36.0)", "types-boto3-quicksight (>=1.35.0,<1.36.0)", "types-boto3-ram (>=1.35.0,<1.36.0)", "types-boto3-rbin (>=1.35.0,<1.36.0)", "types-boto3-rds (>=1.35.0,<1.36.0)", "types-boto3-rds-data (>=1.35.0,<1.36.0)", "types-boto3-redshift (>=1.35.0,<1.36.0)", "types-boto3-redshift-data (>=1.35.0,<1.36.0)", "types-boto3-redshift-serverless (>=1.35.0,<1.36.0)", "types-boto3-rekognition (>=1.35.0,<1.36.0)", "types-boto3-repostspace (>=1.35.0,<1.36.0)", "types-boto3-resiliencehub (>=1.35.0,<1.36.0)", "types-boto3-resource-explorer-2 (>=1.35.0,<1.36.0)", "types-boto3-resource-groups (>=1.35.0,<1.36.0)", "types-boto3-resourcegroupstaggingapi (>=1.35.0,<1.36.0)", "types-boto3-robomaker (>=1.35.0,<1.36.0)", "types-boto3-rolesanywhere (>=1.35.0,<1.36.0)", "types-boto3-route53 (>=1.35.0,<1.36.0)", "types-boto3-route53-recovery-cluster (>=1.35.0,<1.36.0)", "types-boto3-route53-recovery-control-config (>=1.35.0,<1.36.0)", "types-boto3-route53-recovery-readiness (>=1.35.0,<1.36.0)", "types-boto3-route53domains (>=1.35.0,<1.36.0)", "types-boto3-route53profiles (>=1.35.0,<1.36.0)", "types-boto3-route53resolver (>=1.35.0,<1.36.0)", "types-boto3-rum (>=1.35.0,<1.36.0)", "types-boto3-s3 (>=1.35.0,<1.36.0)", "types-boto3-s3control (>=1.35.0,<1.36.0)", "types-boto3-s3outposts (>=1.35.0,<1.36.0)", "types-boto3-s3tables (>=1.35.0,<1.36.0)", "types-boto3-sagemaker (>=1.35.0,<1.36.0)", "types-boto3-sagemaker-a2i-runtime (>=1.35.0,<1.36.0)", "types-boto3-sagemaker-edge (>=1.35.0,<1.36.0)", "types-boto3-sagemaker-featurestore-runtime (>=1.35.0,<1.36.0)", "types-boto3-sagemaker-geospatial (>=1.35.0,<1.36.0)", "types-boto3-sagemaker-metrics (>=1.35.0,<1.36.0)", "types-boto3-sagemaker-runtime (>=1.35.0,<1.36.0)", "types-boto3-savingsplans (>=1.35.0,<1.36.0)", "types-boto3-scheduler (>=1.35.0,<1.36.0)", "types-boto3-schemas (>=1.35.0,<1.36.0)", "types-boto3-sdb (>=1.35.0,<1.36.0)", "types-boto3-secretsmanager (>=1.35.0,<1.36.0)", "types-boto3-security-ir (>=1.35.0,<1.36.0)", "types-boto3-securityhub (>=1.35.0,<1.36.0)", "types-boto3-securitylake (>=1.35.0,<1.36.0)", "types-boto3-serverlessrepo (>=1.35.0,<1.36.0)", "types-boto3-service-quotas (>=1.35.0,<1.36.0)", "types-boto3-servicecatalog (>=1.35.0,<1.36.0)", "types-boto3-servicecatalog-appregistry (>=1.35.0,<1.36.0)", "types-boto3-servicediscovery (>=1.35.0,<1.36.0)", "types-boto3-ses (>=1.35.0,<1.36.0)", "types-boto3-sesv2 (>=1.35.0,<1.36.0)", "types-boto3-shield (>=1.35.0,<1.36.0)", "types-boto3-signer (>=1.35.0,<1.36.0)", "types-boto3-simspaceweaver (>=1.35.0,<1.36.0)", "types-boto3-sms (>=1.35.0,<1.36.0)", "types-boto3-sms-voice (>=1.35.0,<1.36.0)", "types-boto3-snow-device-management (>=1.35.0,<1.36.0)", "types-boto3-snowball (>=1.35.0,<1.36.0)", "types-boto3-sns (>=1.35.0,<1.36.0)", "types-boto3-socialmessaging (>=1.35.0,<1.36.0)", "types-boto3-sqs (>=1.35.0,<1.36.0)", "types-boto3-ssm (>=1.35.0,<1.36.0)", "types-boto3-ssm-contacts (>=1.35.0,<1.36.0)", "types-boto3-ssm-incidents (>=1.35.0,<1.36.0)", "types-boto3-ssm-quicksetup (>=1.35.0,<1.36.0)", "types-boto3-ssm-sap (>=1.35.0,<1.36.0)", "types-boto3-sso (>=1.35.0,<1.36.0)", "types-boto3-sso-admin (>=1.35.0,<1.36.0)", "types-boto3-sso-oidc (>=1.35.0,<1.36.0)", "types-boto3-stepfunctions (>=1.35.0,<1.36.0)", "types-boto3-storagegateway (>=1.35.0,<1.36.0)", "types-boto3-sts (>=1.35.0,<1.36.0)", "types-boto3-supplychain (>=1.35.0,<1.36.0)", "types-boto3-support (>=1.35.0,<1.36.0)", "types-boto3-support-app (>=1.35.0,<1.36.0)", "types-boto3-swf (>=1.35.0,<1.36.0)", "types-boto3-synthetics (>=1.35.0,<1.36.0)", "types-boto3-taxsettings (>=1.35.0,<1.36.0)", "types-boto3-textract (>=1.35.0,<1.36.0)", "types-boto3-timestream-influxdb (>=1.35.0,<1.36.0)", "types-boto3-timestream-query (>=1.35.0,<1.36.0)", "types-boto3-timestream-write (>=1.35.0,<1.36.0)", "types-boto3-tnb (>=1.35.0,<1.36.0)", "types-boto3-transcribe (>=1.35.0,<1.36.0)", "types-boto3-transfer (>=1.35.0,<1.36.0)", "types-boto3-translate (>=1.35.0,<1.36.0)", "types-boto3-trustedadvisor (>=1.35.0,<1.36.0)", "types-boto3-verifiedpermissions (>=1.35.0,<1.36.0)", "types-boto3-voice-id (>=1.35.0,<1.36.0)", "types-boto3-vpc-lattice (>=1.35.0,<1.36.0)", "types-boto3-waf (>=1.35.0,<1.36.0)", "types-boto3-waf-regional (>=1.35.0,<1.36.0)", "types-boto3-wafv2 (>=1.35.0,<1.36.0)", "types-boto3-wellarchitected (>=1.35.0,<1.36.0)", "types-boto3-wisdom (>=1.35.0,<1.36.0)", "types-boto3-workdocs (>=1.35.0,<1.36.0)", "types-boto3-workmail (>=1.35.0,<1.36.0)", "types-boto3-workmailmessageflow (>=1.35.0,<1.36.0)", "types-boto3-workspaces (>=1.35.0,<1.36.0)", "types-boto3-workspaces-thin-client (>=1.35.0,<1.36.0)", "types-boto3-workspaces-web (>=1.35.0,<1.36.0)", "types-boto3-xray (>=1.35.0,<1.36.0)"] +amp = ["types-boto3-amp (>=1.35.0,<1.36.0)"] +amplify = ["types-boto3-amplify (>=1.35.0,<1.36.0)"] +amplifybackend = ["types-boto3-amplifybackend (>=1.35.0,<1.36.0)"] +amplifyuibuilder = ["types-boto3-amplifyuibuilder (>=1.35.0,<1.36.0)"] +apigateway = ["types-boto3-apigateway (>=1.35.0,<1.36.0)"] +apigatewaymanagementapi = ["types-boto3-apigatewaymanagementapi (>=1.35.0,<1.36.0)"] +apigatewayv2 = ["types-boto3-apigatewayv2 (>=1.35.0,<1.36.0)"] +appconfig = ["types-boto3-appconfig (>=1.35.0,<1.36.0)"] +appconfigdata = ["types-boto3-appconfigdata (>=1.35.0,<1.36.0)"] +appfabric = ["types-boto3-appfabric (>=1.35.0,<1.36.0)"] +appflow = ["types-boto3-appflow (>=1.35.0,<1.36.0)"] +appintegrations = ["types-boto3-appintegrations (>=1.35.0,<1.36.0)"] +application-autoscaling = ["types-boto3-application-autoscaling (>=1.35.0,<1.36.0)"] +application-insights = ["types-boto3-application-insights (>=1.35.0,<1.36.0)"] +application-signals = ["types-boto3-application-signals (>=1.35.0,<1.36.0)"] +applicationcostprofiler = ["types-boto3-applicationcostprofiler (>=1.35.0,<1.36.0)"] +appmesh = ["types-boto3-appmesh (>=1.35.0,<1.36.0)"] +apprunner = ["types-boto3-apprunner (>=1.35.0,<1.36.0)"] +appstream = ["types-boto3-appstream (>=1.35.0,<1.36.0)"] +appsync = ["types-boto3-appsync (>=1.35.0,<1.36.0)"] +apptest = ["types-boto3-apptest (>=1.35.0,<1.36.0)"] +arc-zonal-shift = ["types-boto3-arc-zonal-shift (>=1.35.0,<1.36.0)"] +artifact = ["types-boto3-artifact (>=1.35.0,<1.36.0)"] +athena = ["types-boto3-athena (>=1.35.0,<1.36.0)"] +auditmanager = ["types-boto3-auditmanager (>=1.35.0,<1.36.0)"] +autoscaling = ["types-boto3-autoscaling (>=1.35.0,<1.36.0)"] +autoscaling-plans = ["types-boto3-autoscaling-plans (>=1.35.0,<1.36.0)"] +b2bi = ["types-boto3-b2bi (>=1.35.0,<1.36.0)"] +backup = ["types-boto3-backup (>=1.35.0,<1.36.0)"] +backup-gateway = ["types-boto3-backup-gateway (>=1.35.0,<1.36.0)"] +batch = ["types-boto3-batch (>=1.35.0,<1.36.0)"] +bcm-data-exports = ["types-boto3-bcm-data-exports (>=1.35.0,<1.36.0)"] +bcm-pricing-calculator = ["types-boto3-bcm-pricing-calculator (>=1.35.0,<1.36.0)"] +bedrock = ["types-boto3-bedrock (>=1.35.0,<1.36.0)"] +bedrock-agent = ["types-boto3-bedrock-agent (>=1.35.0,<1.36.0)"] +bedrock-agent-runtime = ["types-boto3-bedrock-agent-runtime (>=1.35.0,<1.36.0)"] +bedrock-data-automation = ["types-boto3-bedrock-data-automation (>=1.35.0,<1.36.0)"] +bedrock-data-automation-runtime = ["types-boto3-bedrock-data-automation-runtime (>=1.35.0,<1.36.0)"] +bedrock-runtime = ["types-boto3-bedrock-runtime (>=1.35.0,<1.36.0)"] +billing = ["types-boto3-billing (>=1.35.0,<1.36.0)"] +billingconductor = ["types-boto3-billingconductor (>=1.35.0,<1.36.0)"] +boto3 = ["boto3 (==1.35.81)"] +braket = ["types-boto3-braket (>=1.35.0,<1.36.0)"] +budgets = ["types-boto3-budgets (>=1.35.0,<1.36.0)"] +ce = ["types-boto3-ce (>=1.35.0,<1.36.0)"] +chatbot = ["types-boto3-chatbot (>=1.35.0,<1.36.0)"] +chime = ["types-boto3-chime (>=1.35.0,<1.36.0)"] +chime-sdk-identity = ["types-boto3-chime-sdk-identity (>=1.35.0,<1.36.0)"] +chime-sdk-media-pipelines = ["types-boto3-chime-sdk-media-pipelines (>=1.35.0,<1.36.0)"] +chime-sdk-meetings = ["types-boto3-chime-sdk-meetings (>=1.35.0,<1.36.0)"] +chime-sdk-messaging = ["types-boto3-chime-sdk-messaging (>=1.35.0,<1.36.0)"] +chime-sdk-voice = ["types-boto3-chime-sdk-voice (>=1.35.0,<1.36.0)"] +cleanrooms = ["types-boto3-cleanrooms (>=1.35.0,<1.36.0)"] +cleanroomsml = ["types-boto3-cleanroomsml (>=1.35.0,<1.36.0)"] +cloud9 = ["types-boto3-cloud9 (>=1.35.0,<1.36.0)"] +cloudcontrol = ["types-boto3-cloudcontrol (>=1.35.0,<1.36.0)"] +clouddirectory = ["types-boto3-clouddirectory (>=1.35.0,<1.36.0)"] +cloudformation = ["types-boto3-cloudformation (>=1.35.0,<1.36.0)"] +cloudfront = ["types-boto3-cloudfront (>=1.35.0,<1.36.0)"] +cloudfront-keyvaluestore = ["types-boto3-cloudfront-keyvaluestore (>=1.35.0,<1.36.0)"] +cloudhsm = ["types-boto3-cloudhsm (>=1.35.0,<1.36.0)"] +cloudhsmv2 = ["types-boto3-cloudhsmv2 (>=1.35.0,<1.36.0)"] +cloudsearch = ["types-boto3-cloudsearch (>=1.35.0,<1.36.0)"] +cloudsearchdomain = ["types-boto3-cloudsearchdomain (>=1.35.0,<1.36.0)"] +cloudtrail = ["types-boto3-cloudtrail (>=1.35.0,<1.36.0)"] +cloudtrail-data = ["types-boto3-cloudtrail-data (>=1.35.0,<1.36.0)"] +cloudwatch = ["types-boto3-cloudwatch (>=1.35.0,<1.36.0)"] +codeartifact = ["types-boto3-codeartifact (>=1.35.0,<1.36.0)"] +codebuild = ["types-boto3-codebuild (>=1.35.0,<1.36.0)"] +codecatalyst = ["types-boto3-codecatalyst (>=1.35.0,<1.36.0)"] +codecommit = ["types-boto3-codecommit (>=1.35.0,<1.36.0)"] +codeconnections = ["types-boto3-codeconnections (>=1.35.0,<1.36.0)"] +codedeploy = ["types-boto3-codedeploy (>=1.35.0,<1.36.0)"] +codeguru-reviewer = ["types-boto3-codeguru-reviewer (>=1.35.0,<1.36.0)"] +codeguru-security = ["types-boto3-codeguru-security (>=1.35.0,<1.36.0)"] +codeguruprofiler = ["types-boto3-codeguruprofiler (>=1.35.0,<1.36.0)"] +codepipeline = ["types-boto3-codepipeline (>=1.35.0,<1.36.0)"] +codestar-connections = ["types-boto3-codestar-connections (>=1.35.0,<1.36.0)"] +codestar-notifications = ["types-boto3-codestar-notifications (>=1.35.0,<1.36.0)"] +cognito-identity = ["types-boto3-cognito-identity (>=1.35.0,<1.36.0)"] +cognito-idp = ["types-boto3-cognito-idp (>=1.35.0,<1.36.0)"] +cognito-sync = ["types-boto3-cognito-sync (>=1.35.0,<1.36.0)"] +comprehend = ["types-boto3-comprehend (>=1.35.0,<1.36.0)"] +comprehendmedical = ["types-boto3-comprehendmedical (>=1.35.0,<1.36.0)"] +compute-optimizer = ["types-boto3-compute-optimizer (>=1.35.0,<1.36.0)"] +config = ["types-boto3-config (>=1.35.0,<1.36.0)"] +connect = ["types-boto3-connect (>=1.35.0,<1.36.0)"] +connect-contact-lens = ["types-boto3-connect-contact-lens (>=1.35.0,<1.36.0)"] +connectcampaigns = ["types-boto3-connectcampaigns (>=1.35.0,<1.36.0)"] +connectcampaignsv2 = ["types-boto3-connectcampaignsv2 (>=1.35.0,<1.36.0)"] +connectcases = ["types-boto3-connectcases (>=1.35.0,<1.36.0)"] +connectparticipant = ["types-boto3-connectparticipant (>=1.35.0,<1.36.0)"] +controlcatalog = ["types-boto3-controlcatalog (>=1.35.0,<1.36.0)"] +controltower = ["types-boto3-controltower (>=1.35.0,<1.36.0)"] +cost-optimization-hub = ["types-boto3-cost-optimization-hub (>=1.35.0,<1.36.0)"] +cur = ["types-boto3-cur (>=1.35.0,<1.36.0)"] +customer-profiles = ["types-boto3-customer-profiles (>=1.35.0,<1.36.0)"] +databrew = ["types-boto3-databrew (>=1.35.0,<1.36.0)"] +dataexchange = ["types-boto3-dataexchange (>=1.35.0,<1.36.0)"] +datapipeline = ["types-boto3-datapipeline (>=1.35.0,<1.36.0)"] +datasync = ["types-boto3-datasync (>=1.35.0,<1.36.0)"] +datazone = ["types-boto3-datazone (>=1.35.0,<1.36.0)"] +dax = ["types-boto3-dax (>=1.35.0,<1.36.0)"] +deadline = ["types-boto3-deadline (>=1.35.0,<1.36.0)"] +detective = ["types-boto3-detective (>=1.35.0,<1.36.0)"] +devicefarm = ["types-boto3-devicefarm (>=1.35.0,<1.36.0)"] +devops-guru = ["types-boto3-devops-guru (>=1.35.0,<1.36.0)"] +directconnect = ["types-boto3-directconnect (>=1.35.0,<1.36.0)"] +discovery = ["types-boto3-discovery (>=1.35.0,<1.36.0)"] +dlm = ["types-boto3-dlm (>=1.35.0,<1.36.0)"] +dms = ["types-boto3-dms (>=1.35.0,<1.36.0)"] +docdb = ["types-boto3-docdb (>=1.35.0,<1.36.0)"] +docdb-elastic = ["types-boto3-docdb-elastic (>=1.35.0,<1.36.0)"] +drs = ["types-boto3-drs (>=1.35.0,<1.36.0)"] +ds = ["types-boto3-ds (>=1.35.0,<1.36.0)"] +ds-data = ["types-boto3-ds-data (>=1.35.0,<1.36.0)"] +dsql = ["types-boto3-dsql (>=1.35.0,<1.36.0)"] +dynamodb = ["types-boto3-dynamodb (>=1.35.0,<1.36.0)"] +dynamodbstreams = ["types-boto3-dynamodbstreams (>=1.35.0,<1.36.0)"] +ebs = ["types-boto3-ebs (>=1.35.0,<1.36.0)"] +ec2 = ["types-boto3-ec2 (>=1.35.0,<1.36.0)"] +ec2-instance-connect = ["types-boto3-ec2-instance-connect (>=1.35.0,<1.36.0)"] +ecr = ["types-boto3-ecr (>=1.35.0,<1.36.0)"] +ecr-public = ["types-boto3-ecr-public (>=1.35.0,<1.36.0)"] +ecs = ["types-boto3-ecs (>=1.35.0,<1.36.0)"] +efs = ["types-boto3-efs (>=1.35.0,<1.36.0)"] +eks = ["types-boto3-eks (>=1.35.0,<1.36.0)"] +eks-auth = ["types-boto3-eks-auth (>=1.35.0,<1.36.0)"] +elastic-inference = ["types-boto3-elastic-inference (>=1.35.0,<1.36.0)"] +elasticache = ["types-boto3-elasticache (>=1.35.0,<1.36.0)"] +elasticbeanstalk = ["types-boto3-elasticbeanstalk (>=1.35.0,<1.36.0)"] +elastictranscoder = ["types-boto3-elastictranscoder (>=1.35.0,<1.36.0)"] +elb = ["types-boto3-elb (>=1.35.0,<1.36.0)"] +elbv2 = ["types-boto3-elbv2 (>=1.35.0,<1.36.0)"] +emr = ["types-boto3-emr (>=1.35.0,<1.36.0)"] +emr-containers = ["types-boto3-emr-containers (>=1.35.0,<1.36.0)"] +emr-serverless = ["types-boto3-emr-serverless (>=1.35.0,<1.36.0)"] +entityresolution = ["types-boto3-entityresolution (>=1.35.0,<1.36.0)"] +es = ["types-boto3-es (>=1.35.0,<1.36.0)"] +essential = ["types-boto3-cloudformation (>=1.35.0,<1.36.0)", "types-boto3-dynamodb (>=1.35.0,<1.36.0)", "types-boto3-ec2 (>=1.35.0,<1.36.0)", "types-boto3-lambda (>=1.35.0,<1.36.0)", "types-boto3-rds (>=1.35.0,<1.36.0)", "types-boto3-s3 (>=1.35.0,<1.36.0)", "types-boto3-sqs (>=1.35.0,<1.36.0)"] +events = ["types-boto3-events (>=1.35.0,<1.36.0)"] +evidently = ["types-boto3-evidently (>=1.35.0,<1.36.0)"] +finspace = ["types-boto3-finspace (>=1.35.0,<1.36.0)"] +finspace-data = ["types-boto3-finspace-data (>=1.35.0,<1.36.0)"] +firehose = ["types-boto3-firehose (>=1.35.0,<1.36.0)"] +fis = ["types-boto3-fis (>=1.35.0,<1.36.0)"] +fms = ["types-boto3-fms (>=1.35.0,<1.36.0)"] +forecast = ["types-boto3-forecast (>=1.35.0,<1.36.0)"] +forecastquery = ["types-boto3-forecastquery (>=1.35.0,<1.36.0)"] +frauddetector = ["types-boto3-frauddetector (>=1.35.0,<1.36.0)"] +freetier = ["types-boto3-freetier (>=1.35.0,<1.36.0)"] +fsx = ["types-boto3-fsx (>=1.35.0,<1.36.0)"] +full = ["types-boto3-full (>=1.35.0,<1.36.0)"] +gamelift = ["types-boto3-gamelift (>=1.35.0,<1.36.0)"] +geo-maps = ["types-boto3-geo-maps (>=1.35.0,<1.36.0)"] +geo-places = ["types-boto3-geo-places (>=1.35.0,<1.36.0)"] +geo-routes = ["types-boto3-geo-routes (>=1.35.0,<1.36.0)"] +glacier = ["types-boto3-glacier (>=1.35.0,<1.36.0)"] +globalaccelerator = ["types-boto3-globalaccelerator (>=1.35.0,<1.36.0)"] +glue = ["types-boto3-glue (>=1.35.0,<1.36.0)"] +grafana = ["types-boto3-grafana (>=1.35.0,<1.36.0)"] +greengrass = ["types-boto3-greengrass (>=1.35.0,<1.36.0)"] +greengrassv2 = ["types-boto3-greengrassv2 (>=1.35.0,<1.36.0)"] +groundstation = ["types-boto3-groundstation (>=1.35.0,<1.36.0)"] +guardduty = ["types-boto3-guardduty (>=1.35.0,<1.36.0)"] +health = ["types-boto3-health (>=1.35.0,<1.36.0)"] +healthlake = ["types-boto3-healthlake (>=1.35.0,<1.36.0)"] +iam = ["types-boto3-iam (>=1.35.0,<1.36.0)"] +identitystore = ["types-boto3-identitystore (>=1.35.0,<1.36.0)"] +imagebuilder = ["types-boto3-imagebuilder (>=1.35.0,<1.36.0)"] +importexport = ["types-boto3-importexport (>=1.35.0,<1.36.0)"] +inspector = ["types-boto3-inspector (>=1.35.0,<1.36.0)"] +inspector-scan = ["types-boto3-inspector-scan (>=1.35.0,<1.36.0)"] +inspector2 = ["types-boto3-inspector2 (>=1.35.0,<1.36.0)"] +internetmonitor = ["types-boto3-internetmonitor (>=1.35.0,<1.36.0)"] +invoicing = ["types-boto3-invoicing (>=1.35.0,<1.36.0)"] +iot = ["types-boto3-iot (>=1.35.0,<1.36.0)"] +iot-data = ["types-boto3-iot-data (>=1.35.0,<1.36.0)"] +iot-jobs-data = ["types-boto3-iot-jobs-data (>=1.35.0,<1.36.0)"] +iot1click-devices = ["types-boto3-iot1click-devices (>=1.35.0,<1.36.0)"] +iot1click-projects = ["types-boto3-iot1click-projects (>=1.35.0,<1.36.0)"] +iotanalytics = ["types-boto3-iotanalytics (>=1.35.0,<1.36.0)"] +iotdeviceadvisor = ["types-boto3-iotdeviceadvisor (>=1.35.0,<1.36.0)"] +iotevents = ["types-boto3-iotevents (>=1.35.0,<1.36.0)"] +iotevents-data = ["types-boto3-iotevents-data (>=1.35.0,<1.36.0)"] +iotfleethub = ["types-boto3-iotfleethub (>=1.35.0,<1.36.0)"] +iotfleetwise = ["types-boto3-iotfleetwise (>=1.35.0,<1.36.0)"] +iotsecuretunneling = ["types-boto3-iotsecuretunneling (>=1.35.0,<1.36.0)"] +iotsitewise = ["types-boto3-iotsitewise (>=1.35.0,<1.36.0)"] +iotthingsgraph = ["types-boto3-iotthingsgraph (>=1.35.0,<1.36.0)"] +iottwinmaker = ["types-boto3-iottwinmaker (>=1.35.0,<1.36.0)"] +iotwireless = ["types-boto3-iotwireless (>=1.35.0,<1.36.0)"] +ivs = ["types-boto3-ivs (>=1.35.0,<1.36.0)"] +ivs-realtime = ["types-boto3-ivs-realtime (>=1.35.0,<1.36.0)"] +ivschat = ["types-boto3-ivschat (>=1.35.0,<1.36.0)"] +kafka = ["types-boto3-kafka (>=1.35.0,<1.36.0)"] +kafkaconnect = ["types-boto3-kafkaconnect (>=1.35.0,<1.36.0)"] +kendra = ["types-boto3-kendra (>=1.35.0,<1.36.0)"] +kendra-ranking = ["types-boto3-kendra-ranking (>=1.35.0,<1.36.0)"] +keyspaces = ["types-boto3-keyspaces (>=1.35.0,<1.36.0)"] +kinesis = ["types-boto3-kinesis (>=1.35.0,<1.36.0)"] +kinesis-video-archived-media = ["types-boto3-kinesis-video-archived-media (>=1.35.0,<1.36.0)"] +kinesis-video-media = ["types-boto3-kinesis-video-media (>=1.35.0,<1.36.0)"] +kinesis-video-signaling = ["types-boto3-kinesis-video-signaling (>=1.35.0,<1.36.0)"] +kinesis-video-webrtc-storage = ["types-boto3-kinesis-video-webrtc-storage (>=1.35.0,<1.36.0)"] +kinesisanalytics = ["types-boto3-kinesisanalytics (>=1.35.0,<1.36.0)"] +kinesisanalyticsv2 = ["types-boto3-kinesisanalyticsv2 (>=1.35.0,<1.36.0)"] +kinesisvideo = ["types-boto3-kinesisvideo (>=1.35.0,<1.36.0)"] +kms = ["types-boto3-kms (>=1.35.0,<1.36.0)"] +lakeformation = ["types-boto3-lakeformation (>=1.35.0,<1.36.0)"] +lambda = ["types-boto3-lambda (>=1.35.0,<1.36.0)"] +launch-wizard = ["types-boto3-launch-wizard (>=1.35.0,<1.36.0)"] +lex-models = ["types-boto3-lex-models (>=1.35.0,<1.36.0)"] +lex-runtime = ["types-boto3-lex-runtime (>=1.35.0,<1.36.0)"] +lexv2-models = ["types-boto3-lexv2-models (>=1.35.0,<1.36.0)"] +lexv2-runtime = ["types-boto3-lexv2-runtime (>=1.35.0,<1.36.0)"] +license-manager = ["types-boto3-license-manager (>=1.35.0,<1.36.0)"] +license-manager-linux-subscriptions = ["types-boto3-license-manager-linux-subscriptions (>=1.35.0,<1.36.0)"] +license-manager-user-subscriptions = ["types-boto3-license-manager-user-subscriptions (>=1.35.0,<1.36.0)"] +lightsail = ["types-boto3-lightsail (>=1.35.0,<1.36.0)"] +location = ["types-boto3-location (>=1.35.0,<1.36.0)"] +logs = ["types-boto3-logs (>=1.35.0,<1.36.0)"] +lookoutequipment = ["types-boto3-lookoutequipment (>=1.35.0,<1.36.0)"] +lookoutmetrics = ["types-boto3-lookoutmetrics (>=1.35.0,<1.36.0)"] +lookoutvision = ["types-boto3-lookoutvision (>=1.35.0,<1.36.0)"] +m2 = ["types-boto3-m2 (>=1.35.0,<1.36.0)"] +machinelearning = ["types-boto3-machinelearning (>=1.35.0,<1.36.0)"] +macie2 = ["types-boto3-macie2 (>=1.35.0,<1.36.0)"] +mailmanager = ["types-boto3-mailmanager (>=1.35.0,<1.36.0)"] +managedblockchain = ["types-boto3-managedblockchain (>=1.35.0,<1.36.0)"] +managedblockchain-query = ["types-boto3-managedblockchain-query (>=1.35.0,<1.36.0)"] +marketplace-agreement = ["types-boto3-marketplace-agreement (>=1.35.0,<1.36.0)"] +marketplace-catalog = ["types-boto3-marketplace-catalog (>=1.35.0,<1.36.0)"] +marketplace-deployment = ["types-boto3-marketplace-deployment (>=1.35.0,<1.36.0)"] +marketplace-entitlement = ["types-boto3-marketplace-entitlement (>=1.35.0,<1.36.0)"] +marketplace-reporting = ["types-boto3-marketplace-reporting (>=1.35.0,<1.36.0)"] +marketplacecommerceanalytics = ["types-boto3-marketplacecommerceanalytics (>=1.35.0,<1.36.0)"] +mediaconnect = ["types-boto3-mediaconnect (>=1.35.0,<1.36.0)"] +mediaconvert = ["types-boto3-mediaconvert (>=1.35.0,<1.36.0)"] +medialive = ["types-boto3-medialive (>=1.35.0,<1.36.0)"] +mediapackage = ["types-boto3-mediapackage (>=1.35.0,<1.36.0)"] +mediapackage-vod = ["types-boto3-mediapackage-vod (>=1.35.0,<1.36.0)"] +mediapackagev2 = ["types-boto3-mediapackagev2 (>=1.35.0,<1.36.0)"] +mediastore = ["types-boto3-mediastore (>=1.35.0,<1.36.0)"] +mediastore-data = ["types-boto3-mediastore-data (>=1.35.0,<1.36.0)"] +mediatailor = ["types-boto3-mediatailor (>=1.35.0,<1.36.0)"] +medical-imaging = ["types-boto3-medical-imaging (>=1.35.0,<1.36.0)"] +memorydb = ["types-boto3-memorydb (>=1.35.0,<1.36.0)"] +meteringmarketplace = ["types-boto3-meteringmarketplace (>=1.35.0,<1.36.0)"] +mgh = ["types-boto3-mgh (>=1.35.0,<1.36.0)"] +mgn = ["types-boto3-mgn (>=1.35.0,<1.36.0)"] +migration-hub-refactor-spaces = ["types-boto3-migration-hub-refactor-spaces (>=1.35.0,<1.36.0)"] +migrationhub-config = ["types-boto3-migrationhub-config (>=1.35.0,<1.36.0)"] +migrationhuborchestrator = ["types-boto3-migrationhuborchestrator (>=1.35.0,<1.36.0)"] +migrationhubstrategy = ["types-boto3-migrationhubstrategy (>=1.35.0,<1.36.0)"] +mq = ["types-boto3-mq (>=1.35.0,<1.36.0)"] +mturk = ["types-boto3-mturk (>=1.35.0,<1.36.0)"] +mwaa = ["types-boto3-mwaa (>=1.35.0,<1.36.0)"] +neptune = ["types-boto3-neptune (>=1.35.0,<1.36.0)"] +neptune-graph = ["types-boto3-neptune-graph (>=1.35.0,<1.36.0)"] +neptunedata = ["types-boto3-neptunedata (>=1.35.0,<1.36.0)"] +network-firewall = ["types-boto3-network-firewall (>=1.35.0,<1.36.0)"] +networkflowmonitor = ["types-boto3-networkflowmonitor (>=1.35.0,<1.36.0)"] +networkmanager = ["types-boto3-networkmanager (>=1.35.0,<1.36.0)"] +networkmonitor = ["types-boto3-networkmonitor (>=1.35.0,<1.36.0)"] +notifications = ["types-boto3-notifications (>=1.35.0,<1.36.0)"] +notificationscontacts = ["types-boto3-notificationscontacts (>=1.35.0,<1.36.0)"] +oam = ["types-boto3-oam (>=1.35.0,<1.36.0)"] +observabilityadmin = ["types-boto3-observabilityadmin (>=1.35.0,<1.36.0)"] +omics = ["types-boto3-omics (>=1.35.0,<1.36.0)"] +opensearch = ["types-boto3-opensearch (>=1.35.0,<1.36.0)"] +opensearchserverless = ["types-boto3-opensearchserverless (>=1.35.0,<1.36.0)"] +opsworks = ["types-boto3-opsworks (>=1.35.0,<1.36.0)"] +opsworkscm = ["types-boto3-opsworkscm (>=1.35.0,<1.36.0)"] +organizations = ["types-boto3-organizations (>=1.35.0,<1.36.0)"] +osis = ["types-boto3-osis (>=1.35.0,<1.36.0)"] +outposts = ["types-boto3-outposts (>=1.35.0,<1.36.0)"] +panorama = ["types-boto3-panorama (>=1.35.0,<1.36.0)"] +partnercentral-selling = ["types-boto3-partnercentral-selling (>=1.35.0,<1.36.0)"] +payment-cryptography = ["types-boto3-payment-cryptography (>=1.35.0,<1.36.0)"] +payment-cryptography-data = ["types-boto3-payment-cryptography-data (>=1.35.0,<1.36.0)"] +pca-connector-ad = ["types-boto3-pca-connector-ad (>=1.35.0,<1.36.0)"] +pca-connector-scep = ["types-boto3-pca-connector-scep (>=1.35.0,<1.36.0)"] +pcs = ["types-boto3-pcs (>=1.35.0,<1.36.0)"] +personalize = ["types-boto3-personalize (>=1.35.0,<1.36.0)"] +personalize-events = ["types-boto3-personalize-events (>=1.35.0,<1.36.0)"] +personalize-runtime = ["types-boto3-personalize-runtime (>=1.35.0,<1.36.0)"] +pi = ["types-boto3-pi (>=1.35.0,<1.36.0)"] +pinpoint = ["types-boto3-pinpoint (>=1.35.0,<1.36.0)"] +pinpoint-email = ["types-boto3-pinpoint-email (>=1.35.0,<1.36.0)"] +pinpoint-sms-voice = ["types-boto3-pinpoint-sms-voice (>=1.35.0,<1.36.0)"] +pinpoint-sms-voice-v2 = ["types-boto3-pinpoint-sms-voice-v2 (>=1.35.0,<1.36.0)"] +pipes = ["types-boto3-pipes (>=1.35.0,<1.36.0)"] +polly = ["types-boto3-polly (>=1.35.0,<1.36.0)"] +pricing = ["types-boto3-pricing (>=1.35.0,<1.36.0)"] +privatenetworks = ["types-boto3-privatenetworks (>=1.35.0,<1.36.0)"] +proton = ["types-boto3-proton (>=1.35.0,<1.36.0)"] +qapps = ["types-boto3-qapps (>=1.35.0,<1.36.0)"] +qbusiness = ["types-boto3-qbusiness (>=1.35.0,<1.36.0)"] +qconnect = ["types-boto3-qconnect (>=1.35.0,<1.36.0)"] +qldb = ["types-boto3-qldb (>=1.35.0,<1.36.0)"] +qldb-session = ["types-boto3-qldb-session (>=1.35.0,<1.36.0)"] +quicksight = ["types-boto3-quicksight (>=1.35.0,<1.36.0)"] +ram = ["types-boto3-ram (>=1.35.0,<1.36.0)"] +rbin = ["types-boto3-rbin (>=1.35.0,<1.36.0)"] +rds = ["types-boto3-rds (>=1.35.0,<1.36.0)"] +rds-data = ["types-boto3-rds-data (>=1.35.0,<1.36.0)"] +redshift = ["types-boto3-redshift (>=1.35.0,<1.36.0)"] +redshift-data = ["types-boto3-redshift-data (>=1.35.0,<1.36.0)"] +redshift-serverless = ["types-boto3-redshift-serverless (>=1.35.0,<1.36.0)"] +rekognition = ["types-boto3-rekognition (>=1.35.0,<1.36.0)"] +repostspace = ["types-boto3-repostspace (>=1.35.0,<1.36.0)"] +resiliencehub = ["types-boto3-resiliencehub (>=1.35.0,<1.36.0)"] +resource-explorer-2 = ["types-boto3-resource-explorer-2 (>=1.35.0,<1.36.0)"] +resource-groups = ["types-boto3-resource-groups (>=1.35.0,<1.36.0)"] +resourcegroupstaggingapi = ["types-boto3-resourcegroupstaggingapi (>=1.35.0,<1.36.0)"] +robomaker = ["types-boto3-robomaker (>=1.35.0,<1.36.0)"] +rolesanywhere = ["types-boto3-rolesanywhere (>=1.35.0,<1.36.0)"] +route53 = ["types-boto3-route53 (>=1.35.0,<1.36.0)"] +route53-recovery-cluster = ["types-boto3-route53-recovery-cluster (>=1.35.0,<1.36.0)"] +route53-recovery-control-config = ["types-boto3-route53-recovery-control-config (>=1.35.0,<1.36.0)"] +route53-recovery-readiness = ["types-boto3-route53-recovery-readiness (>=1.35.0,<1.36.0)"] +route53domains = ["types-boto3-route53domains (>=1.35.0,<1.36.0)"] +route53profiles = ["types-boto3-route53profiles (>=1.35.0,<1.36.0)"] +route53resolver = ["types-boto3-route53resolver (>=1.35.0,<1.36.0)"] +rum = ["types-boto3-rum (>=1.35.0,<1.36.0)"] +s3 = ["types-boto3-s3 (>=1.35.0,<1.36.0)"] +s3control = ["types-boto3-s3control (>=1.35.0,<1.36.0)"] +s3outposts = ["types-boto3-s3outposts (>=1.35.0,<1.36.0)"] +s3tables = ["types-boto3-s3tables (>=1.35.0,<1.36.0)"] +sagemaker = ["types-boto3-sagemaker (>=1.35.0,<1.36.0)"] +sagemaker-a2i-runtime = ["types-boto3-sagemaker-a2i-runtime (>=1.35.0,<1.36.0)"] +sagemaker-edge = ["types-boto3-sagemaker-edge (>=1.35.0,<1.36.0)"] +sagemaker-featurestore-runtime = ["types-boto3-sagemaker-featurestore-runtime (>=1.35.0,<1.36.0)"] +sagemaker-geospatial = ["types-boto3-sagemaker-geospatial (>=1.35.0,<1.36.0)"] +sagemaker-metrics = ["types-boto3-sagemaker-metrics (>=1.35.0,<1.36.0)"] +sagemaker-runtime = ["types-boto3-sagemaker-runtime (>=1.35.0,<1.36.0)"] +savingsplans = ["types-boto3-savingsplans (>=1.35.0,<1.36.0)"] +scheduler = ["types-boto3-scheduler (>=1.35.0,<1.36.0)"] +schemas = ["types-boto3-schemas (>=1.35.0,<1.36.0)"] +sdb = ["types-boto3-sdb (>=1.35.0,<1.36.0)"] +secretsmanager = ["types-boto3-secretsmanager (>=1.35.0,<1.36.0)"] +security-ir = ["types-boto3-security-ir (>=1.35.0,<1.36.0)"] +securityhub = ["types-boto3-securityhub (>=1.35.0,<1.36.0)"] +securitylake = ["types-boto3-securitylake (>=1.35.0,<1.36.0)"] +serverlessrepo = ["types-boto3-serverlessrepo (>=1.35.0,<1.36.0)"] +service-quotas = ["types-boto3-service-quotas (>=1.35.0,<1.36.0)"] +servicecatalog = ["types-boto3-servicecatalog (>=1.35.0,<1.36.0)"] +servicecatalog-appregistry = ["types-boto3-servicecatalog-appregistry (>=1.35.0,<1.36.0)"] +servicediscovery = ["types-boto3-servicediscovery (>=1.35.0,<1.36.0)"] +ses = ["types-boto3-ses (>=1.35.0,<1.36.0)"] +sesv2 = ["types-boto3-sesv2 (>=1.35.0,<1.36.0)"] +shield = ["types-boto3-shield (>=1.35.0,<1.36.0)"] +signer = ["types-boto3-signer (>=1.35.0,<1.36.0)"] +simspaceweaver = ["types-boto3-simspaceweaver (>=1.35.0,<1.36.0)"] +sms = ["types-boto3-sms (>=1.35.0,<1.36.0)"] +sms-voice = ["types-boto3-sms-voice (>=1.35.0,<1.36.0)"] +snow-device-management = ["types-boto3-snow-device-management (>=1.35.0,<1.36.0)"] +snowball = ["types-boto3-snowball (>=1.35.0,<1.36.0)"] +sns = ["types-boto3-sns (>=1.35.0,<1.36.0)"] +socialmessaging = ["types-boto3-socialmessaging (>=1.35.0,<1.36.0)"] +sqs = ["types-boto3-sqs (>=1.35.0,<1.36.0)"] +ssm = ["types-boto3-ssm (>=1.35.0,<1.36.0)"] +ssm-contacts = ["types-boto3-ssm-contacts (>=1.35.0,<1.36.0)"] +ssm-incidents = ["types-boto3-ssm-incidents (>=1.35.0,<1.36.0)"] +ssm-quicksetup = ["types-boto3-ssm-quicksetup (>=1.35.0,<1.36.0)"] +ssm-sap = ["types-boto3-ssm-sap (>=1.35.0,<1.36.0)"] +sso = ["types-boto3-sso (>=1.35.0,<1.36.0)"] +sso-admin = ["types-boto3-sso-admin (>=1.35.0,<1.36.0)"] +sso-oidc = ["types-boto3-sso-oidc (>=1.35.0,<1.36.0)"] +stepfunctions = ["types-boto3-stepfunctions (>=1.35.0,<1.36.0)"] +storagegateway = ["types-boto3-storagegateway (>=1.35.0,<1.36.0)"] +sts = ["types-boto3-sts (>=1.35.0,<1.36.0)"] +supplychain = ["types-boto3-supplychain (>=1.35.0,<1.36.0)"] +support = ["types-boto3-support (>=1.35.0,<1.36.0)"] +support-app = ["types-boto3-support-app (>=1.35.0,<1.36.0)"] +swf = ["types-boto3-swf (>=1.35.0,<1.36.0)"] +synthetics = ["types-boto3-synthetics (>=1.35.0,<1.36.0)"] +taxsettings = ["types-boto3-taxsettings (>=1.35.0,<1.36.0)"] +textract = ["types-boto3-textract (>=1.35.0,<1.36.0)"] +timestream-influxdb = ["types-boto3-timestream-influxdb (>=1.35.0,<1.36.0)"] +timestream-query = ["types-boto3-timestream-query (>=1.35.0,<1.36.0)"] +timestream-write = ["types-boto3-timestream-write (>=1.35.0,<1.36.0)"] +tnb = ["types-boto3-tnb (>=1.35.0,<1.36.0)"] +transcribe = ["types-boto3-transcribe (>=1.35.0,<1.36.0)"] +transfer = ["types-boto3-transfer (>=1.35.0,<1.36.0)"] +translate = ["types-boto3-translate (>=1.35.0,<1.36.0)"] +trustedadvisor = ["types-boto3-trustedadvisor (>=1.35.0,<1.36.0)"] +verifiedpermissions = ["types-boto3-verifiedpermissions (>=1.35.0,<1.36.0)"] +voice-id = ["types-boto3-voice-id (>=1.35.0,<1.36.0)"] +vpc-lattice = ["types-boto3-vpc-lattice (>=1.35.0,<1.36.0)"] +waf = ["types-boto3-waf (>=1.35.0,<1.36.0)"] +waf-regional = ["types-boto3-waf-regional (>=1.35.0,<1.36.0)"] +wafv2 = ["types-boto3-wafv2 (>=1.35.0,<1.36.0)"] +wellarchitected = ["types-boto3-wellarchitected (>=1.35.0,<1.36.0)"] +wisdom = ["types-boto3-wisdom (>=1.35.0,<1.36.0)"] +workdocs = ["types-boto3-workdocs (>=1.35.0,<1.36.0)"] +workmail = ["types-boto3-workmail (>=1.35.0,<1.36.0)"] +workmailmessageflow = ["types-boto3-workmailmessageflow (>=1.35.0,<1.36.0)"] +workspaces = ["types-boto3-workspaces (>=1.35.0,<1.36.0)"] +workspaces-thin-client = ["types-boto3-workspaces-thin-client (>=1.35.0,<1.36.0)"] +workspaces-web = ["types-boto3-workspaces-web (>=1.35.0,<1.36.0)"] +xray = ["types-boto3-xray (>=1.35.0,<1.36.0)"] [[package]] name = "types-pyyaml" -version = "6.0.12.12" +version = "6.0.12.20240917" description = "Typing stubs for PyYAML" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "types-PyYAML-6.0.12.12.tar.gz", hash = "sha256:334373d392fde0fdf95af5c3f1661885fa10c52167b14593eb856289e1855062"}, - {file = "types_PyYAML-6.0.12.12-py3-none-any.whl", hash = "sha256:c05bc6c158facb0676674b7f11fe3960db4f389718e19e62bd2b84d6205cfd24"}, + {file = "types-PyYAML-6.0.12.20240917.tar.gz", hash = "sha256:d1405a86f9576682234ef83bcb4e6fff7c9305c8b1fbad5e0bcd4f7dbdc9c587"}, + {file = "types_PyYAML-6.0.12.20240917-py3-none-any.whl", hash = "sha256:392b267f1c0fe6022952462bf5d6523f31e37f6cea49b14cee7ad634b6301570"}, ] [[package]] name = "types-s3transfer" -version = "0.10.0" +version = "0.10.4" description = "Type annotations and code completion for s3transfer" optional = false -python-versions = ">=3.7,<4.0" +python-versions = ">=3.8" files = [ - {file = "types_s3transfer-0.10.0-py3-none-any.whl", hash = "sha256:44fcdf0097b924a9aab1ee4baa1179081a9559ca62a88c807e2b256893ce688f"}, - {file = "types_s3transfer-0.10.0.tar.gz", hash = "sha256:35e4998c25df7f8985ad69dedc8e4860e8af3b43b7615e940d53c00d413bdc69"}, + {file = "types_s3transfer-0.10.4-py3-none-any.whl", hash = "sha256:22ac1aabc98f9d7f2928eb3fb4d5c02bf7435687f0913345a97dd3b84d0c217d"}, + {file = "types_s3transfer-0.10.4.tar.gz", hash = "sha256:03123477e3064c81efe712bf9d372c7c72f2790711431f9baa59cf96ea607267"}, ] [[package]] name = "typing-extensions" -version = "4.11.0" +version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.11.0-py3-none-any.whl", hash = "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"}, - {file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"}, + {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, + {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, ] [[package]] name = "urllib3" -version = "1.26.16" +version = "1.26.20" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ - {file = "urllib3-1.26.16-py2.py3-none-any.whl", hash = "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f"}, - {file = "urllib3-1.26.16.tar.gz", hash = "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14"}, + {file = "urllib3-1.26.20-py2.py3-none-any.whl", hash = "sha256:0ed14ccfbf1c30a9072c7ca157e4319b70d65f623e91e7b32fadb2853431016e"}, + {file = "urllib3-1.26.20.tar.gz", hash = "sha256:40c2dc0c681e47eb8f90e7e27bf6ff7df2e677421fd46756da1161c39ca70d32"}, ] [package.dependencies] PySocks = {version = ">=1.5.6,<1.5.7 || >1.5.7,<2.0", optional = true, markers = "extra == \"socks\""} [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +[[package]] +name = "urllib3" +version = "2.2.3" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.8" +files = [ + {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, + {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, +] + +[package.dependencies] +pysocks = {version = ">=1.5.6,<1.5.7 || >1.5.7,<2.0", optional = true, markers = "extra == \"socks\""} + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "websocket-client" +version = "1.8.0" +description = "WebSocket client for Python with low level API options" +optional = false +python-versions = ">=3.8" +files = [ + {file = "websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526"}, + {file = "websocket_client-1.8.0.tar.gz", hash = "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da"}, +] + +[package.extras] +docs = ["Sphinx (>=6.0)", "myst-parser (>=2.0.0)", "sphinx-rtd-theme (>=1.1.0)"] +optional = ["python-socks", "wsaccel"] +test = ["websockets"] + [[package]] name = "wget" version = "3.2" @@ -1455,5 +1553,5 @@ h11 = ">=0.9.0,<1" [metadata] lock-version = "2.0" -python-versions = "^3.10" -content-hash = "aa507fe3e5347d55175e68e87e606a0cbbf90c7e1cef0891070d4c2ba8a0146f" +python-versions = "^3.9" +content-hash = "9e9f050c43ec3f8f64f4f0ff2ca8c0ebd4238d2b98e2ac92014d1a07bfa50933" diff --git a/pyproject.toml b/pyproject.toml index 4ed171a..e32d3c0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ authors = ["Adam Wright, Paulo Nuin and the Alliance of Genome Resources"] readme = "README.md" [tool.poetry.dependencies] -python = "^3.10" +python = "^3.9" rich = "^13.5.2" click = "^8.1.6" @@ -15,7 +15,6 @@ tqdm = "^4.66.3" wget = "^3.2" pyyaml = "^6.0.1" boto3 = "^1.28.46" -biopython = "^1.81" py-fasta-validator = "^0.6" python-dotenv = "^1.0.0" slack-sdk = "^3.23.0" diff --git a/src/create_blast_db.py b/src/create_blast_db.py index 5712be6..b2c9be9 100644 --- a/src/create_blast_db.py +++ b/src/create_blast_db.py @@ -11,332 +11,568 @@ import json import re -import subprocess import sys -import time from datetime import datetime from pathlib import Path -from shutil import copyfile, rmtree +from shutil import rmtree +from subprocess import PIPE, Popen from typing import Dict, List, Optional, Tuple import click -import wget import yaml -from dotenv import load_dotenv -from rich.console import Console -from rich.panel import Panel -from rich.progress import (BarColumn, Progress, SpinnerColumn, TaskID, - TextColumn) -from rich.style import Style -from rich.table import Table -from utils import (check_md5sum, check_output, edit_fasta, get_ftp_file_size, - get_mod_from_json, needs_parse_id, run_command, s3_sync, - setup_logger, slack_message) - -# Load environment variables -load_dotenv() - -console = Console() +from terminal import (create_progress, log_error, print_header, print_status, + show_summary) +from utils import (cleanup_fasta_files, copy_config_file, + extendable_logger, get_files_ftp, get_files_http, + get_mod_from_json, needs_parse_seqids, s3_sync, + setup_detailed_logger, slack_message, + update_genome_browser_map) # Global variables SLACK_MESSAGES: List[Dict[str, str]] = [] -LOGGER = setup_logger("create_blast_db", "blast_db_creation.log") - - -def store_fasta_files(fasta_file: Path) -> None: - """ - Store the downloaded FASTA files in a specific directory. - - Args: - fasta_file (Path): The path to the FASTA file that needs to be stored. - """ - date_to_add = datetime.now().strftime("%Y_%b_%d") - original_files_store = Path(f"../data/database_{date_to_add}") - original_files_store.mkdir(parents=True, exist_ok=True) - - console.log( - Panel( - f"Storing [bold]{fasta_file}[/bold] in [cyan]{original_files_store}[/cyan]", - title="File Storage", - border_style="green", - ) - ) - copyfile(fasta_file, original_files_store / fasta_file.name) - LOGGER.info(f"Stored {fasta_file} in {original_files_store}") - - -def bar_custom(current, total, width=80): - if current % (total / 100) == 0: - LOGGER.info(f"Downloading: {current/total*100:.1f}% complete") +LOGGER = setup_detailed_logger("create_blast_db", "blast_db_creation.log") def create_db_structure( - environment: str, mod: str, config_entry: Dict[str, str] -) -> Tuple[Path, Path]: + environment: str, mod: str, config_entry: Dict, logger +) -> Tuple[str, str]: """ - Create the database and folder structure for storing the downloaded FASTA files. + Creates the database and folder structure for storing the BLAST databases. Args: - environment (str): The current environment (like dev, prod, etc.). - mod (str): The model organism. - config_entry (Dict[str, str]): A dictionary containing the configuration details. + environment: The deployment environment (dev, stage, prod) + mod: The model organism database identifier + config_entry: Configuration dictionary containing database details + logger: Logger instance for tracking operations Returns: - Tuple[Path, Path]: Paths to the database and config directories. + Tuple containing paths to database and config directories """ - LOGGER.info("Creating database structure") + start_time = datetime.now() + logger.info( + f"Starting database structure creation for {config_entry['blast_title']}" + ) blast_title = config_entry["blast_title"] sanitized_blast_title = re.sub(r"\W+", "_", blast_title) + # Determine the path based on config if "seqcol" in config_entry: - LOGGER.info("seqcol found in config file") - db_path = Path( - f"../data/blast/{mod}/{environment}/databases/{config_entry['seqcol']}/{sanitized_blast_title}/" - ) + db_path = f"../data/blast/{mod}/{environment}/databases/{config_entry['seqcol']}/{sanitized_blast_title}/" + logger.info(f"Using seqcol path structure: {db_path}") else: - LOGGER.info("seqcol not found in config file") - db_path = Path( - f"../data/blast/{mod}/{environment}/databases/{config_entry['genus']}/{config_entry['species']}/{sanitized_blast_title}/" + db_path = ( + f"../data/blast/{mod}/{environment}/databases/{config_entry['genus']}/{config_entry['species']}/" + f"{sanitized_blast_title.replace(' ', '_')}/" ) + logger.info(f"Using species path structure: {db_path}") - config_path = Path(f"../data/config/{mod}/{environment}") + config_path = f"../data/config/{mod}/{environment}" - db_path.mkdir(parents=True, exist_ok=True) - config_path.mkdir(parents=True, exist_ok=True) - - console.log( - Panel( - f"Created directory: [cyan]{db_path}[/cyan]", - title="Database Structure", - border_style="blue", + # Create directories + try: + Path(db_path).mkdir(parents=True, exist_ok=True) + Path(config_path).mkdir(parents=True, exist_ok=True) + logger.info( + f"Created directory structure - DB: {db_path}, Config: {config_path}" ) - ) - LOGGER.info(f"Directory {db_path} created") + except Exception as e: + logger.error(f"Failed to create directory structure: {str(e)}") + raise + + duration = datetime.now() - start_time + logger.info(f"Database structure creation completed in {duration}") return db_path, config_path -def get_files_ftp(fasta_uri: str, md5sum: str) -> bool: - LOGGER.info(f"Downloading {fasta_uri}") +def run_makeblastdb(config_entry: Dict, output_dir: str, logger) -> bool: + """ + Runs the makeblastdb command to create a BLAST database. + """ + start_time = datetime.now() + fasta_file = Path(config_entry["uri"]).name + unzipped_fasta = f"../data/{fasta_file.replace('.gz', '')}" - today_date = datetime.now().strftime("%Y_%b_%d") - fasta_file = Path(f"../data/{Path(fasta_uri).name}") - - if (Path(f"../data/database_{today_date}") / fasta_file.name).exists(): - LOGGER.info(f"{fasta_file} already processed") - return False + logger.info(f"Starting makeblastdb process for {fasta_file}") + logger.info(f"Configuration: {json.dumps(config_entry, indent=2)}") try: - file_size = get_ftp_file_size(fasta_uri) - if file_size == 0: - LOGGER.error(f"Failed to get file size for {fasta_uri}") + # Check if unzipped FASTA exists + if not Path(unzipped_fasta).exists(): + logger.error(f"Unzipped FASTA file not found: {unzipped_fasta}") + return False - # Use a custom progress bar (or no progress bar) - wget.download(fasta_uri, str(fasta_file), bar=bar_custom) - LOGGER.info(f"Downloaded {fasta_uri}") + # Check for parse_seqids requirement + parse_ids_flag = "" + if needs_parse_seqids(unzipped_fasta): + parse_ids_flag = "-parse_seqids" + logger.info("FASTA headers require -parse_seqids flag") + + # Prepare makeblastdb command + blast_title = config_entry["blast_title"] + sanitized_blast_title = re.sub(r"\W+", "_", blast_title) + extensions = "".join(Path(fasta_file).suffixes) + + makeblast_command = ( + f"makeblastdb -in {unzipped_fasta} -dbtype {config_entry['seqtype']} " + f"-title '{sanitized_blast_title}' " + f"-out {output_dir}/{fasta_file.replace(extensions, 'db')} " + f"-taxid {config_entry['taxon_id'].replace('NCBITaxon:', '')} " + f"{parse_ids_flag}" + ).strip() + + logger.info(f"Executing makeblastdb command: {makeblast_command}") + + # Run makeblastdb + p = Popen(makeblast_command, shell=True, stdout=PIPE, stderr=PIPE) + stdout, stderr = p.communicate() + + # Log command output + if stdout: + stdout_str = stdout.decode("utf-8") + logger.info(f"makeblastdb stdout: {stdout_str}") + if stderr: + stderr_str = stderr.decode("utf-8") + logger.warning(f"makeblastdb stderr: {stderr_str}") + + if p.returncode != 0: + logger.error(f"makeblastdb command failed with return code {p.returncode}") + logger.error(f"Command: {makeblast_command}") + logger.error(f"Error output: {stderr.decode('utf-8')}") + print_status(f"makeblastdb error: {stderr.decode('utf-8')}", "error") + if Path(output_dir).exists(): + rmtree(output_dir) + return False - store_fasta_files(fasta_file) + logger.info("makeblastdb completed successfully") + duration = datetime.now() - start_time + logger.info(f"Process completed in {duration}") + + # Clean up unzipped file + if Path(unzipped_fasta).exists(): + file_size = Path(unzipped_fasta).stat().st_size + logger.info( + f"Cleaning up unzipped file: {unzipped_fasta} (size: {file_size} bytes)" + ) + Path(unzipped_fasta).unlink() + + # Clean up original gzipped file + original_gzip = f"../data/{fasta_file}" + if Path(original_gzip).exists(): + file_size = Path(original_gzip).stat().st_size + logger.info( + f"Cleaning up original gzipped file: {original_gzip} (size: {file_size} bytes)" + ) + Path(original_gzip).unlink() + + return True - if check_md5sum(fasta_file, md5sum): - LOGGER.info(f"Successfully downloaded and verified {fasta_uri}") - return True - elif fasta_uri.find("zfin") != -1: - return True - else: - LOGGER.error("MD5sums do not match") - return False except Exception as e: - LOGGER.error(f"Error downloading {fasta_uri}: {str(e)}") + logger.error(f"Error in makeblastdb process: {str(e)}", exc_info=True) + print_status(f"makeblastdb error: {str(e)}", "error") + if Path(output_dir).exists(): + rmtree(output_dir) return False -def run_makeblastdb(config_entry: Dict[str, str], output_dir: Path) -> bool: - fasta_file = Path(config_entry["uri"]).name - LOGGER.info(f"Running makeblastdb for {fasta_file}") +def list_databases_from_config(config_file: str) -> None: + """ + Lists all database names from either a YAML or JSON configuration file. + """ + print_header("Available Databases") - SLACK_MESSAGES.append( - {"title": "Running makeblastdb", "text": f"Processing {fasta_file}"} + try: + if config_file.endswith(".yaml") or config_file.endswith(".yml"): + with open(config_file) as f: + config = yaml.safe_load(f) + + for provider in config["data_providers"]: + print_header(provider["name"]) # Using header for provider names + for environment in provider["environments"]: + json_file = ( + Path(config_file).parent + / f"{provider['name']}/databases.{provider['name']}.{environment}.json" + ) + if json_file.exists(): + with open(json_file, "r") as f: + db_coordinates = json.load(f) + for entry in db_coordinates["data"]: + print_status(f"• {entry['blast_title']}", "info") + else: + print_status(f"JSON file not found - {json_file}", "warning") + + elif config_file.endswith(".json"): + with open(config_file, "r") as f: + db_coordinates = json.load(f) + for entry in db_coordinates["data"]: + print_status(f"• {entry['blast_title']}", "info") + else: + log_error("Config file must be either YAML or JSON") + + except Exception as e: + log_error("Failed to list databases", e) + + +def process_files( + config_yaml: Optional[str], + input_json: Optional[str], + environment: str, + db_list: Optional[List[str]] = None, + check_only: bool = False, + store_files: bool = False, + cleanup: bool = False, +) -> None: + """ + Process configuration files with enhanced logging. + """ + LOGGER.info("Starting configuration file processing") + LOGGER.info( + f"Parameters: check_only={check_only}, store_files={store_files}, cleanup={cleanup}" ) - gzipped_fasta = Path(f"../data/{fasta_file}") - unzipped_fasta = gzipped_fasta.with_suffix("") + try: + if config_yaml: + LOGGER.info(f"Processing YAML config: {config_yaml}") + with open(config_yaml) as f: + config = yaml.safe_load(f) + + for provider in config["data_providers"]: + provider_start = datetime.now() + LOGGER.info(f"Processing provider: {provider['name']}") - if not unzipped_fasta.exists(): - success, output = run_command(["gunzip", "-k", "-v", str(gzipped_fasta)]) - if not success: - LOGGER.error(f"Error unzipping {fasta_file}: {output}") - return False - LOGGER.info(f"Unzipping {fasta_file}: done") - - parse_id_needed = needs_parse_id(gzipped_fasta) - - sanitized_blast_title = re.sub(r"\W+", "_", config_entry["blast_title"]) - - makeblast_command = [ - "makeblastdb", - "-in", - str(unzipped_fasta), - "-dbtype", - config_entry["seqtype"], - "-title", - sanitized_blast_title, - "-out", - str(output_dir / unzipped_fasta.name.replace(".fasta", ".db")), - "-taxid", - config_entry["taxon_id"].replace("NCBITaxon:", ""), - ] - - if parse_id_needed: - makeblast_command.extend(["-parse_seqids"]) - LOGGER.info("Added -parse_seqids option to makeblastdb command") - - LOGGER.info(f"Running makeblastdb: {' '.join(makeblast_command)}") - - success, output = run_command(makeblast_command) - if success: - LOGGER.info("Makeblastdb: done") - SLACK_MESSAGES.append( - { - "title": "Makeblastdb completed", - "text": f"Successfully processed {fasta_file}", - } - ) - return True - else: - LOGGER.error(f"Error running makeblastdb: {output}") - SLACK_MESSAGES.append( - {"title": "Makeblastdb Error", "text": f"Failed to process {fasta_file}"} - ) - return False + for env in provider["environments"]: + json_file = ( + Path(config_yaml).parent + / f"{provider['name']}/databases.{provider['name']}.{env}.json" + ) + + if json_file.exists(): + LOGGER.info(f"Found JSON file: {json_file}") + process_json_entries( + str(json_file), + env, + provider["name"], + db_list, + check_only, + store_files, + cleanup, + ) + else: + LOGGER.warning(f"JSON file not found: {json_file}") + + duration = datetime.now() - provider_start + LOGGER.info( + f"Completed processing provider {provider['name']} in {duration}" + ) + + elif input_json: + LOGGER.info(f"Processing single JSON file: {input_json}") + process_json_entries( + input_json, environment, None, db_list, check_only, store_files, cleanup + ) + except Exception as e: + LOGGER.error(f"Failed to process configuration files: {str(e)}", exc_info=True) + raise -def process_yaml(config_yaml: Path) -> bool: + +def process_entry( + entry: Dict, + mod_code: str, + environment: str, + check_only: bool = False, + store_files: bool = False, +) -> bool: """ - Process a YAML file containing configuration details for multiple data providers. + Process a single database entry with comprehensive logging and progress display. Args: - config_yaml (Path): The path to the YAML file that needs to be processed. + entry: Database entry configuration + mod_code: Model organism database identifier + environment: Deployment environment + check_only: Whether to only check parse_seqids + store_files: Whether to store original files Returns: - bool: True if the YAML file was successfully processed, False otherwise. + bool: Success status """ + print_header(f"Processing {entry['blast_title']}") + start_time = datetime.now() + entry_name = entry["blast_title"] + + # Setup entry-specific logging + date_to_add = datetime.now().strftime("%Y_%b_%d") + log_path = f"../logs/{entry['genus']}_{entry['species']}_{entry['seqtype']}_{date_to_add}.log" + logger = extendable_logger(entry_name, log_path) + + logger.info(f"Starting processing of entry: {entry_name}") + logger.info( + f"Configuration details: {json.dumps({k: v for k, v in entry.items() if k != 'uri'}, indent=2)}" + ) + try: - with open(config_yaml, "r") as file: - config = yaml.safe_load(file) - - with Progress( - SpinnerColumn(), - TextColumn("[progress.description]{task.description}"), - BarColumn(), - TextColumn("[progress.percentage]{task.percentage:>3.0f}%"), - ) as progress: - main_task = progress.add_task( - "[green]Processing YAML config", total=len(config["data_providers"]) + fasta_file = Path(entry["uri"]).name + unzipped_fasta = f"../data/{fasta_file.replace('.gz', '')}" + + # Log processing parameters + print_status("Processing parameters:", "info") + print_status(f" MOD code: {mod_code}", "info") + print_status(f" Environment: {environment}", "info") + print_status(f" Check only: {check_only}", "info") + print_status(f" Store files: {store_files}", "info") + + # Download file + print_status(f"Downloading {fasta_file}...", "info") + if entry["uri"].startswith("ftp://"): + success = get_files_ftp( + entry["uri"], + entry["md5sum"], + logger, + mod=mod_code, + store_files=store_files, + ) + else: + success = get_files_http( + entry["uri"], + entry["md5sum"], + logger, + mod=mod_code, + store_files=store_files, ) - for provider in config["data_providers"]: - provider_task = progress.add_task( - f"Processing {provider['name']}", - total=len(provider["environments"]), - ) + if not success: + log_error("File download failed") + return False - for environment in provider["environments"]: - json_file = ( - config_yaml.parent - / f"{provider['name']}/databases.{provider['name']}.{environment}.json" + print_status("File download complete", "success") + + # Create database if not check_only + if not check_only: + # Create database structure + print_status("Creating database structure", "info") + output_dir, config_dir = create_db_structure( + environment, mod_code, entry, logger + ) + + # Unzip file if needed + if ( + not Path(unzipped_fasta).exists() + and Path(f"../data/{fasta_file}").exists() + ): + logger.info(f"Unzipping {fasta_file}") + print_status(f"Unzipping {fasta_file}...", "info") + unzip_command = f"gunzip -v ../data/{fasta_file}" + p = Popen(unzip_command, shell=True, stdout=PIPE, stderr=PIPE) + stdout, stderr = p.communicate() + + if p.returncode != 0: + log_error(f"Unzip failed: {stderr.decode('utf-8')}") + return False + + # Run makeblastdb + print_status("Running makeblastdb...", "info") + if not run_makeblastdb(entry, output_dir, logger): + log_error("Database creation failed") + return False + + print_status("Database created successfully", "success") + + SLACK_MESSAGES.append( + { + "title": "Database Creation Success", + "text": f"Successfully processed {entry_name}", + "color": "#36a64f", + } + ) + + # Check parse_seqids requirement if in check_only mode + elif check_only: + if Path(unzipped_fasta).exists(): + needs_parse = needs_parse_seqids(unzipped_fasta) + status = "requires" if needs_parse else "does not require" + print_status( + f"{entry_name}: {'[green]requires[/green]' if needs_parse else '[yellow]does not require[/yellow]'} -parse_seqids flag", + "info", + ) + logger.info(f"Parse seqids check: {entry_name} {status} -parse_seqids") + + # Clean up files + try: + if Path(unzipped_fasta).exists(): + if check_only or not store_files: + file_size = Path(unzipped_fasta).stat().st_size + print_status( + f"Cleaning up unzipped file: {unzipped_fasta} (size: {file_size:,} bytes)", + "info", ) - process_json(json_file, environment, provider["name"], progress) - progress.update(provider_task, advance=1) + Path(unzipped_fasta).unlink() + + original_gzip = f"../data/{fasta_file}" + if Path(original_gzip).exists() and not store_files: + file_size = Path(original_gzip).stat().st_size + print_status( + f"Cleaning up original gzipped file: {original_gzip} (size: {file_size:,} bytes)", + "info", + ) + Path(original_gzip).unlink() - progress.update(main_task, advance=1) + except Exception as e: + log_error("Cleanup failed", e) + logger.error(f"Cleanup failed: {str(e)}", exc_info=True) + # Log completion + duration = datetime.now() - start_time + logger.info(f"Entry processing completed in {duration}") return True + except Exception as e: - LOGGER.error(f"Error processing YAML file: {e}") - console.print( - Panel( - f"[bold red]Error processing YAML file:[/bold red] {e}", - title="Error", - border_style="red", - ) + log_error("Entry processing failed", e) + logger.error(f"Entry processing failed: {str(e)}", exc_info=True) + SLACK_MESSAGES.append( + { + "title": "Processing Error", + "text": f"Failed to process {entry_name}: {str(e)}", + "color": "#8D2707", + } ) return False -def process_json( - json_file: Path, +def process_json_entries( + json_file: str, environment: str, mod: Optional[str] = None, - db_info: Optional[dict] = None, + db_list: Optional[List[str]] = None, + check_only: bool = False, + store_files: bool = False, + cleanup: bool = True, ) -> bool: - LOGGER.info(f"Processing JSON file: {json_file}") + """ + Process entries from a JSON configuration file with enhanced progress display. + """ + print_header("Processing JSON Entries") + start_time = datetime.now() + LOGGER.info(f"Processing JSON entries from: {json_file}") - if mod is None: - mod = get_mod_from_json(json_file) + try: + with open(json_file, "r") as f: + db_coordinates = json.load(f) + print_status("Successfully loaded JSON configuration", "success") + + # Get MOD code + mod_code = mod if mod is not None else get_mod_from_json(json_file) + if not mod_code: + log_error("Invalid or missing MOD code") + return False - if not mod: - LOGGER.error("Unable to determine MOD") - return False + print_status(f"Using MOD code: {mod_code}", "info") - try: - with open(json_file, "r") as file: - db_coordinates = json.load(file) + # Create logs directory + Path("../logs").mkdir(parents=True, exist_ok=True) - total_entries = len(db_coordinates["data"]) - with Progress() as progress: - main_task = progress.add_task( - f"Processing {mod} - {environment}", total=total_entries - ) + # Process entries with progress tracking + entries = db_coordinates.get("data", []) + total_entries = len(entries) + processed = 0 + successful = 0 - for entry in db_coordinates["data"]: - LOGGER.info(f"Processing {entry['uri']}") - if get_files_ftp(entry["uri"], entry["md5sum"]): - output_dir, config_dir = create_db_structure( - environment, mod, entry - ) - copyfile(json_file, config_dir / "environment.json") - - if output_dir.exists(): - if run_makeblastdb(entry, output_dir): - if db_info is not None: - db_info["databases_created"].append( - { - "name": entry["blast_title"], - "type": entry["seqtype"], - "taxon_id": entry["taxon_id"], - } - ) - else: - LOGGER.error( - f"Failed to create BLAST database for {entry['uri']}" - ) - return False - progress.update(main_task, advance=1) + print_status(f"Found {total_entries} entries to process", "info") - return True - except Exception as e: - LOGGER.error(f"Error processing JSON file: {str(e)}") - return False + with create_progress() as progress: + task = progress.add_task("Processing entries...", total=total_entries) + for entry in entries: + processed += 1 -def derive_mod_from_input(input_file): - """ - Derive the MOD (Model Organism) from the input file name. + if db_list and entry["blast_title"] not in db_list: + print_status( + f"Skipping {entry['blast_title']} (not in requested list)", + "warning", + ) + progress.advance(task) + continue + + try: + if process_entry( + entry, mod_code, environment, check_only, store_files + ): + successful += 1 + except Exception as e: + log_error(f"Failed to process entry {entry['blast_title']}", e) + + progress.advance(task) + + # After all entries are processed successfully, copy the configuration file + if successful > 0 and not check_only: + print_status("Copying configuration file", "info") + config_dir = Path(f"../data/config/{mod_code}/{environment}") + if copy_config_file(Path(json_file), config_dir, LOGGER): + print_status("Configuration file copied successfully", "success") + else: + log_error("Failed to copy configuration file") + + # Update genome browser mappings after all entries are processed + print_status("Updating genome browser mappings", "info") + for entry in entries: + if "genome_browser" in entry: + if update_genome_browser_map(entry, mod_code, environment, LOGGER): + print_status( + f"Updated mapping for {entry['blast_title']}", "success" + ) + else: + log_error( + f"Failed to update mapping for {entry['blast_title']}" + ) + + # Clean up all FASTA files after processing if cleanup is enabled + if cleanup and not check_only: + print_status("Starting post-processing cleanup", "info") + try: + cleanup_fasta_files(Path("../data"), LOGGER) + print_status("Cleanup completed successfully", "success") + except Exception as e: + log_error("Cleanup failed", e) + + # Show final summary + duration = datetime.now() - start_time + show_summary( + "JSON Processing", + { + "Total Entries": total_entries, + "Processed": processed, + "Successful": successful, + "Failed": processed - successful, + "Cleanup Performed": str(cleanup and not check_only), + }, + duration, + ) - Args: - input_file (str): The path to the input file. + summary_text = ( + "*JSON Processing Summary*\n" + f"• *Total Entries:* {total_entries}\n" + f"• *Processed:* {processed}\n" + f"• *Successful:* {successful}\n" + f"• *Failed:* {processed - successful}\n" + f"• *Cleanup Performed:* {cleanup and not check_only}\n" + f"• *Duration:* {duration}" + ) - Returns: - str: The MOD (Model Organism) extracted from the input file name. If the input file name does not have the expected format or the MOD cannot be extracted, returns 'Unknown'. - """ - file_name = Path(input_file).name - parts = file_name.split('.') - if len(parts) >= 3 and parts[0] == 'databases': - return parts[1] # This should be the MOD - return 'Unknown' + SLACK_MESSAGES.append( + { + "color": "#36a64f" if successful == total_entries else "#ff9900", + "title": "Processing Summary", + "text": summary_text, + "mrkdwn_in": ["text"], + } + ) + return successful > 0 + + except Exception as e: + log_error(f"Failed to process JSON file {json_file}", e) + return False @click.command() @@ -344,72 +580,127 @@ def derive_mod_from_input(input_file): @click.option("-j", "--input_json", help="JSON file input coordinates") @click.option("-e", "--environment", help="Environment", default="dev") @click.option("-m", "--mod", help="Model organism") -@click.option("-s", "--skip_efs_sync", help="Skip EFS sync", is_flag=True, default=False) +@click.option( + "-s", "--skip_efs_sync", help="Skip EFS sync", is_flag=True, default=False +) @click.option("-u", "--update-slack", help="Update Slack", is_flag=True, default=False) @click.option("-s3", "--sync-s3", help="Sync to S3", is_flag=True, default=False) -def create_dbs(config_yaml, input_json, environment, mod, skip_efs_sync, update_slack, sync_s3): +@click.option("--store-files", help="Store original files", is_flag=True, default=False) +@click.option( + "-cl", + "--cleanup", + help="Clean up FASTA files after processing", + is_flag=True, + default=True, +) +@click.option( + "-d", + "--db_names", + help="Comma-separated list of database names to create", + default=None, +) +@click.option( + "-l", + "--list", + "list_dbs", + help="List available databases", + is_flag=True, + default=False, +) +@click.option( + "-c", + "--check-parse-seqids", + help="Only check if files need parse_seqids", + is_flag=True, + default=False, +) +def create_dbs( + config_yaml: str, + input_json: str, + environment: str, + mod: str, + skip_efs_sync: bool, + update_slack: bool, + sync_s3: bool, + store_files: bool, + cleanup: bool, + db_names: Optional[str], + list_dbs: bool, + check_parse_seqids: bool, +) -> None: """ - A command line interface function that creates BLAST databases based on the provided configuration. - - Parameters: - - config_yaml (str): YAML file with all MODs configuration. - - input_json (str): JSON file input coordinates. - - environment (str): Environment. Default is "dev". - - mod (str): Model organism. - - skip_efs_sync (bool): Skip EFS sync. Default is False. - - update_slack (bool): Update Slack. Default is False. - - sync_s3 (bool): Sync to S3. Default is False. - - Returns: - None + Main function that runs the pipeline for processing configuration files and creating BLAST databases. """ - start_time = time.time() - LOGGER.info("Starting create_dbs function") + start_time = datetime.now() + LOGGER.info("Starting BLAST database creation process") + LOGGER.info( + f"Parameters: environment={environment}, mod={mod}, store_files={store_files}, cleanup={cleanup}" + ) try: - # If mod is not provided, try to derive it from the input file - if mod is None: - mod = derive_mod_from_input(input_json or config_yaml) - - db_info = { - "mod": mod, - "environment": environment, - "databases_created": [] - } - - if config_yaml: - success = process_yaml(Path(config_yaml), db_info) - elif input_json: - success = process_json(Path(input_json), environment, db_info['mod'], db_info) + if db_names: + db_list = [name.strip() for name in db_names.split(",")] + LOGGER.info(f"Processing specific databases: {db_list}") else: - LOGGER.error("Neither config_yaml nor input_json provided") + db_list = None + LOGGER.info("Processing all databases") + + if list_dbs: + if config_yaml or input_json: + list_databases_from_config(config_yaml or input_json) + else: + msg = "Please provide either a YAML (-g) or JSON (-j) configuration file to list databases." + LOGGER.error(msg) + print_status(msg, "error") return - if not success: - LOGGER.error("Processing failed. Exiting.") + if len(sys.argv) == 1: + LOGGER.info("No arguments provided, showing help") + click.echo(create_dbs.get_help(ctx=None)) return - if update_slack: - message = f"*MOD:* {db_info['mod']}\n" - message += f"*Environment:* {db_info['environment']}\n" - message += f"*Databases created:*\n" - for db in db_info['databases_created']: - message += f"• *{db['name']}* (Type: `{db['type']}`, Taxon ID: `{db['taxon_id']}`)\n" + if config_yaml: + LOGGER.info(f"Processing YAML config: {config_yaml}") + process_files( + config_yaml, + None, + None, + db_list, + check_parse_seqids, + store_files, + cleanup, + ) + elif input_json: + LOGGER.info(f"Processing JSON config: {input_json}") + process_files( + None, + input_json, + environment, + db_list, + check_parse_seqids, + store_files, + cleanup, + ) - slack_success = slack_message([{"text": message}], subject="BLAST Database Update") - LOGGER.info(f"Slack update {'successful' if slack_success else 'failed'}") + # Handle Slack updates with better error checking + if update_slack and not check_parse_seqids and SLACK_MESSAGES: + try: + LOGGER.info("Sending Slack update") + slack_message(SLACK_MESSAGES) + except Exception as e: + log_error("Failed to send Slack update - check SLACK token in .env", e) - if sync_s3: - s3_success = s3_sync(Path("../data"), skip_efs_sync) - LOGGER.info(f"S3 sync {'successful' if s3_success else 'failed'}") + if sync_s3 and not check_parse_seqids: + LOGGER.info("Starting S3 sync") + s3_sync(Path("../data"), skip_efs_sync) - except Exception as e: - LOGGER.error(f"Unhandled exception in create_dbs: {str(e)}", exc_info=True) - finally: - end_time = time.time() - duration = end_time - start_time - LOGGER.info(f"create_dbs function completed in {duration:.2f} seconds") + duration = datetime.now() - start_time + LOGGER.info(f"Process completed successfully in {duration}") + except Exception as e: + LOGGER.error(f"Process failed: {str(e)}", exc_info=True) + log_error(str(e)) + sys.exit(1) if __name__ == "__main__": diff --git a/src/terminal.py b/src/terminal.py new file mode 100644 index 0000000..7b59ecb --- /dev/null +++ b/src/terminal.py @@ -0,0 +1,101 @@ +""" +terminal.py + +This module provides terminal output utilities using the Rich library for consistent +and informative console output throughout the application. +""" + +from datetime import datetime +from typing import Any, Dict, Optional + +from rich import box +from rich.console import Console +from rich.panel import Panel +from rich.progress import (BarColumn, Progress, SpinnerColumn, + TaskProgressColumn, TextColumn) +from rich.table import Table + +console = Console() + + +def print_status(message: str, status: str = "info") -> None: + """ + Prints a status message with an appropriate style. + Status can be: info, success, error, warning + """ + styles = { + "info": "blue", + "success": "green", + "error": "red", + "warning": "yellow", + } + + icons = { + "info": "ℹ", + "success": "✓", + "error": "✗", + "warning": "⚠", + } + + style = styles.get(status, "default") + icon = icons.get(status, "→") + console.print(f"{icon} {message}", style=style) + + +def create_progress() -> Progress: + """ + Creates a consistent progress bar style for the application. + """ + return Progress( + SpinnerColumn(), + TextColumn("[blue]{task.description}"), + BarColumn(complete_style="green"), + TaskProgressColumn(), + console=console, + ) + + +def show_summary( + operation: str, + stats: Dict[str, Any], + duration: datetime, + details: Optional[str] = None, +) -> None: + """ + Shows a summary of the completed operation with statistics. + """ + table = Table(box=box.ROUNDED) + table.add_column("Metric", style="cyan") + table.add_column("Value", style="white") + + for key, value in stats.items(): + if isinstance(value, (int, float)): + formatted_value = f"{value:,}" + else: + formatted_value = str(value) + table.add_row(key, formatted_value) + + table.add_row("Duration", str(duration)) + + panel = Panel(table, title=f"[bold blue]{operation} Summary", border_style="blue") + console.print(panel) + + if details: + console.print(details, style="dim") + + +def log_error(error_message: str, error: Optional[Exception] = None) -> None: + """ + Displays an error message with optional exception details. + """ + console.print(f"[red]Error:[/red] {error_message}") + if error: + console.print(f"[dim red]Details: {str(error)}[/dim red]") + + +def print_header(text: str) -> None: + """ + Prints a section header. + """ + console.print(f"\n[bold blue]{text}[/bold blue]") + console.print("[blue]" + "─" * len(text) + "[/blue]") diff --git a/src/utils.py b/src/utils.py index 1541bad..77ae5ba 100644 --- a/src/utils.py +++ b/src/utils.py @@ -9,135 +9,219 @@ Date: started September 2023 """ -import gzip import hashlib +import json import logging +import re +from datetime import datetime from ftplib import FTP -from logging.handlers import RotatingFileHandler from pathlib import Path -from subprocess import PIPE, CalledProcessError, Popen, run -from typing import Any, List, Tuple +from shutil import copyfile +from subprocess import PIPE, Popen +from typing import Any, Optional +import wget from dotenv import dotenv_values +from rich import print as rprint from rich.console import Console from slack_sdk import WebClient from slack_sdk.errors import SlackApiError -from slack_sdk.webhook import WebhookClient -console = Console() +from terminal import create_progress, log_error, print_status -# Define LOGGER at the top of utils.py -LOGGER = logging.getLogger(__name__) +console = Console() # TODO: move to ENV MODS = ["FB", "SGD", "WB", "XB", "ZFIN"] -def extendable_logger(log_name, file_name, level=logging.INFO) -> Any: +def copy_config_file(json_file: Path, config_dir: Path, logger) -> bool: """ - Creates a logger that can be extended with additional handlers and configurations. + Copies the configuration file to the config directory. + """ + try: + # Ensure config directory exists + config_dir.mkdir(parents=True, exist_ok=True) + + # Copy the JSON configuration file + target_file = config_dir / "environment.json" + target_file.write_text(json_file.read_text()) + logger.info(f"Copied configuration file to {target_file}") + + return True + except Exception as e: + logger.error(f"Failed to copy configuration file: {str(e)}") + return False - This function sets up a logger with a specified name, log file, and logging level. The logger uses a file handler to write log messages to a file. The log messages are formatted to include the timestamp, log level, and the log message. - :param log_name: The name of the logger. - :type log_name: str - :param file_name: The name of the file where the log messages will be written. - :type file_name: str - :param level: The logging level. By default, it's set to logging.INFO. - :type level: int, optional - :return: The configured logger. - :rtype: logging.Logger +def setup_detailed_logger( + log_name: str, file_name: str, level=logging.INFO +) -> logging.Logger: """ + Creates a detailed logger with comprehensive formatting. + """ + formatter = logging.Formatter( + "[%(asctime)s] %(levelname)s [%(name)s.%(funcName)s:%(lineno)d] - %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + ) - formatter = logging.Formatter("[%(asctime)s] %(levelname)s %(message)s") + logger = logging.getLogger(log_name) + logger.setLevel(level) + + # Prevent duplicate handlers + if logger.handlers: + return logger + + # File handler handler = logging.FileHandler(file_name) handler.setFormatter(formatter) - specified_logger = logging.getLogger(log_name) - specified_logger.setLevel(level) - specified_logger.addHandler(handler) + logger.addHandler(handler) - return specified_logger + return logger -def check_md5sum(fasta_file, md5sum) -> bool: +def store_fasta_files(fasta_file: str, logger, store_files: bool = False) -> None: """ - Checks the MD5 checksum of a downloaded file. + Stores FASTA files in a dated directory if storage is enabled. + + Args: + fasta_file (str): Path to the FASTA file + logger (logging.Logger): Logger instance + store_files (bool): Whether to store the file + """ + if not store_files: + logger.info(f"File storage disabled, skipping storage of {fasta_file}") + return + + date_to_add = datetime.now().strftime("%Y_%b_%d") + original_files_store = Path(f"../data/database_{date_to_add}") + + try: + if not original_files_store.exists(): + logger.info(f"Creating storage directory: {original_files_store}") + original_files_store.mkdir(parents=True, exist_ok=True) + + file_size = Path(fasta_file).stat().st_size + dest_path = original_files_store / Path(fasta_file).name + + logger.info( + f"Storing file {fasta_file} (size: {file_size} bytes) to {dest_path}" + ) + copyfile(fasta_file, dest_path) + logger.info("File stored successfully") + + except Exception as e: + logger.error(f"Failed to store file {fasta_file}: {str(e)}", exc_info=True) + # Don't raise the exception - make storage truly optional + logger.warning("Continuing process despite storage failure") - This function calculates the MD5 checksum of the downloaded file and compares it with the expected checksum. If the checksums match, the function returns True. Otherwise, it returns False. - :param fasta_file: The path to the downloaded file. - :type fasta_file: str - :param md5sum: The expected MD5 checksum. - :type md5sum: str - :return: True if the checksums match, False otherwise. - :rtype: bool +def cleanup_fasta_files(data_dir: Path, logger) -> None: """ + Cleans up all FASTA files in the specified directory after database generation. + """ + logger.info(f"Starting cleanup of FASTA files in {data_dir}") + print_status("Starting final cleanup...", "info") - downloaded_md5sum = hashlib.md5(open(fasta_file, "rb").read()).hexdigest() - if downloaded_md5sum != md5sum: - console.log(f"MD5sums do not match: {md5sum} != {downloaded_md5sum}") - return False + try: + # Find all FASTA files (both gzipped and uncompressed) + fasta_patterns = ["*.fa*", "*.fasta*", "*.fna*", "*.gz"] + fasta_files = [] + for pattern in fasta_patterns: + fasta_files.extend(list(data_dir.glob(pattern))) + + if not fasta_files: + logger.info("No FASTA files found for cleanup") + print_status("No files to clean up", "info") + return + + logger.info(f"Found {len(fasta_files)} files to clean up") + print_status(f"Found {len(fasta_files)} files to clean up", "info") + + with create_progress() as progress: + cleanup_task = progress.add_task( + "Cleaning up files...", total=len(fasta_files) + ) - console.log(f"MD5sums match: {md5sum} {downloaded_md5sum}") + for fasta_file in fasta_files: + try: + file_size = fasta_file.stat().st_size + logger.info( + f"Removing {fasta_file.name} (size: {file_size:,} bytes)" + ) + fasta_file.unlink() + logger.info(f"Successfully removed {fasta_file.name}") + except Exception as e: + logger.error(f"Failed to remove {fasta_file.name}: {str(e)}") + print_status(f"Failed to remove {fasta_file.name}", "warning") - return True + progress.advance(cleanup_task) + print_status("Cleanup completed successfully", "success") + logger.info("FASTA file cleanup completed") -def get_ftp_file_size(fasta_uri, file_logger) -> int: + except Exception as e: + error_msg = f"Error during FASTA cleanup: {str(e)}" + logger.error(error_msg, exc_info=True) + print_status(error_msg, "error") + + +def extendable_logger(log_name, file_name, level=logging.INFO) -> Any: + """ + Creates a logger that can be extended with additional handlers and configurations. """ - Function to get the size of a file on an FTP server. + formatter = logging.Formatter("[%(asctime)s] %(levelname)s %(message)s") + handler = logging.FileHandler(file_name) + handler.setFormatter(formatter) + specified_logger = logging.getLogger(log_name) + specified_logger.setLevel(level) + specified_logger.addHandler(handler) + + return specified_logger - This function connects to an FTP server, navigates to the directory containing the file, and retrieves the size of the file. - :param fasta_uri: The URI of the FASTA file on the FTP server. - :type fasta_uri: str - :param file_logger: The logger object used for logging the process of getting the file size. - :type file_logger: logging.Logger - :return: The size of the file in bytes. - :rtype: int +def check_md5sum(fasta_file: str, expected_md5: str, logger) -> bool: """ + Checks MD5 checksum of a file with detailed logging. - # Initialize the size to 0 - size = 0 + Args: + fasta_file (str): Path to the file + expected_md5 (str): Expected MD5 checksum + logger (logging.Logger): Logger instance + + Returns: + bool: True if checksums match, False otherwise + """ + logger.info(f"Calculating MD5 checksum for {fasta_file}") + try: + with open(fasta_file, "rb") as f: + file_size = Path(fasta_file).stat().st_size + logger.info(f"File size: {file_size} bytes") - # Connect to the FTP server - ftp = FTP(Path(fasta_uri).parts[1]) - ftp.login() + # Calculate MD5 + start_time = datetime.now() + calculated_md5 = hashlib.md5(f.read()).hexdigest() + duration = datetime.now() - start_time - # Navigate to the directory containing the file - ftp.cwd("/".join(Path(fasta_uri).parts[2:-1])) + logger.info(f"MD5 calculation completed in {duration}") + logger.info(f"Expected MD5: {expected_md5}") + logger.info(f"Calculated MD5: {calculated_md5}") - # Get the name of the file - filename = Path(fasta_uri).name + if calculated_md5 != expected_md5: + logger.error("MD5 checksums do not match") + return False - if filename is not None: - # Get the size of the file - size = ftp.size(filename) - if size is not None: - # Log the size of the file - console.log(f"File size is {size} bytes") - file_logger.info(f"File size is {size} bytes") - else: - # Handle the case where size is None - console.log("Error: File size is not available.") - return 0 - else: - console.log("Error: Filename is None.") - return 0 + logger.info("MD5 checksums match") + return True - return size + except Exception as e: + logger.error(f"MD5 checksum verification failed: {str(e)}", exc_info=True) + return False def get_mod_from_json(input_json) -> str: """ Retrieves the model organism (mod) from the input JSON file. - - This function extracts the mod from the filename of the input JSON file. The mod is the second element when the filename is split by the "." character. If the mod is not found in the predefined list of mods, the function returns False. Otherwise, it returns the mod. - - :param input_json: The path to the input JSON file. - :type input_json: str - :return: The model organism (mod) if found, False otherwise. - :rtype: str or bool """ filename = Path(input_json).name mod = filename.split(".")[1] @@ -147,85 +231,73 @@ def get_mod_from_json(input_json) -> str: return False console.log(f"Mod found: {mod}") - return mod def edit_fasta(fasta_file: str, config_entry: dict) -> bool: """ Edits the FASTA file based on the configuration entry. - - This function opens the FASTA file, reads the lines, and modifies the header lines to include additional information from the configuration entry. The modified lines are then written back to the FASTA file. - - :param fasta_file: The path to the FASTA file to be edited. - :type fasta_file: str - :param config_entry: The configuration entry containing the additional information to be added to the FASTA file. - :type config_entry: dict - :return: True if the FASTA file was successfully edited, False otherwise. - :rtype: bool """ - - # Initialize a list to store the original file lines original_file = [] - # Open the FASTA file and read the lines with open(fasta_file, "r") as fh: lines = fh.readlines() - # Iterate over the lines for line in lines: - # Check if the line is a header line if line.startswith(">"): - # Strip the newline character from the line line = line.strip() - - # Check if 'seqcol' is in the configuration entry if "seqcol" in config_entry.keys(): - # If so, append the 'seqcol', 'genus', and 'species' values to the line line += f" {config_entry['seqcol']} {config_entry['genus']} {config_entry['species']}\n" else: - # If not, append the 'genus', 'species', and 'version' values to the line line += f" {config_entry['genus']} {config_entry['species']} {config_entry['version']}\n" - - # Add the modified line to the original file list original_file.append(line) else: - # If the line is not a header line, add it to the original file list as is original_file.append(line) - # Open the FASTA file in write mode edited_file = open(fasta_file, "w") - - # Write the lines from the original file list to the FASTA file edited_file.writelines(original_file) - - # Close the FASTA file edited_file.close() return True -def s3_sync(path_to_copy: Path, skip_efs_sync: bool) -> bool: +def validate_fasta(filename: str) -> bool: """ - Syncs files from a local directory to an S3 bucket. + Validates if a file is in FASTA format without using Biopython. + """ + try: + with open(filename, "r") as f: + first_line = f.readline().strip() + if not first_line: + return False - This function uses the AWS CLI to sync files from a local directory to an S3 bucket. It excludes any temporary files during the sync process. If the `skip_efs_sync` flag is not set, it also syncs the files to an EFS volume. + if not first_line.startswith(">"): + return False - :param path_to_copy: The path to the local directory to be synced to the S3 bucket. - :type path_to_copy: Path - :param skip_efs_sync: A flag indicating whether to skip syncing to the EFS volume. - :type skip_efs_sync: bool - :return: True if the sync operation was successful, False otherwise. - :rtype: bool - """ + has_sequence = False + for line in f: + line = line.strip() + if line.startswith(">"): + if not has_sequence: + return False + has_sequence = False + elif line: # sequence line + has_sequence = True - # Load environment variables from .env file - env = dotenv_values(f"{Path.cwd()}/.env") + return has_sequence - # Log the start of the S3 sync process + except Exception as e: + console.log(f"[red]Error validating FASTA file: {e}[/red]") + return False + + +def s3_sync(path_to_copy: Path, skip_efs_sync: bool) -> bool: + """ + Syncs files from a local directory to an S3 bucket. + """ + env = dotenv_values(f"{Path.cwd()}/.env") console.log(f"Syncing {path_to_copy} to S3") - # Construct the AWS CLI command to sync files to the S3 bucket proc = Popen( [ "aws", @@ -242,7 +314,6 @@ def s3_sync(path_to_copy: Path, skip_efs_sync: bool) -> bool: stderr=PIPE, ) - # Process the output of the AWS CLI command while True: output = proc.stderr.readline().strip() if output == b"": @@ -250,13 +321,9 @@ def s3_sync(path_to_copy: Path, skip_efs_sync: bool) -> bool: else: console.log(output.decode("utf-8")) - # Wait for the AWS CLI command to complete proc.wait() - - # Log the completion of the S3 sync process console.log(f"Syncing {path_to_copy} to S3: done") - # If the skip_efs_sync flag is not set, sync the files to the EFS volume if not skip_efs_sync: sync_to_efs() @@ -266,207 +333,430 @@ def s3_sync(path_to_copy: Path, skip_efs_sync: bool) -> bool: def sync_to_efs() -> bool: """ Syncs files from an S3 bucket to an EFS volume. - - This function uses the AWS CLI to sync files from an S3 bucket to an EFS volume. It excludes any temporary files during the sync process. - - :return: True if the sync operation was successful, False otherwise. - :rtype: bool """ - - # Load environment variables from .env file env = dotenv_values(f"{Path.cwd()}/.env") - - # Log the start of the EFS sync process console.log(f"Syncing {env['S3']} to {env['EFS']}") - # Get the S3 and EFS paths from the environment variables s3_path = env.get("S3") efs_path = env.get("EFS") - # Check if the S3 and EFS paths are not None if s3_path is not None and efs_path is not None: - # If so, construct the AWS CLI command to sync files to the EFS volume proc = Popen( ["aws", "s3", "sync", s3_path, efs_path, "--exclude", "*.tmp"], stdout=PIPE, stderr=PIPE, ) else: - # If not, log that the S3 or EFS path is not defined in the environment variables console.log("S3 or EFS path is not defined in the environment variables") + return False - # Process the output of the AWS CLI command while True: - # Read a line from stderr and decode it to utf-8 if proc.stderr is not None: output = proc.stderr.readline().decode("utf-8").strip() - # Process output further if needed - else: - # Handle the case when proc.stderr is None - output = "No output available" + if not output: + break console.log(output) + else: + break - # Wait for the AWS CLI command to complete proc.wait() - - # Log the completion of the EFS sync process console.log(f"Syncing {env['S3']} to {env['EFS']}: done") - return True def check_output(stdout: bytes, stderr: bytes) -> bool: """ - Check the output of a subprocess for errors. - - Args: - stdout (bytes): Standard output from the subprocess. - stderr (bytes): Standard error from the subprocess. - - Returns: - bool: True if no errors were found, False otherwise. + Checks the output of a command for errors. """ - stderr_str = stderr.decode("utf-8") - if stderr_str and "Error" in stderr_str: - console.log( - f"Error in subprocess output: {stderr_str}", style="blink bold white on red" - ) - return False + stderr = stderr.decode("utf-8") + if len(stderr) > 1: + if stderr.find("Error") >= 1: + console.log(stderr, style="blink bold white on red") + return False return True -def run_command(command: List[str]) -> Tuple[bool, str]: +def slack_message(messages: list, subject="BLAST Database Update") -> bool: + """ + Sends a message to a Slack channel using the Slack API. + If no Slack configuration is found, skips silently. """ - Run a shell command and return its output. + env = dotenv_values(f"{Path.cwd()}/.env") - Args: - command (List[str]): The command to run as a list of strings. + # Check if Slack token is configured + if "SLACK" not in env: + print_status("Skipping Slack update - no Slack token configured", "warning") + return True - Returns: - Tuple[bool, str]: A tuple containing a boolean indicating success and the command output. - """ try: - result = run(command, check=True, capture_output=True, text=True) - return True, result.stdout - except CalledProcessError as e: - return False, f"Command failed with error: {e.stderr}" - + client = WebClient(token=env["SLACK"]) + response = client.chat_postMessage( + channel="#blast-status", + text=subject, + attachments=messages, + ) + print_status("Slack message sent successfully", "success") + return True -def needs_parse_id(fasta_file: Path) -> bool: - """ - Determine if the FASTA file needs parse_id option for makeblastdb. + except SlackApiError as e: + log_error(f"Failed to send Slack message: {e.response['error']}") + return False + except Exception as e: + log_error("Unexpected error sending Slack message", e) + return False - Args: - fasta_file (Path): Path to the gzipped FASTA file - Returns: - bool: True if parse_id is needed, False otherwise +def needs_parse_seqids(fasta_file: str) -> bool: + """ + Determines if a FASTA file needs the -parse_seqids flag by examining its headers. """ - open_func = gzip.open if fasta_file.suffix == ".gz" else open - mode = "rt" if fasta_file.suffix == ".gz" else "r" + id_patterns = [ + r"^>.*\|.*\|", + r"^>lcl\|", + r"^>ref\|", + r"^>gb\|", + r"^>emb\|", + r"^>dbj\|", + r"^>pir\|", + r"^>prf\|", + r"^>sp\|", + r"^>pdb\|", + r"^>pat\|", + r"^>bbs\|", + r"^>gnl\|", + r"^>gi\|", + ] + + patterns = [re.compile(pattern) for pattern in id_patterns] - with open_func(fasta_file, mode) as f: - headers = [next(f).strip() for _ in range(100) if next(f).startswith(">")] + try: + with open(fasta_file, "r") as f: + for line in f: + if line.startswith(">"): + if any(pattern.match(line) for pattern in patterns): + return True + except Exception as e: + console.log(f"Warning: Error checking FASTA headers: {e}") + return True - # Analyze headers here - complex_headers = any("|" in header for header in headers) - consistent_format = len(set(header.count("|") for header in headers)) == 1 + return False - return complex_headers and consistent_format +def get_files_http( + file_uri: str, + md5sum: str, + logger, + mod: Optional[str] = None, + store_files: bool = False, +) -> bool: + """ + Downloads files from HTTP/HTTPS sites with controlled output. + """ + start_time = datetime.now() + logger.info(f"Starting HTTP download from: {file_uri}") -def setup_logger(name, log_file, level=logging.INFO): - """Function to set up a logger with file and console handlers.""" - formatter = logging.Formatter("%(asctime)s %(levelname)s %(message)s") + try: + file_name = f"../data/{Path(file_uri).name}" + logger.info(f"Download target: {file_name}") + + # Download file with quiet output + download_start = datetime.now() + wget.download(file_uri, file_name, bar=None) # Suppress wget progress bar + print() # Add newline after download + download_duration = datetime.now() - download_start + + # Rest of the function remains the same + file_size = Path(file_name).stat().st_size + logger.info( + f"Download completed | Size: {file_size:,} bytes | " + f"Duration: {download_duration} | " + f"Speed: {file_size / download_duration.total_seconds() / 1024:.2f} KB/s" + ) - # File Handler - file_handler = RotatingFileHandler( - log_file, maxBytes=10 * 1024 * 1024, backupCount=5 - ) - file_handler.setFormatter(formatter) + if store_files: + logger.info("Storing original file (store_files=True)") + store_fasta_files(file_name, logger) - # Console Handler - console_handler = logging.StreamHandler() - console_handler.setFormatter(formatter) + if mod != "ZFIN": + logger.info(f"Verifying MD5 checksum: expected={md5sum}") + if not check_md5sum(file_name, md5sum, logger): + logger.error("MD5 checksum verification failed") + return False + logger.info("MD5 checksum verified successfully") + else: + logger.info("Skipping MD5 check for ZFIN") - logger = logging.getLogger(name) - logger.setLevel(level) - logger.addHandler(file_handler) - logger.addHandler(console_handler) + return True - return logger + except Exception as e: + logger.error(f"Download failed: {str(e)}", exc_info=True) + return False -def slack_message(messages: list, subject="BLAST Database Update") -> bool: +def get_files_ftp( + fasta_uri: str, + md5sum: str, + logger, + mod: Optional[str] = None, + store_files: bool = False, +) -> bool: """ - Sends a message to a Slack channel using the Slack API. - - :param messages: The list of messages to be posted to the Slack channel. - :type messages: list - :param subject: The subject of the message. By default, it's set to "BLAST Database Update". - :type subject: str, optional - :return: True if the message was successfully posted, False otherwise. - :rtype: bool + Downloads files from FTP sites with controlled output. """ - # Load environment variables from .env file - env = dotenv_values(f"{Path.cwd()}/.env") - - # Create a WebClient object with the Slack API token - client = WebClient(token=env["SLACK"]) + start_time = datetime.now() + logger.info(f"Starting FTP download from: {fasta_uri}") try: - for msg in messages: - blocks = [ - { - "type": "header", - "text": {"type": "plain_text", "text": subject, "emoji": True}, - }, - {"type": "section", "text": {"type": "mrkdwn", "text": msg["text"]}}, - {"type": "divider"}, - ] - - # Call the chat.postMessage method using the WebClient - response = client.chat_postMessage( - channel="#blast-status", # Channel to send message to - blocks=blocks, - text=subject, # Fallback text for notifications + ftp_host = Path(fasta_uri).parts[1] + ftp_path = "/".join(Path(fasta_uri).parts[2:-1]) + fasta_file = f"../data/{Path(fasta_uri).name}" + fasta_name = Path(fasta_uri).name + + logger.info("FTP Details:") + logger.info(f" Host: {ftp_host}") + logger.info(f" Path: {ftp_path}") + logger.info(f" File: {fasta_name}") + logger.info(f"Local target: {fasta_file}") + + if store_files: + date_to_add = datetime.now().strftime("%Y_%b_%d") + stored_path = Path(f"../data/database_{date_to_add}/{fasta_name}") + if stored_path.exists(): + logger.info(f"File already exists in storage: {stored_path}") + return False + + # Get remote file size + try: + remote_size = get_ftp_file_size(fasta_uri, logger) + logger.info(f"Remote file size: {remote_size:,} bytes") + except Exception as e: + logger.warning(f"Could not get remote file size: {str(e)}") + remote_size = None + + # Download file with quiet output + download_start = datetime.now() + logger.info("Starting file download") + + try: + wget.download(fasta_uri, fasta_file, bar=None) # Suppress wget progress bar + print() # Add newline after download + download_duration = datetime.now() - download_start + + # Rest of the verification code... + if Path(fasta_file).exists(): + local_size = Path(fasta_file).stat().st_size + logger.info( + f"Download completed:\n" + f" Duration: {download_duration}\n" + f" Local size: {local_size:,} bytes\n" + f" Speed: {local_size / download_duration.total_seconds() / 1024:.2f} KB/s" + ) + + if remote_size and remote_size != local_size: + logger.error( + f"Size mismatch - Remote: {remote_size:,} bytes, Local: {local_size:,} bytes" + ) + return False + else: + logger.error("Downloaded file not found") + return False + + except Exception as e: + logger.error(f"Download failed: {str(e)}", exc_info=True) + return False + + # Rest of the function remains the same... + if store_files: + logger.info("Storing original file (store_files=True)") + try: + store_fasta_files(fasta_file, logger, store_files) + logger.info("File stored successfully") + except Exception as e: + logger.error(f"File storage failed: {str(e)}", exc_info=True) + return False + + if mod == "ZFIN": + logger.info("Skipping MD5 check for ZFIN") + return True + + logger.info(f"Verifying MD5 checksum: expected={md5sum}") + if check_md5sum(fasta_file, md5sum, logger): + logger.info("MD5 checksum verification successful") + duration = datetime.now() - start_time + logger.info( + f"FTP download and verification completed successfully in {duration}" + ) + return True + else: + logger.error( + f"MD5 checksum verification failed:\n" + f" File: {fasta_file}\n" + f" Expected: {md5sum}" ) + return False - LOGGER.info("Successfully sent message to Slack channel") - return True - except SlackApiError as e: - LOGGER.error(f"Error sending message to Slack: {e.response['error']}") + except Exception as e: + logger.error( + f"FTP download process failed:\n" + f" URI: {fasta_uri}\n" + f" Error: {str(e)}", + exc_info=True, + ) return False -def get_ftp_file_size(fasta_uri: str) -> int: +def get_ftp_file_size(fasta_uri: str, logger) -> int: """ - Get the size of a file on an FTP server. + Gets the size of a file on an FTP server with enhanced logging. Args: - fasta_uri (str): The URI of the FASTA file on the FTP server. + fasta_uri (str): FTP URI of the file + logger (logging.Logger): Logger instance Returns: - int: The size of the file in bytes, or 0 if size couldn't be determined. + int: Size of the file in bytes """ + logger.info(f"Getting file size from FTP: {fasta_uri}") + try: - ftp_parts = fasta_uri.split("/") - ftp_server = ftp_parts[2] - ftp_path = "/".join(ftp_parts[3:-1]) - filename = ftp_parts[-1] + # Parse FTP URI + ftp_host = Path(fasta_uri).parts[1] + ftp_path = "/".join(Path(fasta_uri).parts[2:-1]) + filename = Path(fasta_uri).name - with FTP(ftp_server) as ftp: - ftp.login() - ftp.cwd(ftp_path) - size = ftp.size(filename) + logger.info(f"Connecting to FTP server: {ftp_host}") + + # Connect to FTP server + ftp = FTP(ftp_host) + ftp.login() + + logger.info(f"Navigating to directory: {ftp_path}") + ftp.cwd(ftp_path) + + # Get file size + size = ftp.size(filename) if size is not None: - console.log(f"File size for {filename} is {size} bytes") + logger.info(f"File size retrieved: {size:,} bytes") + ftp.quit() return size else: - console.log(f"Couldn't determine size for {filename}") + logger.error("File size not available") + ftp.quit() return 0 except Exception as e: - console.log(f"Error getting FTP file size: {e}") + logger.error(f"Failed to get FTP file size: {str(e)}", exc_info=True) return 0 + + +def update_genome_browser_map( + config_entry: dict, mod: str, environment: str, logger +) -> bool: + """ + Updates genome browser mappings for both Ruby and JSON formats. + """ + + def log_and_print(message: str, level: str = "info"): + """Helper to both log and print messages""" + if level == "error": + logger.error(message) + rprint(f"[red]ERROR: {message}[/red]") + elif level == "warning": + logger.warning(message) + rprint(f"[yellow]WARNING: {message}[/yellow]") + else: + logger.info(message) + rprint(f"[blue]INFO: {message}[/blue]") + + try: + # Debug current directory + current_dir = Path.cwd() + log_and_print(f"Current working directory: {current_dir}") + + # Skip if no genome browser info + if "genome_browser" not in config_entry: + log_and_print("No genome browser info found in entry, skipping", "warning") + return True + + # Get filename and browser URL for current entry + filename = Path(config_entry["uri"]).name + browser_url = config_entry["genome_browser"]["url"] + log_and_print(f"Processing: {filename} -> {browser_url}") + + # Define target directory with correct path and create if needed + target_dir = Path("../data/config") / mod / environment + target_dir.mkdir(parents=True, exist_ok=True) + log_and_print( + f"Target directory: {target_dir.absolute()} (exists: {target_dir.exists()})" + ) + + # Define file paths + json_file = target_dir / "genome_browser_map.json" + ruby_file = target_dir / "genome_browser_map.rb" + log_and_print( + f"Will write to:\n JSON: {json_file.absolute()}\n Ruby: {ruby_file.absolute()}" + ) + + # Load existing mappings from JSON if it exists + mapping = {} + if json_file.exists(): + try: + with open(json_file, "r") as f: + content = f.read() + log_and_print(f"Existing JSON content: {content[:100]}...") + if content.strip(): + mapping = json.loads(content) + log_and_print(f"Loaded {len(mapping)} existing mappings") + except Exception as e: + log_and_print( + f"Starting fresh due to error reading JSON: {e}", "warning" + ) + + # Add new mapping + mapping[filename] = browser_url + log_and_print(f"Added new mapping. Total mappings now: {len(mapping)}") + + # Write JSON file + try: + json_content = json.dumps(mapping, indent=2, sort_keys=True) + log_and_print(f"Writing JSON content: {json_content[:100]}...") + with open(json_file, "w") as f: + f.write(json_content) + log_and_print( + f"Wrote JSON file: {json_file} (size: {json_file.stat().st_size} bytes)" + ) + except Exception as e: + log_and_print(f"Failed to write JSON file: {e}", "error") + return False + + # Write Ruby file + try: + ruby_content = "GENOME_BROWSER_MAP = {\n" + for fname, url in sorted(mapping.items()): + ruby_content += f" '{fname}' => '{url}',\n" + ruby_content += "}.freeze\n" + + log_and_print(f"Writing Ruby content: {ruby_content[:100]}...") + with open(ruby_file, "w") as f: + f.write(ruby_content) + log_and_print( + f"Wrote Ruby file: {ruby_file} (size: {ruby_file.stat().st_size} bytes)" + ) + except Exception as e: + log_and_print(f"Failed to write Ruby file: {e}", "error") + return False + + # Final verification + if not json_file.exists() or not ruby_file.exists(): + log_and_print("One or both files missing after writing!", "error") + log_and_print(f"JSON exists: {json_file.exists()}", "error") + log_and_print(f"Ruby exists: {ruby_file.exists()}", "error") + return False + + log_and_print("✓ Successfully updated both mapping files") + return True + + except Exception as e: + log_and_print(f"Failed to update mapping: {str(e)}", "error") + return False diff --git a/tests/CLI/config.json b/tests/CLI/config.json new file mode 100644 index 0000000..7a5dd66 --- /dev/null +++ b/tests/CLI/config.json @@ -0,0 +1,236 @@ +{ + "SGD": { + "main": { + "url": "https://blast.alliancegenome.org/blast/SGD/main", + "nucl": "ATGGATTCTGGTATGTTCTAGCGCTTGCACCATCCCATTTAACTGTAAGAAGAATTGCACGGTCCCAATTGCTCGAGAGATTTCTCTTTTACCTTTTTTTACTATTTTTCACTCTCCCATAACCTCCTATATTGACTGATCTGTAATAACCACGATATTATTGGAATAAATAGGGGCTTGAAATTTGGAAAAAAAAAAAAAACTGAAATATTTTCGTGATAAGTGATAGTGATATTCTTCTTTTATTTGCTACTGTTACTAAGTCTCATGTACTAACATCGATTGCTTCATTCTTTTTGTTGCTATATTATATGTTTAGAGGTTGCTGCTTTGGTTATTGATAACGGTTCTGGTATGTGTAAAGCCGGTTTTGCCGGTGACGACGCTCCTCGTGCTGTCTTCCCATCTATCGTCGGTAGACCAAGACACCAAGGTATCATGGTCGGTATGGGTCAAAAAGACTCCTACGTTGGTGATGAAGCTCAATCCAAGAGAGGTATCTTGACTTTACGTTACCCAATTGAACACGGTATTGTCACCAACTGGGACGATATGGAAAAGATCTGGCATCATACCTTCTACAACGAATTGAGAGTTGCCCCAGAAGAACACCCTGTTCTTTTGACTGAAGCTCCAATGAACCCTAAATCAAACAGAGAAAG", + "prot": "MDSEVAALVIDNGSGMCKAGFAGDDAPRAVFPSIVGRPRHQGIMVGMGQKDSYVGDEAQSKRGILTLRYPIEHGIVTNWDDMEKIWHHTFYNELRVAPEEHPVLLTEAPMNPKSNREKMTQIMFETFNVPAFYVSIQAVLSLYSSGRTTGIVLDSGDGVTHVVPIYAGFSLPHAILRIDLAGRDLTDYLMKILSERGYSFSTTAEREIVRDIKEKLCYVALDFEQEMQTAAQSSSIEKSYELPDGQVITIGNERFRAPEALFHPSVLGLESAGIDQTTYNSIMKCDVDVRKELYGNIVMSGGTTMFPGIAERMQKEITALAPSSMKVKIIAPPERKYSVWIGGSILASLTTFQQMWISKQEYDESGPSIVHHKCF", + "items": [] + }, + "fungal": { + "url": "https://blast.alliancegenome.org/blast/SGD/fungal", + "nucl": "ATGGTCAAATTAACTTCAATCGCCGCTGGTGTCGCTGCCATCGCTGCTACTGCTTCTGCAACCACCACTCTAGCTCAATCTGACGAAAGAGTCAACTTGGTGGAATTGGGTGTCTACGTC", + "prot": "MDSEVAALVIDNGSGMCKAGFAGDDAPRAVFPSIVGRPRHQGIMVGMGQKDSYVGDEAQSKRGILTLRYPIEHGIVTNWDDMEKIWHHTFYNELRVAPEEHPVLLTEAPMNPKSNREKMTQIMFETFNVPAFYVSIQAVLSLYSSGRTTGIVLDSGDGVTHVVPIYAGFSLPHAILRIDLAGRDLTDYLMKILSERGYSFSTTAEREIVRDIKEKLCYVALDFEQEMQTAAQSSSIEKSYELPDGQVITIGNERFRAPEALFHPSVLGLESAGIDQTTYNSIMKCDVDVRKELYGNIVMSGGTTMFPGIAERMQKEITALAPSSMKVKIIAPPERKYSVWIGGSILASLTTFQQMWISKQEYDESGPSIVHHKCF", + "dbs": ["Fulvia/fulva/F_fulva_Genome_Assembly/fulvia_fulva_genomicdb", + "Fulvia/fulva/F_fulva_Coding_Sequences/fulvia_fulva_cdsdb", + "Naumovozyma/dairenensis/N_dairenensis_Genome_Assembly/naumovozyma_dairenensis_genomicdb", + "Naumovozyma/dairenensis/N_dairenensis_Coding_Sequences/naumovozyma_dairenensis_cdsdb", + "Naumovozyma/castellii/N_castellii_Coding_Sequences/naumovozyma_castellii_cdsdb", + "Naumovozyma/castellii/N_castellii_Genome_Assembly/naumovozyma_castellii_genomicdb", + "Cryptococcus/deuterogattii/C_deuterogattii_Genome_Assembly/cryptococcus_deuterogattii_genomicdb", + "Cryptococcus/deuterogattii/C_deuterogattii_Coding_Sequences/cryptococcus_deuterogattii_cdsdb", + "Cryptococcus/neoformans/C_neoformans_Coding_Sequences/cryptococcus_neoformans_cdsdb", + "Cryptococcus/neoformans/C_neoformans_Genome_Assembly/cryptococcus_neoformans_genomicdb", + "Cryptococcus/gattii/C_gattii_Genome_Assembly/cryptococcus_gattii_genomicdb", + "Cryptococcus/gattii/C_gattii_Coding_Sequences/cryptococcus_gattii_cdsdb", + "Tetrapisispora/blattae/T_blattae_Coding_Sequences/tetrapisispora_blattae_cdsdb", + "Tetrapisispora/blattae/T_blattae_Genome_Assembly/tetrapisispora_blattae_genomicdb", + "Tetrapisispora/phaffii/T_phaffii_Genome_Assembly/tetrapisispora_phaffii_genomicdb", + "Tetrapisispora/phaffii/T_phaffii_Coding_Sequences/tetrapisispora_phaffii_cdsdb", + "Ogataea/parapolymorpha/O_parapolymorpha_Genome_Assembly/ogataea_parapolymorpha_genomicdb", + "Ogataea/parapolymorpha/O_parapolymorpha_Coding_Sequences/ogataea_parapolymorpha_cdsdb", + "Ascochyta/rabiei/A_rabiei_Genome_Assembly/ascochyta_rabiei_genomicdb", + "Ascochyta/rabiei/A_rabiei_Coding_Sequences/ascochyta_rabiei_cdsdb", + "Debaryomyces/hansenii/D_hansenii_Genome_Assembly/debaryomyces_hansenii_genomicdb", + "Debaryomyces/hansenii/D_hansenii_Coding_Sequences/debaryomyces_hansenii_cdsdb", + "Zymoseptoria/tritici/Z_tritici_Coding_Sequences/zymoseptoria_tritici_cdsdb", + "Zymoseptoria/tritici/Z_tritici_Genome_Assembly/zymoseptoria_tritici_genomicdb", + "Purpureocillium/takamizusanense/P_takamizusanense_Genome_Assembly/purpureocillium_takamizusanense_genomicdb", + "Purpureocillium/takamizusanense/P_takamizusanense_Coding_Sequences/purpureocillium_takamizusanense_cdsdb", + "Kazachstania/africana/K_africana_Coding_Sequences/kazachstania_africana_cdsdb", + "Kazachstania/africana/K_africana_Genome_Assembly/kazachstania_africana_genomicdb", + "Kazachstania/naganishii/K_naganishii_Genome_Assembly/kazachstania_naganishii_genomicdb", + "Kazachstania/naganishii/K_naganishii_Coding_Sequences/kazachstania_naganishii_cdsdb", + "Saccharomycodes/ludwigii/S_ludwigii_Genome_Assembly/saccharomycodes_ludwigii_genomicdb", + "Saccharomycodes/ludwigii/S_ludwigii_Coding_Sequences/saccharomycodes_ludwigii_cdsdb", + "Thermothielavioides/terrestris/T_terrestris_Genome_Assembly/thermothielavioides_terrestris_genomicdb", + "Thermothielavioides/terrestris/T_terrestris_Coding_Sequences/thermothielavioides_terrestris_cdsdb", + "Yarrowia/lipolytica/Y_lipolytica_Coding_Sequences/yarrowia_lipolytica_cdsdb", + "Yarrowia/lipolytica/Y_lipolytica_Genome_Assembly/yarrowia_lipolytica_genomicdb", + "Podospora/bellae-mahoneyi/P_bellae_mahoneyi_Coding_Sequences/podospora_bellae-mahoneyi_cdsdb", + "Podospora/bellae-mahoneyi/P_bellae_mahoneyi_Genome_Assembly/podospora_bellae-mahoneyi_genomicdb", + "Podospora/pseudopauciseta/P_pseudopauciseta_Coding_Sequences/podospora_pseudopauciseta_cdsdb", + "Podospora/pseudopauciseta/P_pseudopauciseta_Genome_Assembly/podospora_pseudopauciseta_genomicdb", + "Podospora/pseudocomata/P_pseudocomata_Coding_Sequences/podospora_pseudocomata_cdsdb", + "Podospora/pseudocomata/P_pseudocomata_Genome_Assembly/podospora_pseudocomata_genomicdb", + "Podospora/pseudoanserina/P_pseudoanserina_Coding_Sequences/podospora_pseudoanserina_cdsdb", + "Podospora/pseudoanserina/P_pseudoanserina_Genome_Assembly/podospora_pseudoanserina_genomicdb", + "Botrytis/cinerea/B_cinerea_Coding_Sequences/botrytis_cinerea_cdsdb", + "Botrytis/cinerea/B_cinerea_Genome_Assembly/botrytis_cinerea_genomicdb", + "Akanthomyces/muscarius/A_muscarius_Coding_Sequences/akanthomyces_muscarius_cdsdb", + "Akanthomyces/muscarius/A_muscarius_Genome_Assembly/akanthomyces_muscarius_genomicdb", + "Sporisorium/graminicola/S_graminicola_Coding_Sequences/sporisorium_graminicola_cdsdb", + "Sporisorium/graminicola/S_graminicola_Genome_Assembly/sporisorium_graminicola_genomicdb", + "Rhizoctonia/solani/R_solani_Genome_Assembly/rhizoctonia_solani_genomicdb", + "Rhizoctonia/solani/R_solani_Coding_Sequences/rhizoctonia_solani_cdsdb", + "Kluyveromyces/lactis/K_lactis_Genome_Assembly/kluyveromyces_lactis_genomicdb", + "Kluyveromyces/lactis/K_lactis_Coding_Sequences/kluyveromyces_lactis_cdsdb", + "Kluyveromyces/marxianus/K_marxianus_Coding_Sequences/kluyveromyces_marxianus_cdsdb", + "Kluyveromyces/marxianus/K_marxianus_Genome_Assembly/kluyveromyces_marxianus_genomicdb", + "Encephalitozoon/cuniculi/E_cuniculi_Genome_Assembly/encephalitozoon_cuniculi_genomicdb", + "Encephalitozoon/cuniculi/E_cuniculi_Coding_Sequences/encephalitozoon_cuniculi_cdsdb", + "Encephalitozoon/hellem/E_hellem_Genome_Assembly/encephalitozoon_hellem_genomicdb", + "Encephalitozoon/hellem/E_hellem_Coding_Sequences/encephalitozoon_hellem_cdsdb", + "Encephalitozoon/intestinalis/E_intestinalis_Genome_Assembly/encephalitozoon_intestinalis_genomicdb", + "Encephalitozoon/intestinalis/E_intestinalis_Coding_Sequences/encephalitozoon_intestinalis_cdsdb", + "Encephalitozoon/romaleae/E_romaleae_Genome_Assembly/encephalitozoon_romaleae_genomicdb", + "Encephalitozoon/romaleae/E_romaleae_Coding_Sequences/encephalitozoon_romaleae_cdsdb", + "Fusarium/fujikuroi/F_fujikuroi_Coding_Sequences/fusarium_fujikuroi_cdsdb", + "Fusarium/fujikuroi/F_fujikuroi_Genome_Assembly/fusarium_fujikuroi_genomicdb", + "Fusarium/falciforme/F_falciforme_Coding_Sequences/fusarium_falciforme_cdsdb", + "Fusarium/falciforme/F_falciforme_Genome_Assembly/fusarium_falciforme_genomicdb", + "Fusarium/verticillioides/F_verticillioides_Genome_Assembly/fusarium_verticillioides_genomicdb", + "Fusarium/verticillioides/F_verticillioides_Coding_Sequences/fusarium_verticillioides_cdsdb", + "Fusarium/pseudograminearum/F_pseudograminearum_Coding_Sequences/fusarium_pseudograminearum_cdsdb", + "Fusarium/pseudograminearum/F_pseudograminearum_Genome_Assembly/fusarium_pseudograminearum_genomicdb", + "Fusarium/graminearum/F_graminearum_Genome_Assembly/fusarium_graminearum_genomicdb", + "Fusarium/graminearum/F_graminearum_Coding_Sequences/fusarium_graminearum_cdsdb", + "Fusarium/poae/F_poae_Coding_Sequences/fusarium_poae_cdsdb", + "Fusarium/poae/F_poae_Genome_Assembly/fusarium_poae_genomicdb", + "Fusarium/venenatum/F_venenatum_Coding_Sequences/fusarium_venenatum_cdsdb", + "Fusarium/venenatum/F_venenatum_Genome_Assembly/fusarium_venenatum_genomicdb", + "Fusarium/keratoplasticum/F_keratoplasticum_Genome_Assembly/fusarium_keratoplasticum_genomicdb", + "Fusarium/keratoplasticum/F_keratoplasticum_Coding_Sequences/fusarium_keratoplasticum_cdsdb", + "Fusarium/oxysporum/F_oxysporum_Coding_Sequences/fusarium_oxysporum_cdsdb", + "Fusarium/oxysporum/F_oxysporum_Genome_Assembly/fusarium_oxysporum_genomicdb", + "Fusarium/musae/F_musae_Coding_Sequences/fusarium_musae_cdsdb", + "Fusarium/musae/F_musae_Genome_Assembly/fusarium_musae_genomicdb", + "Vanrija/pseudolonga/V_pseudolonga_Coding_Sequences/vanrija_pseudolonga_cdsdb", + "Vanrija/pseudolonga/V_pseudolonga_Genome_Assembly/vanrija_pseudolonga_genomicdb", + "Trichoderma/breve/T_breve_Genome_Assembly/trichoderma_breve_genomicdb", + "Trichoderma/breve/T_breve_Coding_Sequences/trichoderma_breve_cdsdb", + "Scheffersomyces/stipitis/S_stipitis_Genome_Assembly/scheffersomyces_stipitis_genomicdb", + "Scheffersomyces/stipitis/S_stipitis_Coding_Sequences/scheffersomyces_stipitis_cdsdb", + "Brettanomyces/bruxellensis/B_bruxellensis_Coding_Sequences/brettanomyces_bruxellensis_cdsdb", + "Brettanomyces/bruxellensis/B_bruxellensis_Genome_Assembly/brettanomyces_bruxellensis_genomicdb", + "Brettanomyces/nanus/B_nanus_Coding_Sequences/brettanomyces_nanus_cdsdb", + "Brettanomyces/nanus/B_nanus_Genome_Assembly/brettanomyces_nanus_genomicdb", + "Drechmeria/coniospora/D_coniospora_Genome_Assembly/drechmeria_coniospora_genomicdb", + "Drechmeria/coniospora/D_coniospora_Coding_Sequences/drechmeria_coniospora_cdsdb", + "Puccinia/triticina/P_triticina_Genome_Assembly/puccinia_triticina_genomicdb", + "Puccinia/triticina/P_triticina_Coding_Sequences/puccinia_triticina_cdsdb", + "Puccinia/striiformis/P_striiformis_Genome_Assembly/puccinia_striiformis_genomicdb", + "Puccinia/striiformis/P_striiformis_Coding_Sequences/puccinia_striiformis_cdsdb", + "Neurospora/crassa/N_crassa_Coding_Sequences/neurospora_crassa_cdsdb", + "Neurospora/crassa/N_crassa_Genome_Assembly/neurospora_crassa_genomicdb", + "Nakaseomyces/glabratus/N_glabratus_Coding_Sequences/nakaseomyces_glabratus_cdsdb", + "Nakaseomyces/glabratus/N_glabratus_Genome_Assembly/nakaseomyces_glabratus_genomicdb", + "Lachancea/thermotolerans/L_thermotolerans_Genome_Assembly/lachancea_thermotolerans_genomicdb", + "Lachancea/thermotolerans/L_thermotolerans_Coding_Sequences/lachancea_thermotolerans_cdsdb", + "Saccharomyces/cerevisiae/S_cerevisiae_Genome_Assembly/saccharomyces_cerevisiae_genomicdb", + "Saccharomyces/cerevisiae/S_cerevisiae_Coding_Sequences/saccharomyces_cerevisiae_cdsdb", + "Saccharomyces/mikatae/S_mikatae_Coding_Sequences/saccharomyces_mikatae_cdsdb", + "Saccharomyces/mikatae/S_mikatae_Genome_Assembly/saccharomyces_mikatae_genomicdb", + "Saccharomyces/kudriavzevii/S_kudriavzevii_Genome_Assembly/saccharomyces_kudriavzevii_genomicdb", + "Saccharomyces/kudriavzevii/S_kudriavzevii_Coding_Sequences/saccharomyces_kudriavzevii_cdsdb", + "Saccharomyces/eubayanus/S_eubayanus_Coding_Sequences/saccharomyces_eubayanus_cdsdb", + "Saccharomyces/eubayanus/S_eubayanus_Genome_Assembly/saccharomyces_eubayanus_genomicdb", + "Saccharomyces/paradoxus/S_paradoxus_Coding_Sequences/saccharomyces_paradoxus_cdsdb", + "Saccharomyces/paradoxus/S_paradoxus_Genome_Assembly/saccharomyces_paradoxus_genomicdb", + "Candida/orthopsilosis/C_orthopsilosis_Genome_Assembly/candida_orthopsilosis_genomicdb", + "Candida/orthopsilosis/C_orthopsilosis_Coding_Sequences/candida_orthopsilosis_cdsdb", + "Candida/saopauloensis/C_saopauloensis_Genome_Assembly/candida_saopauloensis_genomicdb", + "Candida/saopauloensis/C_saopauloensis_Coding_Sequences/candida_saopauloensis_cdsdb", + "Candida/albicans/C_albicans_Coding_Sequences/candida_albicans_cdsdb", + "Candida/albicans/C_albicans_Genome_Assembly/candida_albicans_genomicdb", + "Candida/dubliniensis/C_dubliniensis_Genome_Assembly/candida_dubliniensis_genomicdb", + "Candida/dubliniensis/C_dubliniensis_Coding_Sequences/candida_dubliniensis_cdsdb", + "Candida/auris/C_auris_Coding_Sequences/candida_auris_cdsdb", + "Candida/auris/C_auris_Genome_Assembly/candida_auris_genomicdb", + "Torulaspora/globosa/T_globosa_Coding_Sequences/torulaspora_globosa_cdsdb", + "Torulaspora/globosa/T_globosa_Genome_Assembly/torulaspora_globosa_genomicdb", + "Torulaspora/delbrueckii/T_delbrueckii_Coding_Sequences/torulaspora_delbrueckii_cdsdb", + "Torulaspora/delbrueckii/T_delbrueckii_Genome_Assembly/torulaspora_delbrueckii_genomicdb", + "Psilocybe/cubensis/P_cubensis_Genome_Assembly/psilocybe_cubensis_genomicdb", + "Psilocybe/cubensis/P_cubensis_Coding_Sequences/psilocybe_cubensis_cdsdb", + "Thermothelomyces/thermophilus/T_thermophilus_Genome_Assembly/thermothelomyces_thermophilus_genomicdb", + "Thermothelomyces/thermophilus/T_thermophilus_Coding_Sequences/thermothelomyces_thermophilus_cdsdb", + "Lodderomyces/elongisporus/L_elongisporus_Coding_Sequences/lodderomyces_elongisporus_cdsdb", + "Lodderomyces/elongisporus/L_elongisporus_Genome_Assembly/lodderomyces_elongisporus_genomicdb", + "Aspergillus/puulaauensis/A_puulaauensis_Coding_Sequences/aspergillus_puulaauensis_cdsdb", + "Aspergillus/puulaauensis/A_puulaauensis_Genome_Assembly/aspergillus_puulaauensis_genomicdb", + "Aspergillus/flavus/A_flavus_Genome_Assembly/aspergillus_flavus_genomicdb", + "Aspergillus/flavus/A_flavus_Coding_Sequences/aspergillus_flavus_cdsdb", + "Aspergillus/nidulans/A_nidulans_Coding_Sequences/aspergillus_nidulans_cdsdb", + "Aspergillus/nidulans/A_nidulans_Genome_Assembly/aspergillus_nidulans_genomicdb", + "Aspergillus/chevalieri/A_chevalieri_Coding_Sequences/aspergillus_chevalieri_cdsdb", + "Aspergillus/chevalieri/A_chevalieri_Genome_Assembly/aspergillus_chevalieri_genomicdb", + "Aspergillus/fumigatus/A_fumigatus_Coding_Sequences/aspergillus_fumigatus_cdsdb", + "Aspergillus/fumigatus/A_fumigatus_Genome_Assembly/aspergillus_fumigatus_genomicdb", + "Aspergillus/luchuensis/A_luchuensis_Genome_Assembly/aspergillus_luchuensis_genomicdb", + "Aspergillus/luchuensis/A_luchuensis_Coding_Sequences/aspergillus_luchuensis_cdsdb", + "Aspergillus/oryzae/A_oryzae_Genome_Assembly/aspergillus_oryzae_genomicdb", + "Aspergillus/oryzae/A_oryzae_Coding_Sequences/aspergillus_oryzae_cdsdb", + "Zygotorulaspora/mrakii/Z_mrakii_Genome_Assembly/zygotorulaspora_mrakii_genomicdb", + "Zygotorulaspora/mrakii/Z_mrakii_Coding_Sequences/zygotorulaspora_mrakii_cdsdb", + "Pyricularia/grisea/P_grisea_Coding_Sequences/pyricularia_grisea_cdsdb", + "Pyricularia/grisea/P_grisea_Genome_Assembly/pyricularia_grisea_genomicdb", + "Pyricularia/oryzae/P_oryzae_Genome_Assembly/pyricularia_oryzae_genomicdb", + "Pyricularia/oryzae/P_oryzae_Coding_Sequences/pyricularia_oryzae_cdsdb", + "Pyricularia/pennisetigena/P_pennisetigena_Genome_Assembly/pyricularia_pennisetigena_genomicdb", + "Pyricularia/pennisetigena/P_pennisetigena_Coding_Sequences/pyricularia_pennisetigena_cdsdb", + "Pochonia/chlamydosporia/P_chlamydosporia_Genome_Assembly/pochonia_chlamydosporia_genomicdb", + "Pochonia/chlamydosporia/P_chlamydosporia_Coding_Sequences/pochonia_chlamydosporia_cdsdb", + "Ustilago/maydis/U_maydis_Genome_Assembly/ustilago_maydis_genomicdb", + "Ustilago/maydis/U_maydis_Coding_Sequences/ustilago_maydis_cdsdb", + "Kwoniella/shivajii/K_shivajii_Coding_Sequences/kwoniella_shivajii_cdsdb", + "Kwoniella/shivajii/K_shivajii_Genome_Assembly/kwoniella_shivajii_genomicdb", + "Ustilaginoidea/virens/U_virens_Coding_Sequences/ustilaginoidea_virens_cdsdb", + "Ustilaginoidea/virens/U_virens_Genome_Assembly/ustilaginoidea_virens_genomicdb", + "Sugiyamaella/lignohabitans/S_lignohabitans_Genome_Assembly/sugiyamaella_lignohabitans_genomicdb", + "Sugiyamaella/lignohabitans/S_lignohabitans_Coding_Sequences/sugiyamaella_lignohabitans_cdsdb", + "Colletotrichum/lupini/C_lupini_Genome_Assembly/colletotrichum_lupini_genomicdb", + "Colletotrichum/lupini/C_lupini_Coding_Sequences/colletotrichum_lupini_cdsdb", + "Colletotrichum/higginsianum/C_higginsianum_Coding_Sequences/colletotrichum_higginsianum_cdsdb", + "Colletotrichum/higginsianum/C_higginsianum_Genome_Assembly/colletotrichum_higginsianum_genomicdb", + "Colletotrichum/destructivum/C_destructivum_Genome_Assembly/colletotrichum_destructivum_genomicdb", + "Colletotrichum/destructivum/C_destructivum_Coding_Sequences/colletotrichum_destructivum_cdsdb", + "Komagataella/phaffii/K_phaffii_Genome_Assembly/komagataella_phaffii_genomicdb", + "Komagataella/phaffii/K_phaffii_Coding_Sequences/komagataella_phaffii_cdsdb", + "Eremothecium/sinecaudum/E_sinecaudum_Coding_Sequences/eremothecium_sinecaudum_cdsdb", + "Eremothecium/sinecaudum/E_sinecaudum_Genome_Assembly/eremothecium_sinecaudum_genomicdb", + "Eremothecium/gossypii/E_gossypii_Coding_Sequences/eremothecium_gossypii_cdsdb", + "Eremothecium/gossypii/E_gossypii_Genome_Assembly/eremothecium_gossypii_genomicdb", + "Eremothecium/cymbalariae/E_cymbalariae_Genome_Assembly/eremothecium_cymbalariae_genomicdb", + "Eremothecium/cymbalariae/E_cymbalariae_Coding_Sequences/eremothecium_cymbalariae_cdsdb", + "Schizosaccharomyces/osmophilus/S_osmophilus_Coding_Sequences/schizosaccharomyces_osmophilus_cdsdb", + "Schizosaccharomyces/osmophilus/S_osmophilus_Genome_Assembly/schizosaccharomyces_osmophilus_genomicdb", + "Schizosaccharomyces/pombe/S_pombe_Coding_Sequences/schizosaccharomyces_pombe_cdsdb", + "Schizosaccharomyces/pombe/S_pombe_Genome_Assembly/schizosaccharomyces_pombe_genomicdb", + "Malassezia/japonica/M_japonica_Genome_Assembly/malassezia_japonica_genomicdb", + "Malassezia/japonica/M_japonica_Coding_Sequences/malassezia_japonica_cdsdb", + "Malassezia/vespertilionis/M_vespertilionis_Genome_Assembly/malassezia_vespertilionis_genomicdb", + "Malassezia/vespertilionis/M_vespertilionis_Coding_Sequences/malassezia_vespertilionis_cdsdb", + "Malassezia/restricta/M_restricta_Genome_Assembly/malassezia_restricta_genomicdb", + "Malassezia/restricta/M_restricta_Coding_Sequences/malassezia_restricta_cdsdb", + "Cutaneotrichosporon/cavernicola/C_cavernicola_Genome_Assembly/cutaneotrichosporon_cavernicola_genomicdb", + "Cutaneotrichosporon/cavernicola/C_cavernicola_Coding_Sequences/cutaneotrichosporon_cavernicola_cdsdb", + "Cercospora/beticola/C_beticola_Coding_Sequences/cercospora_beticola_cdsdb", + "Cercospora/beticola/C_beticola_Genome_Assembly/cercospora_beticola_genomicdb", + "Talaromyces/marneffei/T_marneffei_Coding_Sequences/talaromyces_marneffei_cdsdb", + "Talaromyces/marneffei/T_marneffei_Genome_Assembly/talaromyces_marneffei_genomicdb", + "Talaromyces/rugulosus/T_rugulosus_Genome_Assembly/talaromyces_rugulosus_genomicdb", + "Talaromyces/rugulosus/T_rugulosus_Coding_Sequences/talaromyces_rugulosus_cdsdb", + "Marasmius/oreades/M_oreades_Coding_Sequences/marasmius_oreades_cdsdb", + "Marasmius/oreades/M_oreades_Genome_Assembly/marasmius_oreades_genomicdb", + "Pichia/kudriavzevii/P_kudriavzevii_Genome_Assembly/pichia_kudriavzevii_genomicdb", + "Pichia/kudriavzevii/P_kudriavzevii_Coding_Sequences/pichia_kudriavzevii_cdsdb", + "Zygosaccharomyces/rouxii/Z_rouxii_Coding_Sequences/zygosaccharomyces_rouxii_cdsdb", + "Zygosaccharomyces/rouxii/Z_rouxii_Genome_Assembly/zygosaccharomyces_rouxii_genomicdb", + "Penicillium/oxalicum/P_oxalicum_Genome_Assembly/penicillium_oxalicum_genomicdb", + "Penicillium/oxalicum/P_oxalicum_Coding_Sequences/penicillium_oxalicum_cdsdb" + ] + } + }, + "WB": { + }, + "RGD": { + }, + "ZFIN": { + }, + "MGI": { + }, + "FB": { + } +} + + diff --git a/tests/CLI/test_cli.py b/tests/CLI/test_cli.py new file mode 100644 index 0000000..d119920 --- /dev/null +++ b/tests/CLI/test_cli.py @@ -0,0 +1,42 @@ +# blastn -db +# /Users/nuin/Projects/wormbase/blast/agr_blastdb_manager/data/blast/SGD/fungal/databases/Zygosaccharomyces/rouxii/Z_rouxii_Genome_Assembly/zygosaccharomyces_rouxii_genomicdb +# -query input_files/SGD.fasta │ + + +import pathlib +from pathlib import Path +import click +import json +from subprocess import Popen, PIPE + + +def run_blast(db, fasta, mod, environment): + print(db) + temp = open("temp.fasta", "w") + temp.write(fasta) + temp.close() + + blast_command = f"blastn -db {db} -query temp.fasta -out output/{mod}/{environment}/{Path(db).name}.txt -num_threads 4 -evalue 1 -outfmt 6" + + print(blast_command) + p = Popen(blast_command, shell=True, stdout=PIPE, stderr=PIPE) + + +@click.command() +@click.option("-d", "--datadir", help="The path to the data directory", required=True) +@click.option("-M", "--mod", help="The MOD to test", required=True) +@click.option("-e", "--environment", help="The environment to test", required=True) +def setup_blast(datadir, mod, environment): + data = json.loads(open("config.json").read()) + + p = pathlib.Path(f"{datadir}/{mod}/{environment}/databases/") + dbs = data[mod][environment]["dbs"] + fasta = f">test\n{data[mod][environment]["nucl"]}" + + for db in dbs: + full_dir = p / db + run_blast(full_dir, fasta, mod, environment) + + +if __name__ == "__main__": + setup_blast() diff --git a/tests/UI/README_locust.md b/tests/UI/README_locust.md new file mode 100644 index 0000000..7b39201 --- /dev/null +++ b/tests/UI/README_locust.md @@ -0,0 +1,242 @@ +# BLAST Web Interface Load Testing + +This document provides comprehensive instructions for running load tests against the BLAST web interface using Locust. + +## Table of Contents +- [Prerequisites](#prerequisites) +- [Installation](#installation) +- [Configuration](#configuration) +- [Running Tests](#running-tests) +- [Test Scenarios](#test-scenarios) +- [Monitoring and Analysis](#monitoring-and-analysis) +- [Troubleshooting](#troubleshooting) + +## Prerequisites + +- Python 3.8 or higher +- pip (Python package installer) +- Access to the BLAST web interface +- Basic understanding of BLAST searches and MOD databases + +## Installation + +1. Ensure Poetry is installed on your system. If not, install it following the [official instructions](https://python-poetry.org/docs/#installation). + +2. Clone this repository and navigate to the project directory: +```bash +git clone +cd +``` + +3. Install dependencies using Poetry: +```bash +poetry install +``` + +4. Add Locust dependencies to the project: +```bash +poetry add locust rich +``` + +Your `pyproject.toml` should include these dependencies: +```toml +[tool.poetry.dependencies] +python = "^3.8" +locust = "^2.15.1" +rich = "^13.3.5" +``` + +5. Activate the Poetry shell: +```bash +poetry shell +``` + +## Configuration + +### Environment Variables + +The following environment variables can be set: + +- `BLAST_CONFIG`: Path to the configuration file (default: config.json) +- `LOCUST_MOD`: Model organism database to test +- `LOCUST_ENV`: Target environment (prod, dev, stage) + +### Configuration File (config.json) + +The configuration file should follow this structure: + +```json +{ + "SGD": { + "fungal": { + "items": ["database1", "database2"], + "nucl": "ATGC...", + "prot": "MKLT..." + } + }, + "WB": { + "nematode": { + "items": ["database3", "database4"], + "nucl": "ATGC...", + "prot": "MKLT..." + } + } +} +``` + +## Running Tests + +### Basic Usage + +With Poetry: +```bash +poetry run locust -f locustfile.py --host=https://blast.alliancegenome.org --mod=SGD --env=prod +``` + +Or from within Poetry shell: +```bash +locust -f locustfile.py --host=https://blast.alliancegenome.org --mod=SGD --env=prod +``` + +### Common Options + +- `-t RUNTIME`: Test duration (e.g., 1h, 30m) +- `-u NUM_USERS`: Number of concurrent users +- `-r SPAWN_RATE`: User spawn rate per second +- `--headless`: Run without web interface +- `--mod MOD`: Model organism database to test +- `--env ENV`: Target environment + +### Example Commands + +1. Run a 1-hour test with 10 users: +```bash +# Using Poetry run +poetry run locust -f locustfile.py --host=https://blast.alliancegenome.org -t 1h -u 10 -r 1 --mod=SGD --env=prod --headless + +# Or from within Poetry shell +locust -f locustfile.py --host=https://blast.alliancegenome.org -t 1h -u 10 -r 1 --mod=SGD --env=prod --headless +``` + +2. Run with web interface for manual control: +```bash +locust -f locustfile.py --host=https://blast.alliancegenome.org --mod=SGD --env=prod +``` + +3. Distributed load testing (multiple workers): +```bash +# Master +locust -f locustfile.py --master --expect-workers=2 + +# Workers +locust -f locustfile.py --worker --master-host=localhost +``` + +## Test Scenarios + +The load test implements two main scenarios: + +1. Nucleotide BLAST Search (`@task(1)`) + - Randomly selects a database type + - Uses nucleotide sequences from config + - Simulates form submission + +2. Protein BLAST Search (`@task(1)`) + - Randomly selects a database type + - Uses protein sequences from config + - Simulates form submission + +Each test: +- Waits 1-5 seconds between requests +- Randomly selects databases +- Validates responses +- Reports errors and successes + +## Monitoring and Analysis + +### Web Interface + +Access the web interface at http://localhost:8089 when running without --headless: + +- Real-time statistics +- RPS (Requests Per Second) +- Response time distribution +- Error rates + +### Console Output + +The script provides rich console output: + +- Test start/stop events +- Configuration details +- Error reporting +- Progress updates + +### Generating Reports + +Generate HTML reports after test completion: + +```bash +locust -f locustfile.py --host=https://blast.alliancegenome.org --mod=SGD --env=prod --headless --html=report.html +``` + +## Troubleshooting + +### Common Issues + +1. Configuration Not Found +``` +Error: No module named 'config.json' +Solution: Ensure config.json is in the same directory as locustfile.py +``` + +2. MOD Not Specified +``` +Error: MOD must be specified via --mod or LOCUST_MOD +Solution: Add --mod parameter or set LOCUST_MOD environment variable +``` + +3. Connection Errors +``` +Error: Connection refused +Solution: Verify host URL and network connectivity +``` + +### Debug Mode + +Enable debug logging: + +```bash +# Using Poetry run +poetry run locust -f locustfile.py --host=https://blast.alliancegenome.org --mod=SGD --env=prod --loglevel=DEBUG + +# Or from within Poetry shell +locust -f locustfile.py --host=https://blast.alliancegenome.org --mod=SGD --env=prod --loglevel=DEBUG +``` + +You can also set Poetry-specific environment variables in the `pyproject.toml`: + +```toml +[tool.poetry.env] +BLAST_CONFIG = "config.json" +LOCUST_MOD = "SGD" +LOCUST_ENV = "prod" +``` + +### Support + +For issues or questions: +1. Check the error message in the console output +2. Verify configuration file format +3. Ensure all prerequisites are installed +4. Check network connectivity to the target host + +## Contributing + +To contribute: +1. Fork the repository +2. Create a feature branch +3. Add or modify tests +4. Submit a pull request + +Please ensure all new code includes appropriate tests and documentation. \ No newline at end of file diff --git a/tests/UI/Readme_ui.md b/tests/UI/Readme_ui.md new file mode 100644 index 0000000..2683445 --- /dev/null +++ b/tests/UI/Readme_ui.md @@ -0,0 +1,251 @@ +# BLAST Web Interface UI Testing + +This tool provides automated UI testing capabilities for the BLAST web interface using Selenium WebDriver. It allows testing of different Model Organism Databases (MODs) and their various BLAST configurations. + +## Table of Contents +- [Prerequisites](#prerequisites) +- [Installation](#installation) +- [Configuration](#configuration) +- [Usage](#usage) +- [Test Output](#test-output) +- [Troubleshooting](#troubleshooting) +- [Development](#development) + +## Prerequisites + +- Python 3.8 or higher +- Poetry (dependency management) +- Chrome or Chromium browser +- ChromeDriver matching your Chrome version + +## Installation + +1. Ensure Poetry is installed on your system. If not, install it following the [official instructions](https://python-poetry.org/docs/#installation). + +2. Clone this repository and navigate to the project directory: +```bash +git clone +cd +``` + +3. Install dependencies using Poetry: +```bash +poetry install +``` + +4. Add the required dependencies to your project: +```bash +poetry add selenium rich click +``` + +Your `pyproject.toml` should include these dependencies: +```toml +[tool.poetry.dependencies] +python = "^3.8" +selenium = "^4.9.0" +rich = "^13.3.5" +click = "^8.1.3" + +[tool.poetry.dev-dependencies] +# Add any development dependencies here +``` + +## Configuration + +### ChromeDriver Setup + +1. Download ChromeDriver that matches your Chrome version from [ChromeDriver Downloads](https://sites.google.com/chromium.org/driver/) +2. Add ChromeDriver to your system PATH + +### Configuration File (config.json) + +Create a `config.json` file with your test configurations: + +```json +{ + "SGD": { + "fungal": { + "items": [ + "database1_id", + "database2_id" + ], + "nucl": "ATGCATGC...", + "prot": "MKLTMKLT..." + } + }, + "WB": { + "nematode": { + "items": [ + "database3_id", + "database4_id" + ], + "nucl": "ATGCATGC...", + "prot": "MKLTMKLT..." + } + } +} +``` + +## Usage + +### Basic Command Structure + +```bash +poetry run python test_ui.py [OPTIONS] +``` + +### Required Options + +- `-m, --mod`: Model organism database to test (e.g., SGD, WB) +- `-t, --type`: Database type (e.g., fungal, nematode) + +### Optional Parameters + +- `-s, --single_item`: Number of items to test (default: 1) +- `-M, --molecule`: Molecule type to test ('nucl' or 'prot', default: 'nucl') +- `-n, --number_of_items`: Number of random items to test +- `-c, --config`: Path to configuration file (default: config.json) +- `-o, --output`: Output directory for screenshots (default: output) + +### Example Commands + +1. Test a single database: +```bash +poetry run python test_ui.py --mod SGD --type fungal +``` + +2. Test multiple databases with protein sequences: +```bash +poetry run python test_ui.py --mod SGD --type fungal --molecule prot --number_of_items 3 +``` + +3. Test with custom configuration: +```bash +poetry run python test_ui.py --mod WB --type nematode --config custom_config.json +``` + +### Poetry Scripts + +Add these convenient scripts to your `pyproject.toml`: + +```toml +[tool.poetry.scripts] +test-ui = "test_ui:run_blast_tests" +``` + +Then run tests using: +```bash +poetry run test-ui --mod SGD --type fungal +``` + +## Test Output + +### Screenshots + +Screenshots are saved in the output directory with the following structure: +``` +output/ +└── / + ├── database1_id.png + ├── database2_id.png + └── ... +``` + +### Console Output + +The tool provides rich console output including: +- Progress indicators +- Success/failure messages +- Error details +- Screenshot locations + +## Troubleshooting + +### Common Issues + +1. ChromeDriver Version Mismatch +``` +Error: SessionNotCreatedException +Solution: Update ChromeDriver to match your Chrome version +``` + +2. Configuration Not Found +``` +Error: Invalid JSON configuration file +Solution: Ensure config.json exists and is properly formatted +``` + +3. Browser Launch Failed +``` +Error: WebDriverException +Solution: Check Chrome installation and ChromeDriver path +``` + +### Debug Tips + +1. Disable Headless Mode: + - Edit `setup_browser()` in the code + - Remove the `--headless` option to see browser automation in action + +2. Increase Wait Times: + - Adjust the `WebDriverWait` timeout values for slower connections + - Default wait is 10 seconds for elements, 600 seconds for results + +3. Check Screenshots: + - Screenshots are saved even if tests fail + - Compare failed test screenshots with successful ones + +## Development + +### Adding New Features + +1. Clone the repository +2. Create a new branch +3. Install development dependencies: +```bash +poetry install --with dev +``` + +### Code Style + +Follow these guidelines: +- Use type hints +- Add docstrings for new functions +- Follow PEP 8 conventions +- Add appropriate error handling + +### Running Tests + +If you add tests for the testing script itself: +```bash +poetry run pytest tests/ +``` + +### Contributing + +1. Fork the repository +2. Create a feature branch +3. Add or modify tests +4. Submit a pull request + +### Project Structure + +``` +. +├── test_ui.py +├── config.json +├── pyproject.toml +├── poetry.lock +├── README.md +└── output/ + └── / + └── screenshots/ +``` + +## License + +[Add your license information here] + +## Authors + +[Add author information here] \ No newline at end of file diff --git a/tests/UI/locustfile.py b/tests/UI/locustfile.py new file mode 100644 index 0000000..e9eb057 --- /dev/null +++ b/tests/UI/locustfile.py @@ -0,0 +1,186 @@ +""" +locustfile.py + +This module implements load testing for the BLAST web interface using Locust. +It supports testing different MODs and environments, using sequences from a +configuration file. + +Usage: + locust -f locustfile.py --host=https://blast.alliancegenome.org -t 1h -u 10 -r 1 + --mod=SGD --env=prod --headless + +Environment variables: + BLAST_CONFIG: Path to the configuration file (default: config.json) +""" + +import json +import os +import random +from pathlib import Path +from typing import Dict, List, Optional + +from locust import HttpUser, between, events, task +from rich.console import Console + +console = Console() + + +class BlastLoadTest: + """ + Handles configuration and data management for BLAST load testing. + """ + + def __init__(self, mod: str, environment: str = "prod"): + self.mod = mod + self.environment = environment + self.config = self._load_config() + self.sequences = self._prepare_sequences() + self.database_items = self._prepare_database_items() + + def _load_config(self) -> Dict: + """Load and validate the configuration file.""" + config_path = os.getenv("BLAST_CONFIG", "config.json") + try: + with open(config_path) as f: + config = json.load(f) + + if self.mod not in config: + raise ValueError(f"MOD '{self.mod}' not found in configuration") + + return config[self.mod] + except Exception as e: + console.log(f"[red]Error loading configuration: {str(e)}[/red]") + raise + + def _prepare_sequences(self) -> Dict[str, str]: + """Prepare test sequences for each database type.""" + sequences = {} + for db_type, data in self.config.items(): + if isinstance(data, dict): + sequences[db_type] = { + 'nucl': data.get('nucl', ''), + 'prot': data.get('prot', '') + } + return sequences + + def _prepare_database_items(self) -> Dict[str, List[str]]: + """Prepare database items for each type.""" + items = {} + for db_type, data in self.config.items(): + if isinstance(data, dict) and 'items' in data: + items[db_type] = data['items'] + return items + + def get_random_sequence(self, db_type: str, molecule_type: str = 'nucl') -> str: + """Get a random sequence for the specified database type.""" + if db_type in self.sequences: + return self.sequences[db_type].get(molecule_type, '') + return '' + + def get_random_database(self, db_type: str) -> Optional[str]: + """Get a random database item for the specified type.""" + if db_type in self.database_items and self.database_items[db_type]: + return random.choice(self.database_items[db_type]) + return None + + +class BlastUser(HttpUser): + """ + Simulates user behavior for load testing the BLAST web interface. + """ + + wait_time = between(1, 5) # Wait 1-5 seconds between tasks + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.mod = self.host.split('/')[-1] if self.host.endswith('/') else '' + self.blast_test = None + + def on_start(self): + """Initialize the test configuration when user starts.""" + try: + # Get MOD from command line or environment + self.mod = os.getenv("LOCUST_MOD", self.mod) + if not self.mod: + raise ValueError("MOD must be specified via --mod or LOCUST_MOD") + + self.environment = os.getenv("LOCUST_ENV", "prod") + self.blast_test = BlastLoadTest(self.mod, self.environment) + + except Exception as e: + console.log(f"[red]Error initializing test user: {str(e)}[/red]") + raise + + @task(1) + def nucleotide_blast(self): + """Simulate nucleotide BLAST search.""" + if not self.blast_test: + return + + db_type = random.choice(list(self.blast_test.database_items.keys())) + database = self.blast_test.get_random_database(db_type) + sequence = self.blast_test.get_random_sequence(db_type, 'nucl') + + if database and sequence: + self._perform_blast(db_type, database, sequence) + + @task(1) + def protein_blast(self): + """Simulate protein BLAST search.""" + if not self.blast_test: + return + + db_type = random.choice(list(self.blast_test.database_items.keys())) + database = self.blast_test.get_random_database(db_type) + sequence = self.blast_test.get_random_sequence(db_type, 'prot') + + if database and sequence: + self._perform_blast(db_type, database, sequence) + + def _perform_blast(self, db_type: str, database: str, sequence: str): + """ + Perform a BLAST search request. + + Args: + db_type: Type of database to search + database: Specific database identifier + sequence: Query sequence + """ + try: + # Submit BLAST search + with self.client.post( + f"/blast/{self.mod}/{db_type}", + data={ + "database": database, + "sequence": sequence, + "submit": "BLAST" + }, + catch_response=True + ) as response: + if response.status_code == 200: + response.success() + else: + response.failure(f"BLAST search failed: {response.status_code}") + + except Exception as e: + console.log(f"[red]Error performing BLAST search: {str(e)}[/red]") + events.request_failure.fire( + request_type="POST", + name="blast_search", + response_time=0, + exception=e + ) + + +@events.test_start.add_listener +def on_test_start(environment, **kwargs): + """Log test configuration at start.""" + console.log("[green]Starting BLAST load test[/green]") + console.log(f"MOD: {os.getenv('LOCUST_MOD', 'Not specified')}") + console.log(f"Environment: {os.getenv('LOCUST_ENV', 'prod')}") + + +@events.test_stop.add_listener +def on_test_stop(environment, **kwargs): + """Log test completion.""" + console.log("[green]BLAST load test completed[/green]") \ No newline at end of file diff --git a/tests/UI/test_ui.py b/tests/UI/test_ui.py index 9c342b1..051142b 100644 --- a/tests/UI/test_ui.py +++ b/tests/UI/test_ui.py @@ -1,81 +1,169 @@ +# test_ui.py +""" +test_ui.py + +This module provides automated UI testing functionality for the BLAST web interface. +It uses Selenium WebDriver to automate browser interactions and test various BLAST +database configurations. + +Features: +- Configurable test parameters for different MODs and sequence types +- Screenshot capture of test results +- Progress tracking with rich console output +- Flexible test configuration via JSON +""" + import json import time +from pathlib import Path +from typing import List, Optional import click from rich.console import Console +from rich.progress import Progress, SpinnerColumn, TextColumn from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait -from tqdm import tqdm +from selenium.common.exceptions import TimeoutException, WebDriverException console = Console() -def run_test(mod, items, type, sequence): - - # Locate and click the checkbox - # Locate and click the checkbox - for item in items: - # Set up the browser (replace "chrome" with "firefox" for Firefox) - browser = webdriver.Chrome() - - # Navigate to your webpage - browser.get(f"https://blast.alliancegenome.org/blast/{mod}/{type}") - console.log(f"Testing {item}") - checkbox = WebDriverWait(browser, 10).until( - EC.element_to_be_clickable((By.ID, item)) - ) - checkbox.click() - console.log(f"Clicked {item}") - - # Locate and fill out the input box - input_box = WebDriverWait(browser, 10).until( - EC.element_to_be_clickable((By.NAME, "sequence")) - ) - input_box.send_keys(sequence) - console.log(f"Sent sequence") - - # Locate the element right before interacting with it - element = WebDriverWait(browser, 10).until( - EC.element_to_be_clickable((By.ID, "method")) - ) - element.click() - console.log("Clicked button") - - for _ in tqdm(range(5)): # Pauses the script for 10 seconds - time.sleep(1) - - try: - next_page_element = WebDriverWait(browser, 600).until( - EC.presence_of_element_located((By.ID, "view")) - ) - browser.save_screenshot(f"output/{mod}/{item}.png") - for _ in tqdm(range(5)): # Pauses the script for 10 seconds - time.sleep(1) - except Exception as e: - console.log(e) - - browser.quit() +class BlastUITester: + """ + Handles automated testing of the BLAST web interface. + """ + + def __init__(self, base_url: str = "https://blast.alliancegenome.org/blast"): + self.base_url = base_url + self.browser = None + + def setup_browser(self) -> None: + """Initialize the Chrome WebDriver with optimized settings.""" + options = webdriver.ChromeOptions() + options.add_argument('--headless') # Run in headless mode + options.add_argument('--no-sandbox') + options.add_argument('--disable-dev-shm-usage') + self.browser = webdriver.Chrome(options=options) + + def cleanup(self) -> None: + """Safely close the browser instance.""" + if self.browser: + self.browser.quit() + + def run_test(self, mod: str, items: List[str], test_type: str, + sequence: str, output_dir: Path) -> None: + """ + Run UI tests for specified BLAST configurations. + + Args: + mod: Model organism database identifier + items: List of UI elements to test + test_type: Type of BLAST search + sequence: Input sequence for BLAST + output_dir: Directory for saving screenshots + """ + # Ensure output directory exists + output_path = output_dir / mod + output_path.mkdir(parents=True, exist_ok=True) + + with Progress( + SpinnerColumn(), + TextColumn("[progress.description]{task.description}"), + console=console + ) as progress: + + for item in items: + task_desc = f"Testing {item}" + progress.add_task(task_desc, total=None) + + try: + self.setup_browser() + url = f"{self.base_url}/{mod}/{test_type}" + self.browser.get(url) + + # Select database + checkbox = WebDriverWait(self.browser, 10).until( + EC.element_to_be_clickable((By.ID, item)) + ) + checkbox.click() + + # Input sequence + input_box = WebDriverWait(self.browser, 10).until( + EC.element_to_be_clickable((By.NAME, "sequence")) + ) + input_box.send_keys(sequence) + + # Submit search + submit_button = WebDriverWait(self.browser, 10).until( + EC.element_to_be_clickable((By.ID, "method")) + ) + submit_button.click() + + # Wait for results and capture screenshot + WebDriverWait(self.browser, 600).until( + EC.presence_of_element_located((By.ID, "view")) + ) + screenshot_path = output_path / f"{item}.png" + self.browser.save_screenshot(str(screenshot_path)) + console.log(f"Screenshot saved: {screenshot_path}") + + except TimeoutException: + console.log(f"[red]Timeout waiting for results: {item}[/red]") + except WebDriverException as e: + console.log(f"[red]Browser error for {item}: {str(e)}[/red]") + except Exception as e: + console.log(f"[red]Unexpected error for {item}: {str(e)}[/red]") + finally: + self.cleanup() -@click.command() -@click.option("-m", "--mod", help="The MOD to test") -@click.option("-t", "--type", help="The DB type to test, i.e. fungal for SGD") -@click.option("-s", "--single_item", help="How many items to test", default=1) -@click.option("-M", "--molecule", help="The molecule to test, nucl or prot only, default nucl", default="nucl") -@click.option( - "-n", - "--number_of_items", - help="number of items to test, random, default all, cannot be used with single item", -) -def prepare_test(mod, type, single_item, number_of_items, molecule): - """ """ - - # print(mod, type, single_item, number_of_items, molecule) - data = json.loads(open("config.json").read()) - run_test(mod, data[mod][type]["items"], type, data[mod][type][molecule]) +@click.command() +@click.option("-m", "--mod", required=True, help="Model organism database to test") +@click.option("-t", "--type", required=True, help="Database type (e.g., fungal for SGD)") +@click.option("-s", "--single_item", type=int, default=1, help="Number of items to test") +@click.option("-M", "--molecule", type=click.Choice(['nucl', 'prot']), + default="nucl", help="Molecule type to test") +@click.option("-n", "--number_of_items", type=int, help="Number of random items to test") +@click.option("-c", "--config", type=click.Path(exists=True), + default="config.json", help="Path to configuration file") +@click.option("-o", "--output", type=click.Path(), + default="output", help="Output directory for screenshots") +def run_blast_tests(mod: str, type: str, single_item: int, + molecule: str, number_of_items: Optional[int], + config: str, output: str) -> None: + """ + Run automated tests for the BLAST web interface. + + This command-line tool allows testing of various BLAST database configurations + with customizable parameters and automated browser interaction. + """ + try: + with open(config) as f: + config_data = json.load(f) + + if mod not in config_data or type not in config_data[mod]: + raise click.BadParameter(f"Invalid MOD/type combination: {mod}/{type}") + + items = config_data[mod][type]["items"] + sequence = config_data[mod][type][molecule] + + if number_of_items and number_of_items < len(items): + import random + items = random.sample(items, number_of_items) + elif single_item > 1: + items = items[:single_item] + + tester = BlastUITester() + tester.run_test(mod, items, type, sequence, Path(output)) + + except json.JSONDecodeError: + console.log("[red]Error: Invalid JSON configuration file[/red]") + except Exception as e: + console.log(f"[red]Error: {str(e)}[/red]") + raise click.Abort() if __name__ == "__main__": - prepare_test() + run_blast_tests() \ No newline at end of file diff --git a/tests/UI/utils.py b/tests/UI/utils.py index ab18a52..7882ef3 100644 --- a/tests/UI/utils.py +++ b/tests/UI/utils.py @@ -1,29 +1,132 @@ +""" +utils.py + +This module provides utilities for web scraping and HTML parsing, +specifically focused on extracting BLAST-related information from +web pages. + +Features: +- HTML parsing with BeautifulSoup +- Command-line interface for file/URL processing +- Error handling and logging +""" + import sys +from pathlib import Path +from typing import List, Optional +from urllib.parse import urlparse +import click from bs4 import BeautifulSoup +import requests +from rich.console import Console +from rich.progress import Progress, SpinnerColumn, TextColumn + +console = Console() + + +class BlastScraper: + """ + Handles web scraping operations for BLAST-related content. + """ + + def __init__(self): + self.session = requests.Session() + + def extract_items_from_html(self, content: str) -> List[str]: + """ + Extract item IDs from HTML content containing jstree elements. + + Args: + content: HTML content to parse + + Returns: + List of unique item IDs + """ + soup = BeautifulSoup(content, features="html.parser") + items = [ + tag.get("id") for tag in soup.find_all("a", class_="jstree-anchor") + if tag.get("id") + ] + return sorted(list(set(items))) + + def scrape_url(self, url: str) -> List[str]: + """ + Scrape items from a given URL. + + Args: + url: URL to scrape + + Returns: + List of extracted items + + Raises: + requests.RequestException: If URL fetch fails + """ + try: + response = self.session.get(url, timeout=30) + response.raise_for_status() + return self.extract_items_from_html(response.text) + except requests.RequestException as e: + console.log(f"[red]Error fetching URL {url}: {str(e)}[/red]") + raise + + def scrape_file(self, filepath: Path) -> List[str]: + """ + Extract items from a local HTML file. + + Args: + filepath: Path to HTML file + + Returns: + List of extracted items + """ + try: + content = filepath.read_text(encoding='utf-8') + return self.extract_items_from_html(content) + except Exception as e: + console.log(f"[red]Error reading file {filepath}: {str(e)}[/red]") + raise + +@click.group() +def cli(): + """BLAST web scraping utilities.""" + pass -def main(): - if len(sys.argv) != 2: - print("Usage: python script.py ") - return - filename = sys.argv[1] +@cli.command() +@click.argument('source') +@click.option('-o', '--output', type=click.Path(), help='Output file path') +def scrape(source: str, output: Optional[str]) -> None: + """ + Scrape items from a URL or local file. - with open(filename, "r") as f: - data = f.read() + Args: + source: URL or file path to scrape + output: Optional file path to save results + """ + try: + scraper = BlastScraper() - soup = BeautifulSoup(data, features="html.parser") - # print(soup) + # Determine if source is URL or file + parsed = urlparse(source) + if parsed.scheme and parsed.netloc: + items = scraper.scrape_url(source) + else: + items = scraper.scrape_file(Path(source)) - items = [] - for tag in soup.find_all("a", class_="jstree-anchor"): - # print(tag.text) - # print(tag.get("id")) - items.append(tag.get("id")) + # Output results + if output: + Path(output).write_text('\n'.join(items)) + console.log(f"Results saved to {output}") + else: + console.print(items) - print(items) + except Exception as e: + console.log(f"[red]Error: {str(e)}[/red]") + sys.exit(1) if __name__ == "__main__": - main() + cli() \ No newline at end of file