diff --git a/.github/workflows/code_quality.yaml b/.github/workflows/code_quality.yaml index 4c9b7fb6983..4fb33dcf0ad 100644 --- a/.github/workflows/code_quality.yaml +++ b/.github/workflows/code_quality.yaml @@ -13,7 +13,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-python@v3 with: - python-version: "3.10" + python-version: "3.11" - name: Install git-secrets in the repository run: git secrets --install - name: Install git-secrets aws register in the repository diff --git a/.github/workflows/run_build_deploy.yaml b/.github/workflows/run_build_deploy.yaml index 8824a87132f..eba2cf403e9 100644 --- a/.github/workflows/run_build_deploy.yaml +++ b/.github/workflows/run_build_deploy.yaml @@ -5,9 +5,7 @@ on: # branches: # - develop workflow_dispatch: {} -# pull_request: -# types: -# - closed + concurrency: cancel-in-progress: true @@ -26,9 +24,12 @@ env: BUILD_NAME: ${{github.event_name}} BUILD_NUMBER: ${{github.run_id}} ECR_ADDRESS: 917902836630.dkr.ecr.us-east-1.amazonaws.com + DR_ECR_ADDRESS: 973422231492.dkr.ecr.us-west-2.amazonaws.com OUT_DIR: ./out AWS_REGION : "us-east-1" + DR_AWS_REGION : "us-west-2" ECR_REPO: 917902836630.dkr.ecr.us-east-1.amazonaws.com/api-server + DR_ECR_REPO: 973422231492.dkr.ecr.us-west-2.amazonaws.com/api-server jobs: @@ -37,6 +38,7 @@ jobs: runs-on: ubuntu-latest outputs: IMAGE_NAME: ${{ steps.sha.outputs.IMAGE_NAME }} + IMAGE_SHA: ${{ steps.sha.outputs.SHORT_SHA }} steps: - name: Checkout repository uses: actions/checkout@v4 @@ -77,6 +79,17 @@ jobs: run: | aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin ${{ env.ECR_ADDRESS }} + - name: configure aws DR credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::973422231492:role/cmiml-dr-oidc-github-role + role-session-name: gha-oidc-runner + aws-region: ${{ env.DR_AWS_REGION }} + + - name: Login to DR ECR + run: | + aws ecr get-login-password --region ${{ env.DR_AWS_REGION }} | docker login --username AWS --password-stdin ${{ env.DR_ECR_ADDRESS }} + - name: Generate short sha id: sha run: | @@ -94,7 +107,11 @@ jobs: PIPENV_EXTRA_ARGS=--dev cache-to: mode=max,image-manifest=true,oci-mediatypes=true,type=registry,ref=${{ env.ECR_REPO }}:cache cache-from: type=registry,ref=${{ env.ECR_REPO }}:cache - tags: ${{ steps.sha.outputs.IMAGE_NAME }},${{ env.ECR_REPO }}:latest + tags: | + ${{ env.ECR_REPO }}:latest + ${{ env.ECR_REPO }}:${{ steps.sha.outputs.SHORT_SHA }} + ${{ env.DR_ECR_REPO }}:latest + ${{ env.DR_ECR_REPO }}:${{ steps.sha.outputs.SHORT_SHA }} platforms: linux/amd64,linux/arm64 - name: Upload artifacts diff --git a/.github/workflows/run_deploy_dev.yaml b/.github/workflows/run_deploy_dev.yaml index 47d4ac81c98..e4bd537bfe4 100644 --- a/.github/workflows/run_deploy_dev.yaml +++ b/.github/workflows/run_deploy_dev.yaml @@ -24,55 +24,6 @@ env: IMAGE_NAME: ${{ inputs.IMAGE_NAME }} jobs: -# run_migration: -# environment: dev -# name: Run Database Migrations -# runs-on: ubuntu-latest -# env: -# TASK_DEFINITION: migration -# ECS_SERVICE_NAME: migration -# -# steps: -# - name: echo IMAGE_NAME -# run: | -# echo $IMAGE_NAME -# -# - name: configure aws credentials -# uses: aws-actions/configure-aws-credentials@v3 -# with: -# role-to-assume: arn:aws:iam::017925157769:role/cmiml-dev-oidc-github-role -# role-session-name: OIDC-GHA-session -# aws-region: ${{ env.AWS_REGION }} -# -# - name: Download task definition -# run: | -# aws ecs describe-task-definition --task-definition ${{ env.TASK_DEFINITION }} --query taskDefinition > task-definition.json -# -# - name: Render Amazon ECS task definition -# id: task-def -# uses: aws-actions/amazon-ecs-render-task-definition@v1 -# with: -# task-definition: task-definition.json -# container-name: mind_logger -# image: ${{ inputs.IMAGE_NAME }} -# -# - name: Update Task Definition -# uses: aws-actions/amazon-ecs-deploy-task-definition@v1 -# with: -# task-definition: ${{ steps.task-def.outputs.task-definition }} -# -# - name: Run migration container -# id: run-task -# uses: geekcell/github-action-aws-ecs-run-task@v4 -# with: -# cluster: ${{ env.ECS_CLUSTER_NAME }} -# task-definition: ${{ env.TASK_DEFINITION }} -# subnet-ids: subnet-02b7cfd48947b31ef -# security-group-ids: sg-0976f7b2b2b5bf411 -# override-container-command: | -# /bin/sh -# -c -# /fastapi-migrate all deploy_to_ecs: runs-on: ubuntu-latest diff --git a/Pipfile b/Pipfile index 9438a2662f1..7072d500303 100644 --- a/Pipfile +++ b/Pipfile @@ -4,41 +4,27 @@ verify_ssl = true name = "pypi" [packages] -redis = "==5.0.8" -alembic = "==1.13.2" +aio-pika = "==9.4.3" +aiofiles = "==24.1.0" +aiohttp = "==3.10.9" +alembic = "==1.13.3" asyncpg = "==0.29.0" +azure-storage-blob = "==12.22.0" +bcrypt = "==4.2.0" boto3 = "==1.35.16" fastapi = "==0.110.3" # The latest version of the fastapi is not taken because of the issue -# with fastapi-mail that requires 0.21 < starlette < 0.22 # starlette version for those deps ==0.21.0 +# with fastapi-mail that requires 0.21 < starlette < 0.22 + fastapi-mail = "==1.2.9" +firebase-admin = "==6.5.0" httpx = "==0.27.2" jinja2 = "==3.1.4" -bcrypt = "==4.2.0" -passlib = { version = "==1.7.4", extras = ["bcrypt"] } -pyOpenSSL = "==24.2.1" -pydantic = { extras = ["email"], version = "==1.10.18" } -python-jose = { version = "==3.3.0", extras = ["cryptography"] } -python-multipart = "==0.0.9" -sentry-sdk = "~=2.13" -sqlalchemy = { extras = ["asyncio"], version = "==1.4.53" } -uvicorn = { extras = ["standard"], version = "==0.30.6" } -taskiq = { extras = ["reload"], version = "==0.11.7" } -aiohttp = "==3.10.5" -firebase-admin = "==6.5.0" -aio-pika = "==9.4.3" -azure-storage-blob = "==12.22.0" -taskiq-fastapi = "==0.3.2" -taskiq-redis = "==1.0.0" -taskiq-aio-pika = "==0.4.1" -sqlalchemy-utils = "==0.41.2" -typer = "==0.12.5" -aiofiles = "==24.1.0" +nh3 = "==0.2.18" opentelemetry-api = "==1.27.0" -opentelemetry-sdk = "==1.27.0" -opentelemetry-exporter-otlp = "==1.27.0" opentelemetry-distro = "==0.48b0" +opentelemetry-exporter-otlp = "==1.27.0" opentelemetry-instrumentation = "==0.48b0" opentelemetry-instrumentation-asgi = "==0.48b0" opentelemetry-instrumentation-asyncio = "==0.48b0" @@ -49,51 +35,57 @@ opentelemetry-instrumentation-sqlite3 = "==0.48b0" opentelemetry-instrumentation-tortoiseorm = "==0.48b0" opentelemetry-instrumentation-urllib = "==0.48b0" opentelemetry-instrumentation-wsgi = "==0.48b0" +opentelemetry-propagator-aws-xray = "==1.0.2" +opentelemetry-sdk = "==1.27.0" +opentelemetry-sdk-extension-aws = "==2.0.2" opentelemetry-semantic-conventions = "==0.48b0" opentelemetry-test-utils = "==0.48b0" opentelemetry-util-http = "==0.48b0" -opentelemetry-propagator-aws-xray = "==1.0.2" -opentelemetry-sdk-extension-aws = "==2.0.2" -nh3 = "==0.2.18" +pyOpenSSL = "==24.2.1" +pydantic = { extras = ["email"], version = "==1.10.18" } pymongo = "*" +python-multipart = "==0.0.12" +redis = "==5.1.0" +sentry-sdk = "~=2.13" +sqlalchemy = { extras = ["asyncio"], version = "==1.4.53" } +sqlalchemy-utils = "==0.41.2" +taskiq = { extras = ["reload"], version = "==0.11.7" } +taskiq-aio-pika = "==0.4.1" +taskiq-fastapi = "==0.3.2" +taskiq-redis = "==1.0.2" +typer = "==0.12.5" +uvicorn = { extras = ["standard"], version = "==0.30.6" } +pyjwt = "==2.9.0" [dev-packages] -# Nobody knows for what its needed ipdb = "==0.13.13" pudb = "==2024.1.2" -# Linters and Formatters pre-commit = "==3.8.0" -ruff = "==0.6.4" -# Tests +ruff = "==0.6.8" allure-pytest = "==2.13.5" pydantic-factories = "==1.17.3" pytest = "==8.3.3" pytest-asyncio = "~=0.19" pytest-cov = "==5.0.0" -pytest-env = "==1.1.4" +pytest-env = "==1.1.5" pytest-lazy-fixtures = "==1.1.1" pytest-mock = "==3.14.0" nest-asyncio = "==1.6.0" gevent = "==24.2.1" -# MyPy mypy = "==1.11.2" -types-passlib = "==1.7.7.20240819" types-python-dateutil = "==2.9.0.20240906" -types-python-jose = "==3.3.4.20240106" typing-extensions = "==4.12.2" -types-requests = "==2.32.0.20240712" -types-pytz = "==2024.1.0.20240417" +types-requests = "==2.32.0.20240914" +types-pytz = "==2024.2.0.20240913" types-aiofiles = "==24.1.0.20240626" types-cachetools = "==5.5.0.20240820" -# https://github.com/sqlalchemy/sqlalchemy/issues/7714 greenlet = "==3.1.0" -# JSONLD deps only for dev reproschema = "*" cachetools = "==5.3.0" pyld = "==2.0.4" [requires] -python_version = "3.10" +python_version = "3.11" [scripts] cli = "python src/cli.py" diff --git a/Pipfile.lock b/Pipfile.lock index e41225c1e26..7310d3eaf21 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,11 +1,11 @@ { "_meta": { "hash": { - "sha256": "4176cbc56761e9bb9ae86678e121b87dc4381f6d4f4791bb3c92e7d66e354a3b" + "sha256": "07fba85afd88883cc30ca1036d869fc0f7d4e710011fd755224b42b5c4b0cef4" }, "pipfile-spec": 6, "requires": { - "python_version": "3.10" + "python_version": "3.11" }, "sources": [ { @@ -36,109 +36,109 @@ }, "aiohappyeyeballs": { "hashes": [ - "sha256:55a1714f084e63d49639800f95716da97a1f173d46a16dfcfda0016abb93b6b2", - "sha256:7ce92076e249169a13c2f49320d1967425eaf1f407522d707d59cac7628d62bd" + "sha256:75cf88a15106a5002a8eb1dab212525c00d1f4c0fa96e551c9fbe6f09a621586", + "sha256:8a7a83727b2756f394ab2895ea0765a0a8c475e3c71e98d43d76f22b4b435572" ], "markers": "python_version >= '3.8'", - "version": "==2.4.0" + "version": "==2.4.3" }, "aiohttp": { "hashes": [ - "sha256:02594361128f780eecc2a29939d9dfc870e17b45178a867bf61a11b2a4367277", - "sha256:03f2645adbe17f274444953bdea69f8327e9d278d961d85657cb0d06864814c1", - "sha256:074d1bff0163e107e97bd48cad9f928fa5a3eb4b9d33366137ffce08a63e37fe", - "sha256:0912b8a8fadeb32ff67a3ed44249448c20148397c1ed905d5dac185b4ca547bb", - "sha256:0d277cfb304118079e7044aad0b76685d30ecb86f83a0711fc5fb257ffe832ca", - "sha256:0d93400c18596b7dc4794d48a63fb361b01a0d8eb39f28800dc900c8fbdaca91", - "sha256:123dd5b16b75b2962d0fff566effb7a065e33cd4538c1692fb31c3bda2bfb972", - "sha256:17e997105bd1a260850272bfb50e2a328e029c941c2708170d9d978d5a30ad9a", - "sha256:18a01eba2574fb9edd5f6e5fb25f66e6ce061da5dab5db75e13fe1558142e0a3", - "sha256:1923a5c44061bffd5eebeef58cecf68096e35003907d8201a4d0d6f6e387ccaa", - "sha256:1942244f00baaacaa8155eca94dbd9e8cc7017deb69b75ef67c78e89fdad3c77", - "sha256:1b2c16a919d936ca87a3c5f0e43af12a89a3ce7ccbce59a2d6784caba945b68b", - "sha256:1c19de68896747a2aa6257ae4cf6ef59d73917a36a35ee9d0a6f48cff0f94db8", - "sha256:1e72589da4c90337837fdfe2026ae1952c0f4a6e793adbbfbdd40efed7c63599", - "sha256:22c0a23a3b3138a6bf76fc553789cb1a703836da86b0f306b6f0dc1617398abc", - "sha256:2c634a3207a5445be65536d38c13791904fda0748b9eabf908d3fe86a52941cf", - "sha256:2d21ac12dc943c68135ff858c3a989f2194a709e6e10b4c8977d7fcd67dfd511", - "sha256:2f1f1c75c395991ce9c94d3e4aa96e5c59c8356a15b1c9231e783865e2772699", - "sha256:305be5ff2081fa1d283a76113b8df7a14c10d75602a38d9f012935df20731487", - "sha256:33e6bc4bab477c772a541f76cd91e11ccb6d2efa2b8d7d7883591dfb523e5987", - "sha256:349ef8a73a7c5665cca65c88ab24abe75447e28aa3bc4c93ea5093474dfdf0ff", - "sha256:380f926b51b92d02a34119d072f178d80bbda334d1a7e10fa22d467a66e494db", - "sha256:38172a70005252b6893088c0f5e8a47d173df7cc2b2bd88650957eb84fcf5022", - "sha256:391cc3a9c1527e424c6865e087897e766a917f15dddb360174a70467572ac6ce", - "sha256:3a1c32a19ee6bbde02f1cb189e13a71b321256cc1d431196a9f824050b160d5a", - "sha256:4120d7fefa1e2d8fb6f650b11489710091788de554e2b6f8347c7a20ceb003f5", - "sha256:424ae21498790e12eb759040bbb504e5e280cab64693d14775c54269fd1d2bb7", - "sha256:44b324a6b8376a23e6ba25d368726ee3bc281e6ab306db80b5819999c737d820", - "sha256:4790f0e15f00058f7599dab2b206d3049d7ac464dc2e5eae0e93fa18aee9e7bf", - "sha256:4aff049b5e629ef9b3e9e617fa6e2dfeda1bf87e01bcfecaf3949af9e210105e", - "sha256:4b38b1570242fbab8d86a84128fb5b5234a2f70c2e32f3070143a6d94bc854cf", - "sha256:4d46c7b4173415d8e583045fbc4daa48b40e31b19ce595b8d92cf639396c15d5", - "sha256:4f1c9866ccf48a6df2b06823e6ae80573529f2af3a0992ec4fe75b1a510df8a6", - "sha256:4f7acae3cf1a2a2361ec4c8e787eaaa86a94171d2417aae53c0cca6ca3118ff6", - "sha256:54d9ddea424cd19d3ff6128601a4a4d23d54a421f9b4c0fff740505813739a91", - "sha256:58718e181c56a3c02d25b09d4115eb02aafe1a732ce5714ab70326d9776457c3", - "sha256:5ede29d91a40ba22ac1b922ef510aab871652f6c88ef60b9dcdf773c6d32ad7a", - "sha256:61645818edd40cc6f455b851277a21bf420ce347baa0b86eaa41d51ef58ba23d", - "sha256:66bf9234e08fe561dccd62083bf67400bdbf1c67ba9efdc3dac03650e97c6088", - "sha256:673f988370f5954df96cc31fd99c7312a3af0a97f09e407399f61583f30da9bc", - "sha256:676f94c5480d8eefd97c0c7e3953315e4d8c2b71f3b49539beb2aa676c58272f", - "sha256:6c225286f2b13bab5987425558baa5cbdb2bc925b2998038fa028245ef421e75", - "sha256:7384d0b87d4635ec38db9263e6a3f1eb609e2e06087f0aa7f63b76833737b471", - "sha256:7e2fe37ac654032db1f3499fe56e77190282534810e2a8e833141a021faaab0e", - "sha256:7f2bfc0032a00405d4af2ba27f3c429e851d04fad1e5ceee4080a1c570476697", - "sha256:7f6b639c36734eaa80a6c152a238242bedcee9b953f23bb887e9102976343092", - "sha256:814375093edae5f1cb31e3407997cf3eacefb9010f96df10d64829362ae2df69", - "sha256:8224f98be68a84b19f48e0bdc14224b5a71339aff3a27df69989fa47d01296f3", - "sha256:898715cf566ec2869d5cb4d5fb4be408964704c46c96b4be267442d265390f32", - "sha256:8989f46f3d7ef79585e98fa991e6ded55d2f48ae56d2c9fa5e491a6e4effb589", - "sha256:8ba01ebc6175e1e6b7275c907a3a36be48a2d487549b656aa90c8a910d9f3178", - "sha256:8c5c6fa16412b35999320f5c9690c0f554392dc222c04e559217e0f9ae244b92", - "sha256:8c6a4e5e40156d72a40241a25cc226051c0a8d816610097a8e8f517aeacd59a2", - "sha256:8eaf44ccbc4e35762683078b72bf293f476561d8b68ec8a64f98cf32811c323e", - "sha256:8fb4fc029e135859f533025bc82047334e24b0d489e75513144f25408ecaf058", - "sha256:9093a81e18c45227eebe4c16124ebf3e0d893830c6aca7cc310bfca8fe59d857", - "sha256:94c4381ffba9cc508b37d2e536b418d5ea9cfdc2848b9a7fea6aebad4ec6aac1", - "sha256:94fac7c6e77ccb1ca91e9eb4cb0ac0270b9fb9b289738654120ba8cebb1189c6", - "sha256:95c4dc6f61d610bc0ee1edc6f29d993f10febfe5b76bb470b486d90bbece6b22", - "sha256:975218eee0e6d24eb336d0328c768ebc5d617609affaca5dbbd6dd1984f16ed0", - "sha256:ad146dae5977c4dd435eb31373b3fe9b0b1bf26858c6fc452bf6af394067e10b", - "sha256:afe16a84498441d05e9189a15900640a2d2b5e76cf4efe8cbb088ab4f112ee57", - "sha256:b1c43eb1ab7cbf411b8e387dc169acb31f0ca0d8c09ba63f9eac67829585b44f", - "sha256:b90078989ef3fc45cf9221d3859acd1108af7560c52397ff4ace8ad7052a132e", - "sha256:b98e698dc34966e5976e10bbca6d26d6724e6bdea853c7c10162a3235aba6e16", - "sha256:ba5a8b74c2a8af7d862399cdedce1533642fa727def0b8c3e3e02fcb52dca1b1", - "sha256:c31ad0c0c507894e3eaa843415841995bf8de4d6b2d24c6e33099f4bc9fc0d4f", - "sha256:c3b9162bab7e42f21243effc822652dc5bb5e8ff42a4eb62fe7782bcbcdfacf6", - "sha256:c58c6837a2c2a7cf3133983e64173aec11f9c2cd8e87ec2fdc16ce727bcf1a04", - "sha256:c83f7a107abb89a227d6c454c613e7606c12a42b9a4ca9c5d7dad25d47c776ae", - "sha256:cde98f323d6bf161041e7627a5fd763f9fd829bcfcd089804a5fdce7bb6e1b7d", - "sha256:ce91db90dbf37bb6fa0997f26574107e1b9d5ff939315247b7e615baa8ec313b", - "sha256:d00f3c5e0d764a5c9aa5a62d99728c56d455310bcc288a79cab10157b3af426f", - "sha256:d17920f18e6ee090bdd3d0bfffd769d9f2cb4c8ffde3eb203777a3895c128862", - "sha256:d55f011da0a843c3d3df2c2cf4e537b8070a419f891c930245f05d329c4b0689", - "sha256:d742c36ed44f2798c8d3f4bc511f479b9ceef2b93f348671184139e7d708042c", - "sha256:d9a487ef090aea982d748b1b0d74fe7c3950b109df967630a20584f9a99c0683", - "sha256:d9ef084e3dc690ad50137cc05831c52b6ca428096e6deb3c43e95827f531d5ef", - "sha256:da452c2c322e9ce0cfef392e469a26d63d42860f829026a63374fde6b5c5876f", - "sha256:dc4826823121783dccc0871e3f405417ac116055bf184ac04c36f98b75aacd12", - "sha256:de7a5299827253023c55ea549444e058c0eb496931fa05d693b95140a947cb73", - "sha256:e04a1f2a65ad2f93aa20f9ff9f1b672bf912413e5547f60749fa2ef8a644e061", - "sha256:e1ca1ef5ba129718a8fc827b0867f6aa4e893c56eb00003b7367f8a733a9b072", - "sha256:ee40b40aa753d844162dcc80d0fe256b87cba48ca0054f64e68000453caead11", - "sha256:f071854b47d39591ce9a17981c46790acb30518e2f83dfca8db2dfa091178691", - "sha256:f29930bc2921cef955ba39a3ff87d2c4398a0394ae217f41cb02d5c26c8b1b77", - "sha256:f489a2c9e6455d87eabf907ac0b7d230a9786be43fbe884ad184ddf9e9c1e385", - "sha256:f5bf3ead3cb66ab990ee2561373b009db5bc0e857549b6c9ba84b20bc462e172", - "sha256:f6f18898ace4bcd2d41a122916475344a87f1dfdec626ecde9ee802a711bc569", - "sha256:f8112fb501b1e0567a1251a2fd0747baae60a4ab325a871e975b7bb67e59221f", - "sha256:fd31f176429cecbc1ba499d4aba31aaccfea488f418d60376b911269d3b883c5" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==3.10.5" + "sha256:02d1d6610588bcd743fae827bd6f2e47e0d09b346f230824b4c6fb85c6065f9c", + "sha256:03690541e4cc866eef79626cfa1ef4dd729c5c1408600c8cb9e12e1137eed6ab", + "sha256:0bc059ecbce835630e635879f5f480a742e130d9821fbe3d2f76610a6698ee25", + "sha256:0c21c82df33b264216abffff9f8370f303dab65d8eee3767efbbd2734363f677", + "sha256:1298b854fd31d0567cbb916091be9d3278168064fca88e70b8468875ef9ff7e7", + "sha256:1321658f12b6caffafdc35cfba6c882cb014af86bef4e78c125e7e794dfb927b", + "sha256:143b0026a9dab07a05ad2dd9e46aa859bffdd6348ddc5967b42161168c24f857", + "sha256:16e6a51d8bc96b77f04a6764b4ad03eeef43baa32014fce71e882bd71302c7e4", + "sha256:172ad884bb61ad31ed7beed8be776eb17e7fb423f1c1be836d5cb357a096bf12", + "sha256:17c272cfe7b07a5bb0c6ad3f234e0c336fb53f3bf17840f66bd77b5815ab3d16", + "sha256:1a0ee6c0d590c917f1b9629371fce5f3d3f22c317aa96fbdcce3260754d7ea21", + "sha256:2746d8994ebca1bdc55a1e998feff4e94222da709623bb18f6e5cfec8ec01baf", + "sha256:2914caa46054f3b5ff910468d686742ff8cff54b8a67319d75f5d5945fd0a13d", + "sha256:2bbf94d4a0447705b7775417ca8bb8086cc5482023a6e17cdc8f96d0b1b5aba6", + "sha256:2bd9f3eac515c16c4360a6a00c38119333901b8590fe93c3257a9b536026594d", + "sha256:2c33fa6e10bb7ed262e3ff03cc69d52869514f16558db0626a7c5c61dde3c29f", + "sha256:2d37f4718002863b82c6f391c8efd4d3a817da37030a29e2682a94d2716209de", + "sha256:3668d0c2a4d23fb136a753eba42caa2c0abbd3d9c5c87ee150a716a16c6deec1", + "sha256:36d4fba838be5f083f5490ddd281813b44d69685db910907636bc5dca6322316", + "sha256:40ff5b7660f903dc587ed36ef08a88d46840182d9d4b5694e7607877ced698a1", + "sha256:42775de0ca04f90c10c5c46291535ec08e9bcc4756f1b48f02a0657febe89b10", + "sha256:482c85cf3d429844396d939b22bc2a03849cb9ad33344689ad1c85697bcba33a", + "sha256:4e6cb75f8ddd9c2132d00bc03c9716add57f4beff1263463724f6398b813e7eb", + "sha256:4edc3fd701e2b9a0d605a7b23d3de4ad23137d23fc0dbab726aa71d92f11aaaf", + "sha256:4fd16b30567c5b8e167923be6e027eeae0f20cf2b8a26b98a25115f28ad48ee0", + "sha256:5002a02c17fcfd796d20bac719981d2fca9c006aac0797eb8f430a58e9d12431", + "sha256:51d0a4901b27272ae54e42067bc4b9a90e619a690b4dc43ea5950eb3070afc32", + "sha256:558b3d223fd631ad134d89adea876e7fdb4c93c849ef195049c063ada82b7d08", + "sha256:5c070430fda1a550a1c3a4c2d7281d3b8cfc0c6715f616e40e3332201a253067", + "sha256:5f392ef50e22c31fa49b5a46af7f983fa3f118f3eccb8522063bee8bfa6755f8", + "sha256:60555211a006d26e1a389222e3fab8cd379f28e0fbf7472ee55b16c6c529e3a6", + "sha256:608cecd8d58d285bfd52dbca5b6251ca8d6ea567022c8a0eaae03c2589cd9af9", + "sha256:60ad5b8a7452c0f5645c73d4dad7490afd6119d453d302cd5b72b678a85d6044", + "sha256:63649309da83277f06a15bbdc2a54fbe75efb92caa2c25bb57ca37762789c746", + "sha256:6ebdc3b3714afe1b134b3bbeb5f745eed3ecbcff92ab25d80e4ef299e83a5465", + "sha256:6f3c6648aa123bcd73d6f26607d59967b607b0da8ffcc27d418a4b59f4c98c7c", + "sha256:7003f33f5f7da1eb02f0446b0f8d2ccf57d253ca6c2e7a5732d25889da82b517", + "sha256:776e9f3c9b377fcf097c4a04b241b15691e6662d850168642ff976780609303c", + "sha256:85711eec2d875cd88c7eb40e734c4ca6d9ae477d6f26bd2b5bb4f7f60e41b156", + "sha256:87d1e4185c5d7187684d41ebb50c9aeaaaa06ca1875f4c57593071b0409d2444", + "sha256:8a3f063b41cc06e8d0b3fcbbfc9c05b7420f41287e0cd4f75ce0a1f3d80729e6", + "sha256:8b3fb28a9ac8f2558760d8e637dbf27aef1e8b7f1d221e8669a1074d1a266bb2", + "sha256:8bd9125dd0cc8ebd84bff2be64b10fdba7dc6fd7be431b5eaf67723557de3a31", + "sha256:8be1a65487bdfc285bd5e9baf3208c2132ca92a9b4020e9f27df1b16fab998a9", + "sha256:8cc0d13b4e3b1362d424ce3f4e8c79e1f7247a00d792823ffd640878abf28e56", + "sha256:8d9d10d10ec27c0d46ddaecc3c5598c4db9ce4e6398ca872cdde0525765caa2f", + "sha256:8debb45545ad95b58cc16c3c1cc19ad82cffcb106db12b437885dbee265f0ab5", + "sha256:91aa966858593f64c8a65cdefa3d6dc8fe3c2768b159da84c1ddbbb2c01ab4ef", + "sha256:9331dd34145ff105177855017920dde140b447049cd62bb589de320fd6ddd582", + "sha256:99f9678bf0e2b1b695e8028fedac24ab6770937932eda695815d5a6618c37e04", + "sha256:9fdf5c839bf95fc67be5794c780419edb0dbef776edcfc6c2e5e2ffd5ee755fa", + "sha256:a14e4b672c257a6b94fe934ee62666bacbc8e45b7876f9dd9502d0f0fe69db16", + "sha256:a19caae0d670771ea7854ca30df76f676eb47e0fd9b2ee4392d44708f272122d", + "sha256:a35ed3d03910785f7d9d6f5381f0c24002b2b888b298e6f941b2fc94c5055fcd", + "sha256:a61df62966ce6507aafab24e124e0c3a1cfbe23c59732987fc0fd0d71daa0b88", + "sha256:a6e00c8a92e7663ed2be6fcc08a2997ff06ce73c8080cd0df10cc0321a3168d7", + "sha256:ac3196952c673822ebed8871cf8802e17254fff2a2ed4835d9c045d9b88c5ec7", + "sha256:ac74e794e3aee92ae8f571bfeaa103a141e409863a100ab63a253b1c53b707eb", + "sha256:ad3675c126f2a95bde637d162f8231cff6bc0bc9fbe31bd78075f9ff7921e322", + "sha256:aeebd3061f6f1747c011e1d0b0b5f04f9f54ad1a2ca183e687e7277bef2e0da2", + "sha256:ba1a599255ad6a41022e261e31bc2f6f9355a419575b391f9655c4d9e5df5ff5", + "sha256:bbdb8def5268f3f9cd753a265756f49228a20ed14a480d151df727808b4531dd", + "sha256:c2555e4949c8d8782f18ef20e9d39730d2656e218a6f1a21a4c4c0b56546a02e", + "sha256:c2695c61cf53a5d4345a43d689f37fc0f6d3a2dc520660aec27ec0f06288d1f9", + "sha256:c2b627d3c8982691b06d89d31093cee158c30629fdfebe705a91814d49b554f8", + "sha256:c46131c6112b534b178d4e002abe450a0a29840b61413ac25243f1291613806a", + "sha256:c54dc329cd44f7f7883a9f4baaefe686e8b9662e2c6c184ea15cceee587d8d69", + "sha256:c7d7cafc11d70fdd8801abfc2ff276744ae4cb39d8060b6b542c7e44e5f2cfc2", + "sha256:cb0b2d5d51f96b6cc19e6ab46a7b684be23240426ae951dcdac9639ab111b45e", + "sha256:d15a29424e96fad56dc2f3abed10a89c50c099f97d2416520c7a543e8fddf066", + "sha256:d1f5c9169e26db6a61276008582d945405b8316aae2bb198220466e68114a0f5", + "sha256:d271f770b52e32236d945911b2082f9318e90ff835d45224fa9e28374303f729", + "sha256:d646fdd74c25bbdd4a055414f0fe32896c400f38ffbdfc78c68e62812a9e0257", + "sha256:d6e395c3d1f773cf0651cd3559e25182eb0c03a2777b53b4575d8adc1149c6e9", + "sha256:d7c071235a47d407b0e93aa6262b49422dbe48d7d8566e1158fecc91043dd948", + "sha256:d97273a52d7f89a75b11ec386f786d3da7723d7efae3034b4dda79f6f093edc1", + "sha256:dcf354661f54e6a49193d0b5653a1b011ba856e0b7a76bda2c33e4c6892f34ea", + "sha256:e3e7fabedb3fe06933f47f1538df7b3a8d78e13d7167195f51ca47ee12690373", + "sha256:e525b69ee8a92c146ae5b4da9ecd15e518df4d40003b01b454ad694a27f498b5", + "sha256:e709d6ac598c5416f879bb1bae3fd751366120ac3fa235a01de763537385d036", + "sha256:e83dfefb4f7d285c2d6a07a22268344a97d61579b3e0dce482a5be0251d672ab", + "sha256:e86260b76786c28acf0b5fe31c8dca4c2add95098c709b11e8c35b424ebd4f5b", + "sha256:e883b61b75ca6efc2541fcd52a5c8ccfe288b24d97e20ac08fdf343b8ac672ea", + "sha256:f0a44bb40b6aaa4fb9a5c1ee07880570ecda2065433a96ccff409c9c20c1624a", + "sha256:f82ace0ec57c94aaf5b0e118d4366cff5889097412c75aa14b4fd5fc0c44ee3e", + "sha256:f9ca09414003c0e96a735daa1f071f7d7ed06962ef4fa29ceb6c80d06696d900", + "sha256:fa430b871220dc62572cef9c69b41e0d70fcb9d486a4a207a5de4c1f25d82593", + "sha256:fc262c3df78c8ff6020c782d9ce02e4bcffe4900ad71c0ecdad59943cba54442", + "sha256:fcd546782d03181b0b1d20b43d612429a90a68779659ba8045114b867971ab71", + "sha256:fd4ceeae2fb8cabdd1b71c82bfdd39662473d3433ec95b962200e9e752fb70d0", + "sha256:fec5fac7aea6c060f317f07494961236434928e6f4374e170ef50b3001e14581" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==3.10.9" }, "aiormq": { "hashes": [ @@ -166,20 +166,20 @@ }, "alembic": { "hashes": [ - "sha256:1ff0ae32975f4fd96028c39ed9bb3c867fe3af956bd7bb37343b54c9fe7445ef", - "sha256:6b8733129a6224a9a711e17c99b08462dbf7cc9670ba8f2e2ae9af860ceb1953" + "sha256:203503117415561e203aa14541740643a611f641517f0209fcae63e9fa09f1a2", + "sha256:908e905976d15235fae59c9ac42c4c5b75cfcefe3d27c0fbf7ae15a37715d80e" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==1.13.2" + "version": "==1.13.3" }, "anyio": { "hashes": [ - "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94", - "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7" + "sha256:4c8bc31ccdb51c7f7bd251f51c609e038d63e34219b44aa86e47576389880b4c", + "sha256:6d170c36fba3bdd840c73d3868c1e777e33676a69c3a72cf0a0d5d6d8009b61d" ], - "markers": "python_version >= '3.8'", - "version": "==4.4.0" + "markers": "python_version >= '3.9'", + "version": "==4.6.2.post1" }, "asgiref": { "hashes": [ @@ -194,7 +194,7 @@ "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f", "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028" ], - "markers": "python_full_version < '3.12.0'", + "markers": "python_version < '3.12.0'", "version": "==4.0.3" }, "asyncpg": { @@ -255,11 +255,11 @@ }, "azure-core": { "hashes": [ - "sha256:a14dc210efcd608821aa472d9fb8e8d035d29b68993819147bc290a8ac224472", - "sha256:cf019c1ca832e96274ae85abd3d9f752397194d9fea3b41487290562ac8abe4a" + "sha256:22954de3777e0250029360ef31d80448ef1be13b80a459bff80ba7073379e2cd", + "sha256:656a0dd61e1869b1506b7c6a3b31d62f15984b1a573d6326f6aa2f3e4123284b" ], "markers": "python_version >= '3.8'", - "version": "==1.30.2" + "version": "==1.31.0" }, "azure-storage-blob": { "hashes": [ @@ -428,99 +428,114 @@ }, "charset-normalizer": { "hashes": [ - "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027", - "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087", - "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786", - "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8", - "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09", - "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185", - "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574", - "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e", - "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519", - "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898", - "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269", - "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3", - "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f", - "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6", - "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8", - "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a", - "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73", - "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc", - "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714", - "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2", - "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc", - "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce", - "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d", - "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e", - "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6", - "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269", - "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96", - "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d", - "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a", - "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4", - "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77", - "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d", - "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0", - "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed", - "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068", - "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac", - "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25", - "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8", - "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab", - "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26", - "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2", - "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db", - "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f", - "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5", - "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99", - "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c", - "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d", - "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811", - "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa", - "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a", - "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03", - "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b", - "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04", - "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c", - "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001", - "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458", - "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389", - "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99", - "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985", - "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537", - "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238", - "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f", - "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d", - "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796", - "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a", - "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143", - "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8", - "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c", - "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5", - "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5", - "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711", - "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4", - "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6", - "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c", - "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7", - "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4", - "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b", - "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae", - "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12", - "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c", - "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae", - "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8", - "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887", - "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b", - "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4", - "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f", - "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5", - "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33", - "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519", - "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561" + "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621", + "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6", + "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8", + "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912", + "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c", + "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b", + "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d", + "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d", + "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95", + "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e", + "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565", + "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64", + "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab", + "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be", + "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e", + "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907", + "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0", + "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2", + "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62", + "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62", + "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23", + "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc", + "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284", + "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca", + "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455", + "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858", + "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b", + "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594", + "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc", + "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db", + "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b", + "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea", + "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6", + "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920", + "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749", + "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7", + "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd", + "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99", + "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242", + "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee", + "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129", + "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2", + "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51", + "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee", + "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8", + "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b", + "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613", + "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742", + "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe", + "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3", + "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5", + "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631", + "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7", + "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15", + "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c", + "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea", + "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417", + "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250", + "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88", + "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca", + "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa", + "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99", + "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149", + "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41", + "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574", + "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0", + "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f", + "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d", + "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654", + "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3", + "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19", + "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90", + "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578", + "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9", + "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1", + "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51", + "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719", + "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236", + "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a", + "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c", + "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade", + "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944", + "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc", + "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6", + "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6", + "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27", + "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6", + "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2", + "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12", + "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf", + "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114", + "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7", + "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf", + "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d", + "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b", + "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed", + "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03", + "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4", + "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67", + "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365", + "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a", + "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748", + "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b", + "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079", + "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482" ], "markers": "python_full_version >= '3.7.0'", - "version": "==3.3.2" + "version": "==3.4.0" }, "click": { "hashes": [ @@ -573,19 +588,11 @@ }, "dnspython": { "hashes": [ - "sha256:5ef3b9680161f6fa89daf8ad451b5f1a33b18ae8a1c6778cdf4b43f08c0a6e50", - "sha256:e8f0f9c23a7b7cb99ded64e6c3a6f3e701d78f50c55e002b839dea7225cff7cc" + "sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86", + "sha256:ce9c432eda0dc91cf618a5cedf1a4e142651196bbcd2c80e89ed5a907e5cfaf1" ], - "markers": "python_version >= '3.8'", - "version": "==2.6.1" - }, - "ecdsa": { - "hashes": [ - "sha256:2cea9b88407fdac7bbeca0833b189e4c9c53f2ef1e1eaa29f6224dbc809b707a", - "sha256:60eaad1199659900dd0af521ed462b793bbdf867432b3948e87416ae4caf6bf8" - ], - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==0.19.0" + "markers": "python_version >= '3.9'", + "version": "==2.7.0" }, "email-validator": { "hashes": [ @@ -595,14 +602,6 @@ "markers": "python_version >= '3.5'", "version": "==1.3.1" }, - "exceptiongroup": { - "hashes": [ - "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", - "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc" - ], - "markers": "python_version < '3.11'", - "version": "==1.2.2" - }, "fastapi": { "hashes": [ "sha256:555700b0159379e94fdbfc6bb66a0f1c43f4cf7060f25239af3d84b63a656626", @@ -618,7 +617,7 @@ "sha256:e85783a5a05fa8f48677b965ed8f2056535d7c78b8de714359a01f45f1cd3e21" ], "index": "pypi", - "markers": "python_version < '4.0' and python_full_version >= '3.8.1'", + "markers": "python_full_version >= '3.8.1' and python_version < '4.0'", "version": "==1.2.9" }, "firebase-admin": { @@ -724,27 +723,27 @@ "grpc" ], "hashes": [ - "sha256:53ec0258f2837dd53bbd3d3df50f5359281b3cc13f800c941dd15a9b5a415af4", - "sha256:ca07de7e8aa1c98a8bfca9321890ad2340ef7f2eb136e558cee68f24b94b0a8f" + "sha256:4a152fd11a9f774ea606388d423b68aa7e6d6a0ffe4c8266f74979613ec09f81", + "sha256:6869eacb2a37720380ba5898312af79a4d30b8bca1548fb4093e0697dc4bdf5d" ], "markers": "platform_python_implementation != 'PyPy'", - "version": "==2.19.2" + "version": "==2.21.0" }, "google-api-python-client": { "hashes": [ - "sha256:8b84dde11aaccadc127e4846f5cd932331d804ea324e353131595e3f25376e97", - "sha256:d74da1358f3f2d63daf3c6f26bd96d89652051183bc87cf10a56ceb2a70beb50" + "sha256:1a5232e9cfed8c201799d9327e4d44dc7ea7daa3c6e1627fca41aa201539c0da", + "sha256:b9d68c6b14ec72580d66001bd33c5816b78e2134b93ccc5cf8f624516b561750" ], "markers": "python_version >= '3.7'", - "version": "==2.145.0" + "version": "==2.149.0" }, "google-auth": { "hashes": [ - "sha256:72fd4733b80b6d777dcde515628a9eb4a577339437012874ea286bca7261ee65", - "sha256:8eb87396435c19b20d32abd2f984e31c191a15284af72eb922f10e5bde9c04cc" + "sha256:25df55f327ef021de8be50bad0dfd4a916ad0de96da86cd05661c9297723ad3f", + "sha256:f4c64ed4e01e8e8b646ef34c018f8bf3338df0c8e37d8b3bba40e7f574a3278a" ], "markers": "python_version >= '3.7'", - "version": "==2.34.0" + "version": "==2.35.0" }, "google-auth-httplib2": { "hashes": [ @@ -763,11 +762,11 @@ }, "google-cloud-firestore": { "hashes": [ - "sha256:3db5dd42334b9904d82b3786703a5a4b576810fb50f61b8fa83ecf4f17b7fdae", - "sha256:9a735860b692f39f93f900dd3390713ceb9b47ea82cda98360bb551f03d2b916" + "sha256:1b2ce6e0b791aee89a1e4f072beba1012247e89baca361eed721fb467fe054b0", + "sha256:b49f0019d7bd0d4ab5972a4cff13994b0aabe72d24242200d904db2fb49df7f7" ], "markers": "platform_python_implementation != 'PyPy'", - "version": "==2.18.0" + "version": "==2.19.0" }, "google-cloud-storage": { "hashes": [ @@ -828,127 +827,142 @@ }, "greenlet": { "hashes": [ - "sha256:01059afb9b178606b4b6e92c3e710ea1635597c3537e44da69f4531e111dd5e9", - "sha256:037d9ac99540ace9424cb9ea89f0accfaff4316f149520b4ae293eebc5bded17", - "sha256:0e49a65d25d7350cca2da15aac31b6f67a43d867448babf997fe83c7505f57bc", - "sha256:13ff8c8e54a10472ce3b2a2da007f915175192f18e6495bad50486e87c7f6637", - "sha256:1544b8dd090b494c55e60c4ff46e238be44fdc472d2589e943c241e0169bcea2", - "sha256:184258372ae9e1e9bddce6f187967f2e08ecd16906557c4320e3ba88a93438c3", - "sha256:1ddc7bcedeb47187be74208bc652d63d6b20cb24f4e596bd356092d8000da6d6", - "sha256:221169d31cada333a0c7fd087b957c8f431c1dba202c3a58cf5a3583ed973e9b", - "sha256:243a223c96a4246f8a30ea470c440fe9db1f5e444941ee3c3cd79df119b8eebf", - "sha256:24fc216ec7c8be9becba8b64a98a78f9cd057fd2dc75ae952ca94ed8a893bf27", - "sha256:2651dfb006f391bcb240635079a68a261b227a10a08af6349cba834a2141efa1", - "sha256:26811df4dc81271033a7836bc20d12cd30938e6bd2e9437f56fa03da81b0f8fc", - "sha256:26d9c1c4f1748ccac0bae1dbb465fb1a795a75aba8af8ca871503019f4285e2a", - "sha256:28fe80a3eb673b2d5cc3b12eea468a5e5f4603c26aa34d88bf61bba82ceb2f9b", - "sha256:2cd8518eade968bc52262d8c46727cfc0826ff4d552cf0430b8d65aaf50bb91d", - "sha256:2d004db911ed7b6218ec5c5bfe4cf70ae8aa2223dffbb5b3c69e342bb253cb28", - "sha256:3d07c28b85b350564bdff9f51c1c5007dfb2f389385d1bc23288de51134ca303", - "sha256:3e7e6ef1737a819819b1163116ad4b48d06cfdd40352d813bb14436024fcda99", - "sha256:44151d7b81b9391ed759a2f2865bbe623ef00d648fed59363be2bbbd5154656f", - "sha256:44cd313629ded43bb3b98737bba2f3e2c2c8679b55ea29ed73daea6b755fe8e7", - "sha256:4a3dae7492d16e85ea6045fd11cb8e782b63eac8c8d520c3a92c02ac4573b0a6", - "sha256:4b5ea3664eed571779403858d7cd0a9b0ebf50d57d2cdeafc7748e09ef8cd81a", - "sha256:4c3446937be153718250fe421da548f973124189f18fe4575a0510b5c928f0cc", - "sha256:5415b9494ff6240b09af06b91a375731febe0090218e2898d2b85f9b92abcda0", - "sha256:5fd6e94593f6f9714dbad1aaba734b5ec04593374fa6638df61592055868f8b8", - "sha256:619935a44f414274a2c08c9e74611965650b730eb4efe4b2270f91df5e4adf9a", - "sha256:655b21ffd37a96b1e78cc48bf254f5ea4b5b85efaf9e9e2a526b3c9309d660ca", - "sha256:665b21e95bc0fce5cab03b2e1d90ba9c66c510f1bb5fdc864f3a377d0f553f6b", - "sha256:6a4bf607f690f7987ab3291406e012cd8591a4f77aa54f29b890f9c331e84989", - "sha256:6cea1cca3be76c9483282dc7760ea1cc08a6ecec1f0b6ca0a94ea0d17432da19", - "sha256:713d450cf8e61854de9420fb7eea8ad228df4e27e7d4ed465de98c955d2b3fa6", - "sha256:726377bd60081172685c0ff46afbc600d064f01053190e4450857483c4d44484", - "sha256:76b3e3976d2a452cba7aa9e453498ac72240d43030fdc6d538a72b87eaff52fd", - "sha256:76dc19e660baea5c38e949455c1181bc018893f25372d10ffe24b3ed7341fb25", - "sha256:76e5064fd8e94c3f74d9fd69b02d99e3cdb8fc286ed49a1f10b256e59d0d3a0b", - "sha256:7f346d24d74c00b6730440f5eb8ec3fe5774ca8d1c9574e8e57c8671bb51b910", - "sha256:81eeec4403a7d7684b5812a8aaa626fa23b7d0848edb3a28d2eb3220daddcbd0", - "sha256:90b5bbf05fe3d3ef697103850c2ce3374558f6fe40fd57c9fac1bf14903f50a5", - "sha256:9730929375021ec90f6447bff4f7f5508faef1c02f399a1953870cdb78e0c345", - "sha256:9eb4a1d7399b9f3c7ac68ae6baa6be5f9195d1d08c9ddc45ad559aa6b556bce6", - "sha256:a0409bc18a9f85321399c29baf93545152d74a49d92f2f55302f122007cfda00", - "sha256:a22f4e26400f7f48faef2d69c20dc055a1f3043d330923f9abe08ea0aecc44df", - "sha256:a53dfe8f82b715319e9953330fa5c8708b610d48b5c59f1316337302af5c0811", - "sha256:a771dc64fa44ebe58d65768d869fcfb9060169d203446c1d446e844b62bdfdca", - "sha256:a814dc3100e8a046ff48faeaa909e80cdb358411a3d6dd5293158425c684eda8", - "sha256:a8870983af660798dc1b529e1fd6f1cefd94e45135a32e58bd70edd694540f33", - "sha256:ac0adfdb3a21dc2a24ed728b61e72440d297d0fd3a577389df566651fcd08f97", - "sha256:b395121e9bbe8d02a750886f108d540abe66075e61e22f7353d9acb0b81be0f0", - "sha256:b9505a0c8579899057cbefd4ec34d865ab99852baf1ff33a9481eb3924e2da0b", - "sha256:c0a5b1c22c82831f56f2f7ad9bbe4948879762fe0d59833a4a71f16e5fa0f682", - "sha256:c3967dcc1cd2ea61b08b0b276659242cbce5caca39e7cbc02408222fb9e6ff39", - "sha256:c6f4c2027689093775fd58ca2388d58789009116844432d920e9147f91acbe64", - "sha256:c9d86401550b09a55410f32ceb5fe7efcd998bd2dad9e82521713cb148a4a15f", - "sha256:cd468ec62257bb4544989402b19d795d2305eccb06cde5da0eb739b63dc04665", - "sha256:cfcfb73aed40f550a57ea904629bdaf2e562c68fa1164fa4588e752af6efdc3f", - "sha256:d0dd943282231480aad5f50f89bdf26690c995e8ff555f26d8a5b9887b559bcc", - "sha256:d3c59a06c2c28a81a026ff11fbf012081ea34fb9b7052f2ed0366e14896f0a1d", - "sha256:d45b75b0f3fd8d99f62eb7908cfa6d727b7ed190737dec7fe46d993da550b81a", - "sha256:d46d5069e2eeda111d6f71970e341f4bd9aeeee92074e649ae263b834286ecc0", - "sha256:d58ec349e0c2c0bc6669bf2cd4982d2f93bf067860d23a0ea1fe677b0f0b1e09", - "sha256:db1b3ccb93488328c74e97ff888604a8b95ae4f35f4f56677ca57a4fc3a4220b", - "sha256:dd65695a8df1233309b701dec2539cc4b11e97d4fcc0f4185b4a12ce54db0491", - "sha256:f9482c2ed414781c0af0b35d9d575226da6b728bd1a720668fa05837184965b7", - "sha256:f9671e7282d8c6fcabc32c0fb8d7c0ea8894ae85cee89c9aadc2d7129e1a9954", - "sha256:fad7a051e07f64e297e6e8399b4d6a3bdcad3d7297409e9a06ef8cbccff4f501", - "sha256:ffb08f2a1e59d38c7b8b9ac8083c9c8b9875f0955b1e9b9b9a965607a51f8e54" - ], - "markers": "python_version >= '3.7'", - "version": "==3.1.0" + "sha256:0153404a4bb921f0ff1abeb5ce8a5131da56b953eda6e14b88dc6bbc04d2049e", + "sha256:03a088b9de532cbfe2ba2034b2b85e82df37874681e8c470d6fb2f8c04d7e4b7", + "sha256:04b013dc07c96f83134b1e99888e7a79979f1a247e2a9f59697fa14b5862ed01", + "sha256:05175c27cb459dcfc05d026c4232f9de8913ed006d42713cb8a5137bd49375f1", + "sha256:09fc016b73c94e98e29af67ab7b9a879c307c6731a2c9da0db5a7d9b7edd1159", + "sha256:0bbae94a29c9e5c7e4a2b7f0aae5c17e8e90acbfd3bf6270eeba60c39fce3563", + "sha256:0fde093fb93f35ca72a556cf72c92ea3ebfda3d79fc35bb19fbe685853869a83", + "sha256:1443279c19fca463fc33e65ef2a935a5b09bb90f978beab37729e1c3c6c25fe9", + "sha256:1776fd7f989fc6b8d8c8cb8da1f6b82c5814957264d1f6cf818d475ec2bf6395", + "sha256:1d3755bcb2e02de341c55b4fca7a745a24a9e7212ac953f6b3a48d117d7257aa", + "sha256:23f20bb60ae298d7d8656c6ec6db134bca379ecefadb0b19ce6f19d1f232a942", + "sha256:275f72decf9932639c1c6dd1013a1bc266438eb32710016a1c742df5da6e60a1", + "sha256:2846930c65b47d70b9d178e89c7e1a69c95c1f68ea5aa0a58646b7a96df12441", + "sha256:3319aa75e0e0639bc15ff54ca327e8dc7a6fe404003496e3c6925cd3142e0e22", + "sha256:346bed03fe47414091be4ad44786d1bd8bef0c3fcad6ed3dee074a032ab408a9", + "sha256:36b89d13c49216cadb828db8dfa6ce86bbbc476a82d3a6c397f0efae0525bdd0", + "sha256:37b9de5a96111fc15418819ab4c4432e4f3c2ede61e660b1e33971eba26ef9ba", + "sha256:396979749bd95f018296af156201d6211240e7a23090f50a8d5d18c370084dc3", + "sha256:3b2813dc3de8c1ee3f924e4d4227999285fd335d1bcc0d2be6dc3f1f6a318ec1", + "sha256:411f015496fec93c1c8cd4e5238da364e1da7a124bcb293f085bf2860c32c6f6", + "sha256:47da355d8687fd65240c364c90a31569a133b7b60de111c255ef5b606f2ae291", + "sha256:48ca08c771c268a768087b408658e216133aecd835c0ded47ce955381105ba39", + "sha256:4afe7ea89de619adc868e087b4d2359282058479d7cfb94970adf4b55284574d", + "sha256:4ce3ac6cdb6adf7946475d7ef31777c26d94bccc377e070a7986bd2d5c515467", + "sha256:4ead44c85f8ab905852d3de8d86f6f8baf77109f9da589cb4fa142bd3b57b475", + "sha256:54558ea205654b50c438029505def3834e80f0869a70fb15b871c29b4575ddef", + "sha256:5e06afd14cbaf9e00899fae69b24a32f2196c19de08fcb9f4779dd4f004e5e7c", + "sha256:62ee94988d6b4722ce0028644418d93a52429e977d742ca2ccbe1c4f4a792511", + "sha256:63e4844797b975b9af3a3fb8f7866ff08775f5426925e1e0bbcfe7932059a12c", + "sha256:6510bf84a6b643dabba74d3049ead221257603a253d0a9873f55f6a59a65f822", + "sha256:667a9706c970cb552ede35aee17339a18e8f2a87a51fba2ed39ceeeb1004798a", + "sha256:6ef9ea3f137e5711f0dbe5f9263e8c009b7069d8a1acea822bd5e9dae0ae49c8", + "sha256:7017b2be767b9d43cc31416aba48aab0d2309ee31b4dbf10a1d38fb7972bdf9d", + "sha256:7124e16b4c55d417577c2077be379514321916d5790fa287c9ed6f23bd2ffd01", + "sha256:73aaad12ac0ff500f62cebed98d8789198ea0e6f233421059fa68a5aa7220145", + "sha256:77c386de38a60d1dfb8e55b8c1101d68c79dfdd25c7095d51fec2dd800892b80", + "sha256:7876452af029456b3f3549b696bb36a06db7c90747740c5302f74a9e9fa14b13", + "sha256:7939aa3ca7d2a1593596e7ac6d59391ff30281ef280d8632fa03d81f7c5f955e", + "sha256:8320f64b777d00dd7ccdade271eaf0cad6636343293a25074cc5566160e4de7b", + "sha256:85f3ff71e2e60bd4b4932a043fbbe0f499e263c628390b285cb599154a3b03b1", + "sha256:8b8b36671f10ba80e159378df9c4f15c14098c4fd73a36b9ad715f057272fbef", + "sha256:93147c513fac16385d1036b7e5b102c7fbbdb163d556b791f0f11eada7ba65dc", + "sha256:935e943ec47c4afab8965954bf49bfa639c05d4ccf9ef6e924188f762145c0ff", + "sha256:94b6150a85e1b33b40b1464a3f9988dcc5251d6ed06842abff82e42632fac120", + "sha256:94ebba31df2aa506d7b14866fed00ac141a867e63143fe5bca82a8e503b36437", + "sha256:95ffcf719966dd7c453f908e208e14cde192e09fde6c7186c8f1896ef778d8cd", + "sha256:98884ecf2ffb7d7fe6bd517e8eb99d31ff7855a840fa6d0d63cd07c037f6a981", + "sha256:99cfaa2110534e2cf3ba31a7abcac9d328d1d9f1b95beede58294a60348fba36", + "sha256:9e8f8c9cb53cdac7ba9793c276acd90168f416b9ce36799b9b885790f8ad6c0a", + "sha256:a0dfc6c143b519113354e780a50381508139b07d2177cb6ad6a08278ec655798", + "sha256:b2795058c23988728eec1f36a4e5e4ebad22f8320c85f3587b539b9ac84128d7", + "sha256:b42703b1cf69f2aa1df7d1030b9d77d3e584a70755674d60e710f0af570f3761", + "sha256:b7cede291382a78f7bb5f04a529cb18e068dd29e0fb27376074b6d0317bf4dd0", + "sha256:b8a678974d1f3aa55f6cc34dc480169d58f2e6d8958895d68845fa4ab566509e", + "sha256:b8da394b34370874b4572676f36acabac172602abf054cbc4ac910219f3340af", + "sha256:c3a701fe5a9695b238503ce5bbe8218e03c3bcccf7e204e455e7462d770268aa", + "sha256:c4aab7f6381f38a4b42f269057aee279ab0fc7bf2e929e3d4abfae97b682a12c", + "sha256:ca9d0ff5ad43e785350894d97e13633a66e2b50000e8a183a50a88d834752d42", + "sha256:d0028e725ee18175c6e422797c407874da24381ce0690d6b9396c204c7f7276e", + "sha256:d21e10da6ec19b457b82636209cbe2331ff4306b54d06fa04b7c138ba18c8a81", + "sha256:d5e975ca70269d66d17dd995dafc06f1b06e8cb1ec1e9ed54c1d1e4a7c4cf26e", + "sha256:da7a9bff22ce038e19bf62c4dd1ec8391062878710ded0a845bcf47cc0200617", + "sha256:db32b5348615a04b82240cc67983cb315309e88d444a288934ee6ceaebcad6cc", + "sha256:dcc62f31eae24de7f8dce72134c8651c58000d3b1868e01392baea7c32c247de", + "sha256:dfc59d69fc48664bc693842bd57acfdd490acafda1ab52c7836e3fc75c90a111", + "sha256:e347b3bfcf985a05e8c0b7d462ba6f15b1ee1c909e2dcad795e49e91b152c383", + "sha256:e4d333e558953648ca09d64f13e6d8f0523fa705f51cae3f03b5983489958c70", + "sha256:ed10eac5830befbdd0c32f83e8aa6288361597550ba669b04c48f0f9a2c843c6", + "sha256:efc0f674aa41b92da8c49e0346318c6075d734994c3c4e4430b1c3f853e498e4", + "sha256:f1695e76146579f8c06c1509c7ce4dfe0706f49c6831a817ac04eebb2fd02011", + "sha256:f1d4aeb8891338e60d1ab6127af1fe45def5259def8094b9c7e34690c8858803", + "sha256:f406b22b7c9a9b4f8aa9d2ab13d6ae0ac3e85c9a809bd590ad53fed2bf70dc79", + "sha256:f6ff3b14f2df4c41660a7dec01045a045653998784bf8cfcb5a525bdffffbc8f" + ], + "version": "==3.1.1" }, "grpcio": { "hashes": [ - "sha256:0e6c9b42ded5d02b6b1fea3a25f036a2236eeb75d0579bfd43c0018c88bf0a3e", - "sha256:161d5c535c2bdf61b95080e7f0f017a1dfcb812bf54093e71e5562b16225b4ce", - "sha256:17663598aadbedc3cacd7bbde432f541c8e07d2496564e22b214b22c7523dac8", - "sha256:1c17ebcec157cfb8dd445890a03e20caf6209a5bd4ac5b040ae9dbc59eef091d", - "sha256:292a846b92cdcd40ecca46e694997dd6b9be6c4c01a94a0dfb3fcb75d20da858", - "sha256:2ca2559692d8e7e245d456877a85ee41525f3ed425aa97eb7a70fc9a79df91a0", - "sha256:307b1d538140f19ccbd3aed7a93d8f71103c5d525f3c96f8616111614b14bf2a", - "sha256:30a1c2cf9390c894c90bbc70147f2372130ad189cffef161f0432d0157973f45", - "sha256:31a049daa428f928f21090403e5d18ea02670e3d5d172581670be006100db9ef", - "sha256:35334f9c9745add3e357e3372756fd32d925bd52c41da97f4dfdafbde0bf0ee2", - "sha256:3750c5a00bd644c75f4507f77a804d0189d97a107eb1481945a0cf3af3e7a5ac", - "sha256:3885f037eb11f1cacc41f207b705f38a44b69478086f40608959bf5ad85826dd", - "sha256:4573608e23f7e091acfbe3e84ac2045680b69751d8d67685ffa193a4429fedb1", - "sha256:4825a3aa5648010842e1c9d35a082187746aa0cdbf1b7a2a930595a94fb10fce", - "sha256:4877ba180591acdf127afe21ec1c7ff8a5ecf0fe2600f0d3c50e8c4a1cbc6492", - "sha256:48b0d92d45ce3be2084b92fb5bae2f64c208fea8ceed7fccf6a7b524d3c4942e", - "sha256:4d813316d1a752be6f5c4360c49f55b06d4fe212d7df03253dfdae90c8a402bb", - "sha256:5dd67ed9da78e5121efc5c510f0122a972216808d6de70953a740560c572eb44", - "sha256:6f914386e52cbdeb5d2a7ce3bf1fdfacbe9d818dd81b6099a05b741aaf3848bb", - "sha256:7101db1bd4cd9b880294dec41a93fcdce465bdbb602cd8dc5bd2d6362b618759", - "sha256:7e06aa1f764ec8265b19d8f00140b8c4b6ca179a6dc67aa9413867c47e1fb04e", - "sha256:84ca1be089fb4446490dd1135828bd42a7c7f8421e74fa581611f7afdf7ab761", - "sha256:8a1e224ce6f740dbb6b24c58f885422deebd7eb724aff0671a847f8951857c26", - "sha256:97ae7edd3f3f91480e48ede5d3e7d431ad6005bfdbd65c1b56913799ec79e791", - "sha256:9c9bebc6627873ec27a70fc800f6083a13c70b23a5564788754b9ee52c5aef6c", - "sha256:a013c5fbb12bfb5f927444b477a26f1080755a931d5d362e6a9a720ca7dbae60", - "sha256:a66fe4dc35d2330c185cfbb42959f57ad36f257e0cc4557d11d9f0a3f14311df", - "sha256:a92c4f58c01c77205df6ff999faa008540475c39b835277fb8883b11cada127a", - "sha256:aa8ba945c96e73de29d25331b26f3e416e0c0f621e984a3ebdb2d0d0b596a3b3", - "sha256:b0aa03d240b5539648d996cc60438f128c7f46050989e35b25f5c18286c86734", - "sha256:b1b24c23d51a1e8790b25514157d43f0a4dce1ac12b3f0b8e9f66a5e2c4c132f", - "sha256:b7ffb8ea674d68de4cac6f57d2498fef477cef582f1fa849e9f844863af50083", - "sha256:b9feb4e5ec8dc2d15709f4d5fc367794d69277f5d680baf1910fc9915c633524", - "sha256:bff2096bdba686019fb32d2dde45b95981f0d1490e054400f70fc9a8af34b49d", - "sha256:c30aeceeaff11cd5ddbc348f37c58bcb96da8d5aa93fed78ab329de5f37a0d7a", - "sha256:c9f80f9fad93a8cf71c7f161778ba47fd730d13a343a46258065c4deb4b550c0", - "sha256:cfd349de4158d797db2bd82d2020554a121674e98fbe6b15328456b3bf2495bb", - "sha256:d0cd7050397b3609ea51727b1811e663ffda8bda39c6a5bb69525ef12414b503", - "sha256:d639c939ad7c440c7b2819a28d559179a4508783f7e5b991166f8d7a34b52815", - "sha256:e3ba04659e4fce609de2658fe4dbf7d6ed21987a94460f5f92df7579fd5d0e22", - "sha256:ecfe735e7a59e5a98208447293ff8580e9db1e890e232b8b292dc8bd15afc0d2", - "sha256:ef82d361ed5849d34cf09105d00b94b6728d289d6b9235513cb2fcc79f7c432c", - "sha256:f03a5884c56256e08fd9e262e11b5cfacf1af96e2ce78dc095d2c41ccae2c80d", - "sha256:f1fe60d0772831d96d263b53d83fb9a3d050a94b0e94b6d004a5ad111faa5b5b", - "sha256:f517fd7259fe823ef3bd21e508b653d5492e706e9f0ef82c16ce3347a8a5620c", - "sha256:fdb14bad0835914f325349ed34a51940bc2ad965142eb3090081593c6e347be9" - ], - "markers": "python_version >= '3.8'", - "version": "==1.66.1" + "sha256:02697eb4a5cbe5a9639f57323b4c37bcb3ab2d48cec5da3dc2f13334d72790dd", + "sha256:03b0b307ba26fae695e067b94cbb014e27390f8bc5ac7a3a39b7723fed085604", + "sha256:05bc2ceadc2529ab0b227b1310d249d95d9001cd106aa4d31e8871ad3c428d73", + "sha256:06de8ec0bd71be123eec15b0e0d457474931c2c407869b6c349bd9bed4adbac3", + "sha256:0be4e0490c28da5377283861bed2941d1d20ec017ca397a5df4394d1c31a9b50", + "sha256:12fda97ffae55e6526825daf25ad0fa37483685952b5d0f910d6405c87e3adb6", + "sha256:1caa38fb22a8578ab8393da99d4b8641e3a80abc8fd52646f1ecc92bcb8dee34", + "sha256:2018b053aa15782db2541ca01a7edb56a0bf18c77efed975392583725974b249", + "sha256:20657d6b8cfed7db5e11b62ff7dfe2e12064ea78e93f1434d61888834bc86d75", + "sha256:2335c58560a9e92ac58ff2bc5649952f9b37d0735608242973c7a8b94a6437d8", + "sha256:31fd163105464797a72d901a06472860845ac157389e10f12631025b3e4d0453", + "sha256:38b68498ff579a3b1ee8f93a05eb48dc2595795f2f62716e797dc24774c1aaa8", + "sha256:3b00efc473b20d8bf83e0e1ae661b98951ca56111feb9b9611df8efc4fe5d55d", + "sha256:3ed71e81782966ffead60268bbda31ea3f725ebf8aa73634d5dda44f2cf3fb9c", + "sha256:45a3d462826f4868b442a6b8fdbe8b87b45eb4f5b5308168c156b21eca43f61c", + "sha256:49f0ca7ae850f59f828a723a9064cadbed90f1ece179d375966546499b8a2c9c", + "sha256:4e504572433f4e72b12394977679161d495c4c9581ba34a88d843eaf0f2fbd39", + "sha256:4ea1d062c9230278793820146c95d038dc0f468cbdd172eec3363e42ff1c7d01", + "sha256:563588c587b75c34b928bc428548e5b00ea38c46972181a4d8b75ba7e3f24231", + "sha256:6001e575b8bbd89eee11960bb640b6da6ae110cf08113a075f1e2051cc596cae", + "sha256:66a0cd8ba6512b401d7ed46bb03f4ee455839957f28b8d61e7708056a806ba6a", + "sha256:6851de821249340bdb100df5eacfecfc4e6075fa85c6df7ee0eb213170ec8e5d", + "sha256:728bdf36a186e7f51da73be7f8d09457a03061be848718d0edf000e709418987", + "sha256:73e3b425c1e155730273f73e419de3074aa5c5e936771ee0e4af0814631fb30a", + "sha256:73fc8f8b9b5c4a03e802b3cd0c18b2b06b410d3c1dcbef989fdeb943bd44aff7", + "sha256:78fa51ebc2d9242c0fc5db0feecc57a9943303b46664ad89921f5079e2e4ada7", + "sha256:7b2c86457145ce14c38e5bf6bdc19ef88e66c5fee2c3d83285c5aef026ba93b3", + "sha256:7d69ce1f324dc2d71e40c9261d3fdbe7d4c9d60f332069ff9b2a4d8a257c7b2b", + "sha256:802d84fd3d50614170649853d121baaaa305de7b65b3e01759247e768d691ddf", + "sha256:80fd702ba7e432994df208f27514280b4b5c6843e12a48759c9255679ad38db8", + "sha256:8ac475e8da31484efa25abb774674d837b343afb78bb3bcdef10f81a93e3d6bf", + "sha256:950da58d7d80abd0ea68757769c9db0a95b31163e53e5bb60438d263f4bed7b7", + "sha256:99a641995a6bc4287a6315989ee591ff58507aa1cbe4c2e70d88411c4dcc0839", + "sha256:9c3a99c519f4638e700e9e3f83952e27e2ea10873eecd7935823dab0c1c9250e", + "sha256:9c509a4f78114cbc5f0740eb3d7a74985fd2eff022971bc9bc31f8bc93e66a3b", + "sha256:a18e20d8321c6400185b4263e27982488cb5cdd62da69147087a76a24ef4e7e3", + "sha256:a917d26e0fe980b0ac7bfcc1a3c4ad6a9a4612c911d33efb55ed7833c749b0ee", + "sha256:a9539f01cb04950fd4b5ab458e64a15f84c2acc273670072abe49a3f29bbad54", + "sha256:ad2efdbe90c73b0434cbe64ed372e12414ad03c06262279b104a029d1889d13e", + "sha256:b672abf90a964bfde2d0ecbce30f2329a47498ba75ce6f4da35a2f4532b7acbc", + "sha256:bbd27c24a4cc5e195a7f56cfd9312e366d5d61b86e36d46bbe538457ea6eb8dd", + "sha256:c400ba5675b67025c8a9f48aa846f12a39cf0c44df5cd060e23fda5b30e9359d", + "sha256:c408f5ef75cfffa113cacd8b0c0e3611cbfd47701ca3cdc090594109b9fcbaed", + "sha256:c806852deaedee9ce8280fe98955c9103f62912a5b2d5ee7e3eaa284a6d8d8e7", + "sha256:ce89f5876662f146d4c1f695dda29d4433a5d01c8681fbd2539afff535da14d4", + "sha256:d25a14af966438cddf498b2e338f88d1c9706f3493b1d73b93f695c99c5f0e2a", + "sha256:d8d4732cc5052e92cea2f78b233c2e2a52998ac40cd651f40e398893ad0d06ec", + "sha256:d9a9724a156c8ec6a379869b23ba3323b7ea3600851c91489b871e375f710bc8", + "sha256:e636ce23273683b00410f1971d209bf3689238cf5538d960adc3cdfe80dd0dbd", + "sha256:e88264caad6d8d00e7913996030bac8ad5f26b7411495848cc218bd3a9040b6c", + "sha256:f145cc21836c332c67baa6fc81099d1d27e266401565bf481948010d6ea32d46", + "sha256:fb57870449dfcfac428afbb5a877829fcb0d6db9d9baa1148705739e9083880e", + "sha256:fb70487c95786e345af5e854ffec8cb8cc781bcc5df7930c4fbb7feaa72e1cdf", + "sha256:fe96281713168a3270878255983d2cb1a97e034325c8c2c25169a69289d3ecfa", + "sha256:ff1f7882e56c40b0d33c4922c15dfa30612f05fb785074a012f7cda74d1c3679" + ], + "markers": "python_version >= '3.8'", + "version": "==1.66.2" }, "grpcio-status": { "hashes": [ @@ -967,11 +981,11 @@ }, "httpcore": { "hashes": [ - "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61", - "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5" + "sha256:27b59625743b85577a8c0e10e55b50b5368a4f2cfe8cc7bcfa9cf00829c2682f", + "sha256:73f6dbd6eb8c21bbf7ef8efad555481853f5f6acdeaff1edb0694289269ee17f" ], "markers": "python_version >= '3.8'", - "version": "==1.0.5" + "version": "==1.0.6" }, "httplib2": { "hashes": [ @@ -983,44 +997,51 @@ }, "httptools": { "hashes": [ - "sha256:00d5d4b68a717765b1fabfd9ca755bd12bf44105eeb806c03d1962acd9b8e563", - "sha256:0ac5a0ae3d9f4fe004318d64b8a854edd85ab76cffbf7ef5e32920faef62f142", - "sha256:0cf2372e98406efb42e93bfe10f2948e467edfd792b015f1b4ecd897903d3e8d", - "sha256:1ed99a373e327f0107cb513b61820102ee4f3675656a37a50083eda05dc9541b", - "sha256:3c3b214ce057c54675b00108ac42bacf2ab8f85c58e3f324a4e963bbc46424f4", - "sha256:3e802e0b2378ade99cd666b5bffb8b2a7cc8f3d28988685dc300469ea8dd86cb", - "sha256:3f30d3ce413088a98b9db71c60a6ada2001a08945cb42dd65a9a9fe228627658", - "sha256:405784577ba6540fa7d6ff49e37daf104e04f4b4ff2d1ac0469eaa6a20fde084", - "sha256:48ed8129cd9a0d62cf4d1575fcf90fb37e3ff7d5654d3a5814eb3d55f36478c2", - "sha256:4bd3e488b447046e386a30f07af05f9b38d3d368d1f7b4d8f7e10af85393db97", - "sha256:4f0f8271c0a4db459f9dc807acd0eadd4839934a4b9b892f6f160e94da309837", - "sha256:5cceac09f164bcba55c0500a18fe3c47df29b62353198e4f37bbcc5d591172c3", - "sha256:639dc4f381a870c9ec860ce5c45921db50205a37cc3334e756269736ff0aac58", - "sha256:678fcbae74477a17d103b7cae78b74800d795d702083867ce160fc202104d0da", - "sha256:6a4f5ccead6d18ec072ac0b84420e95d27c1cdf5c9f1bc8fbd8daf86bd94f43d", - "sha256:6f58e335a1402fb5a650e271e8c2d03cfa7cea46ae124649346d17bd30d59c90", - "sha256:75c8022dca7935cba14741a42744eee13ba05db00b27a4b940f0d646bd4d56d0", - "sha256:7a7ea483c1a4485c71cb5f38be9db078f8b0e8b4c4dc0210f531cdd2ddac1ef1", - "sha256:7d9ceb2c957320def533671fc9c715a80c47025139c8d1f3797477decbc6edd2", - "sha256:7ebaec1bf683e4bf5e9fbb49b8cc36da482033596a415b3e4ebab5a4c0d7ec5e", - "sha256:85ed077c995e942b6f1b07583e4eb0a8d324d418954fc6af913d36db7c05a5a0", - "sha256:8ae5b97f690badd2ca27cbf668494ee1b6d34cf1c464271ef7bfa9ca6b83ffaf", - "sha256:8b0bb634338334385351a1600a73e558ce619af390c2b38386206ac6a27fecfc", - "sha256:8e216a038d2d52ea13fdd9b9c9c7459fb80d78302b257828285eca1c773b99b3", - "sha256:93ad80d7176aa5788902f207a4e79885f0576134695dfb0fefc15b7a4648d503", - "sha256:95658c342529bba4e1d3d2b1a874db16c7cca435e8827422154c9da76ac4e13a", - "sha256:95fb92dd3649f9cb139e9c56604cc2d7c7bf0fc2e7c8d7fbd58f96e35eddd2a3", - "sha256:97662ce7fb196c785344d00d638fc9ad69e18ee4bfb4000b35a52efe5adcc949", - "sha256:9bb68d3a085c2174c2477eb3ffe84ae9fb4fde8792edb7bcd09a1d8467e30a84", - "sha256:b512aa728bc02354e5ac086ce76c3ce635b62f5fbc32ab7082b5e582d27867bb", - "sha256:c6e26c30455600b95d94b1b836085138e82f177351454ee841c148f93a9bad5a", - "sha256:d2f6c3c4cb1948d912538217838f6e9960bc4a521d7f9b323b3da579cd14532f", - "sha256:dcbab042cc3ef272adc11220517278519adf8f53fd3056d0e68f0a6f891ba94e", - "sha256:e0b281cf5a125c35f7f6722b65d8542d2e57331be573e9e88bc8b0115c4a7a81", - "sha256:e57997ac7fb7ee43140cc03664de5f268813a481dff6245e0075925adc6aa185", - "sha256:fe467eb086d80217b7584e61313ebadc8d187a4d95bb62031b7bab4b205c3ba3" + "sha256:0238f07780782c018e9801d8f5f5aea3a4680a1af132034b444f677718c6fe88", + "sha256:052f7f50e4a38f069478143878371ed17937f268349bcd68f6f7a9de9fcfce21", + "sha256:054bdee08e4f7c15c186f6e7dbc8f0cf974b8dd1832b5f17f988faf8b12815c9", + "sha256:1099f73952e18c718ccaaf7a97ae58c94a91839c3d247c6184326f85a2eda7b4", + "sha256:10d28e5597d4349390c640232c9366ddc15568114f56724fe30a53de9686b6ab", + "sha256:1b7bc59362143dc2d02896dde94004ef54ff1989ceedf4b389ad3b530f312364", + "sha256:1bb67d47f045f56e9a5da4deccf710bdde21212e4b1f4776b7a542449f6a7682", + "sha256:2d5c33d98b2311ddbe06e92b12b14de334dcfbe64ebcbb2c7a34b5c6036db512", + "sha256:2e9d225b178a6cc700c23cf2f5daf85a10f93f1db7c34e9ee4ee0bbc29ad458a", + "sha256:352a496244360deb1c1d108391d76cd6f3dd9f53ccf975a082e74c6761af30c9", + "sha256:3f0246ca7f78fa8e3902ddb985b9f55509d417a862f4634a8fa63a7a496266c8", + "sha256:406f7dc5d9db68cd9ac638d14c74d077085f76b45f704d3ec38d43b842b3cb44", + "sha256:41965586b02715c3d83dd9153001f654e5b621de0c5255f5ef0635485212d0c0", + "sha256:4502620722b453c2c6306fad392c515dcb804dfa9c6d3b90d8926a07a7a01109", + "sha256:4d6e0ba155a1b3159551ac6b4551eb20028617e2e4bb71f2c61efed0756e6825", + "sha256:5141ccc9dbd8cdc59d1e93e318d405477a940dc6ebadcb8d9f8da17d2812d353", + "sha256:53cd2d776700bf0ed0e6fb203d716b041712ea4906479031cc5ac5421ecaa7d2", + "sha256:56bcd9ba0adf16edb4e3e45b8b9346f5b3b2372402e953d54c84b345d0f691e0", + "sha256:76dcb8f5c866f1537ccbaad01ebb3611890d281ef8d25e050d1cc3d90fba6b3d", + "sha256:77e22c33123ce11231ff2773d8905e20b45d77a69459def7481283b72a583955", + "sha256:78f920a75c1dbcb5a48a495f384d73ceb41e437a966c318eb7e56f1c1ad1df3e", + "sha256:7da016a0dab1fcced89dfff8537033c5dc200015e14023368f3f4a69e39b8716", + "sha256:8d80878cb40ebf88a48839ff7206ceb62e4b54327e0c2f9f15ee12edbd8b907e", + "sha256:8fdb4634040d1dbde7e0b373e19668cdb61c0ee8690d3b4064ac748d85365bca", + "sha256:93b1839d54b80a06a51a31b90d024a1770e250d00de57e7ae069bafba932f398", + "sha256:9ddaf99e362ae4169f6a8b3508f3487264e0a1b1e58c0b07b86407bc9ecee831", + "sha256:ad44569b0f508e046ffe85b4a547d5b68d1548fd90767df69449cc28021ee709", + "sha256:ae694efefcb61317c79b2fa1caebc122060992408e389bb00889567e463a47f1", + "sha256:b57cb8a4a8a8ffdaf0395326ef3b9c1aba36e58a421438fc04c002a1f511db63", + "sha256:b73cda1326738eab5d60640ca0b87ac4e4db09a099423c41b59a5681917e8d1d", + "sha256:c30902f9b9da0d74668b6f71d7b57081a4879d9a5ea93d5922dbe15b15b3b24a", + "sha256:c3e45d004531330030f7d07abe4865bc17963b9989bc1941cebbf7224010fb82", + "sha256:c7a5715b1f46e9852442f496c0df2f8c393cc8f293f5396d2c8d95cac852fb51", + "sha256:c92d2b7c1a914ab2f66454961eeaf904f4fe7529b93ff537619d22c18b82d070", + "sha256:cf61238811a75335751b4b17f8b221a35f93f2d57489296742adf98412d2a568", + "sha256:d25f8fdbc6cc6561353c7a384d76295e6a85a4945115b8bc347855db150e8c77", + "sha256:d49b14fcc9b12a52da8667587efa124a18e1a3eb63bbbcabf9882f4008d171d6", + "sha256:ddaf38943dbb32333a182c894b6092a68b56c5e36d0c54ba3761d28119b15447", + "sha256:ddc328c2a2daf2cf4bdc7bbc8a458dc4c840637223d4b8e01bce2168cc79fd23", + "sha256:e350a887adb38ac65c93c2f395b60cf482baca61fd396ed8d6fd313dbcce6fac", + "sha256:efc9d039b6b8a36b182bc60774bb5d456b8ff9ec44cf97719f2f38bb1dcdd546", + "sha256:f0481154c91725f7e7b729a535190388be6c7cbae3bbf0e793343ca386282312", + "sha256:f4f2fea370361a90cb9330610a95303587eda9d1e69930dbbee9978eac1d5946" ], - "version": "==0.6.1" + "version": "==0.6.2" }, "httpx": { "hashes": [ @@ -1033,11 +1054,11 @@ }, "idna": { "hashes": [ - "sha256:050b4e5baadcd44d760cedbd2b8e639f2ff89bbc7a5730fcc662954303377aac", - "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603" + "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", + "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3" ], "markers": "python_version >= '3.6'", - "version": "==3.8" + "version": "==3.10" }, "importlib-metadata": { "hashes": [ @@ -1049,10 +1070,11 @@ }, "isodate": { "hashes": [ - "sha256:0751eece944162659049d35f4f549ed815792b38793f07cf73381c1c87cbed96", - "sha256:48c5881de7e8b0a0d648cb024c8062dc84e7b840ed81e864c7614fd3c127bde9" + "sha256:28009937d8031054830160fce6d409ed342816b543597cece116d966c6d99e15", + "sha256:4cd1aa0f43ca76f4a6c6c0292a85f40b35ec2e43e315b59f06e6d32171a953e6" ], - "version": "==0.6.1" + "markers": "python_version >= '3.7'", + "version": "==0.7.2" }, "jinja2": { "hashes": [ @@ -1089,69 +1111,70 @@ }, "markupsafe": { "hashes": [ - "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf", - "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff", - "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f", - "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3", - "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532", - "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f", - "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617", - "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df", - "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4", - "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906", - "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f", - "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4", - "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8", - "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371", - "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2", - "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465", - "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52", - "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6", - "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169", - "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad", - "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2", - "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0", - "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029", - "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f", - "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a", - "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced", - "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5", - "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c", - "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf", - "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9", - "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb", - "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad", - "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3", - "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1", - "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46", - "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc", - "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a", - "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee", - "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900", - "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5", - "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea", - "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f", - "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5", - "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e", - "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a", - "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f", - "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50", - "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a", - "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b", - "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4", - "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff", - "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2", - "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46", - "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b", - "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf", - "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5", - "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5", - "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab", - "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd", - "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68" + "sha256:0778de17cff1acaeccc3ff30cd99a3fd5c50fc58ad3d6c0e0c4c58092b859396", + "sha256:0f84af7e813784feb4d5e4ff7db633aba6c8ca64a833f61d8e4eade234ef0c38", + "sha256:17b2aea42a7280db02ac644db1d634ad47dcc96faf38ab304fe26ba2680d359a", + "sha256:242d6860f1fd9191aef5fae22b51c5c19767f93fb9ead4d21924e0bcb17619d8", + "sha256:244dbe463d5fb6d7ce161301a03a6fe744dac9072328ba9fc82289238582697b", + "sha256:26627785a54a947f6d7336ce5963569b5d75614619e75193bdb4e06e21d447ad", + "sha256:2a4b34a8d14649315c4bc26bbfa352663eb51d146e35eef231dd739d54a5430a", + "sha256:2ae99f31f47d849758a687102afdd05bd3d3ff7dbab0a8f1587981b58a76152a", + "sha256:312387403cd40699ab91d50735ea7a507b788091c416dd007eac54434aee51da", + "sha256:3341c043c37d78cc5ae6e3e305e988532b072329639007fd408a476642a89fd6", + "sha256:33d1c36b90e570ba7785dacd1faaf091203d9942bc036118fab8110a401eb1a8", + "sha256:3e683ee4f5d0fa2dde4db77ed8dd8a876686e3fc417655c2ece9a90576905344", + "sha256:3ffb4a8e7d46ed96ae48805746755fadd0909fea2306f93d5d8233ba23dda12a", + "sha256:40621d60d0e58aa573b68ac5e2d6b20d44392878e0bfc159012a5787c4e35bc8", + "sha256:40f1e10d51c92859765522cbd79c5c8989f40f0419614bcdc5015e7b6bf97fc5", + "sha256:45d42d132cff577c92bfba536aefcfea7e26efb975bd455db4e6602f5c9f45e7", + "sha256:48488d999ed50ba8d38c581d67e496f955821dc183883550a6fbc7f1aefdc170", + "sha256:4935dd7883f1d50e2ffecca0aa33dc1946a94c8f3fdafb8df5c330e48f71b132", + "sha256:4c2d64fdba74ad16138300815cfdc6ab2f4647e23ced81f59e940d7d4a1469d9", + "sha256:4c8817557d0de9349109acb38b9dd570b03cc5014e8aabf1cbddc6e81005becd", + "sha256:4ffaaac913c3f7345579db4f33b0020db693f302ca5137f106060316761beea9", + "sha256:5a4cb365cb49b750bdb60b846b0c0bc49ed62e59a76635095a179d440540c346", + "sha256:62fada2c942702ef8952754abfc1a9f7658a4d5460fabe95ac7ec2cbe0d02abc", + "sha256:67c519635a4f64e495c50e3107d9b4075aec33634272b5db1cde839e07367589", + "sha256:6a54c43d3ec4cf2a39f4387ad044221c66a376e58c0d0e971d47c475ba79c6b5", + "sha256:7044312a928a66a4c2a22644147bc61a199c1709712069a344a3fb5cfcf16915", + "sha256:730d86af59e0e43ce277bb83970530dd223bf7f2a838e086b50affa6ec5f9295", + "sha256:800100d45176652ded796134277ecb13640c1a537cad3b8b53da45aa96330453", + "sha256:80fcbf3add8790caddfab6764bde258b5d09aefbe9169c183f88a7410f0f6dea", + "sha256:82b5dba6eb1bcc29cc305a18a3c5365d2af06ee71b123216416f7e20d2a84e5b", + "sha256:852dc840f6d7c985603e60b5deaae1d89c56cb038b577f6b5b8c808c97580f1d", + "sha256:8ad4ad1429cd4f315f32ef263c1342166695fad76c100c5d979c45d5570ed58b", + "sha256:8ae369e84466aa70f3154ee23c1451fda10a8ee1b63923ce76667e3077f2b0c4", + "sha256:93e8248d650e7e9d49e8251f883eed60ecbc0e8ffd6349e18550925e31bd029b", + "sha256:973a371a55ce9ed333a3a0f8e0bcfae9e0d637711534bcb11e130af2ab9334e7", + "sha256:9ba25a71ebf05b9bb0e2ae99f8bc08a07ee8e98c612175087112656ca0f5c8bf", + "sha256:a10860e00ded1dd0a65b83e717af28845bb7bd16d8ace40fe5531491de76b79f", + "sha256:a4792d3b3a6dfafefdf8e937f14906a51bd27025a36f4b188728a73382231d91", + "sha256:a7420ceda262dbb4b8d839a4ec63d61c261e4e77677ed7c66c99f4e7cb5030dd", + "sha256:ad91738f14eb8da0ff82f2acd0098b6257621410dcbd4df20aaa5b4233d75a50", + "sha256:b6a387d61fe41cdf7ea95b38e9af11cfb1a63499af2759444b99185c4ab33f5b", + "sha256:b954093679d5750495725ea6f88409946d69cfb25ea7b4c846eef5044194f583", + "sha256:bbde71a705f8e9e4c3e9e33db69341d040c827c7afa6789b14c6e16776074f5a", + "sha256:beeebf760a9c1f4c07ef6a53465e8cfa776ea6a2021eda0d0417ec41043fe984", + "sha256:c91b394f7601438ff79a4b93d16be92f216adb57d813a78be4446fe0f6bc2d8c", + "sha256:c97ff7fedf56d86bae92fa0a646ce1a0ec7509a7578e1ed238731ba13aabcd1c", + "sha256:cb53e2a99df28eee3b5f4fea166020d3ef9116fdc5764bc5117486e6d1211b25", + "sha256:cbf445eb5628981a80f54087f9acdbf84f9b7d862756110d172993b9a5ae81aa", + "sha256:d06b24c686a34c86c8c1fba923181eae6b10565e4d80bdd7bc1c8e2f11247aa4", + "sha256:d98e66a24497637dd31ccab090b34392dddb1f2f811c4b4cd80c230205c074a3", + "sha256:db15ce28e1e127a0013dfb8ac243a8e392db8c61eae113337536edb28bdc1f97", + "sha256:db842712984e91707437461930e6011e60b39136c7331e971952bb30465bc1a1", + "sha256:e24bfe89c6ac4c31792793ad9f861b8f6dc4546ac6dc8f1c9083c7c4f2b335cd", + "sha256:e81c52638315ff4ac1b533d427f50bc0afc746deb949210bc85f05d4f15fd772", + "sha256:e9393357f19954248b00bed7c56f29a25c930593a77630c719653d51e7669c2a", + "sha256:ee3941769bd2522fe39222206f6dd97ae83c442a94c90f2b7a25d847d40f4729", + "sha256:f31ae06f1328595d762c9a2bf29dafd8621c7d3adc130cbb46278079758779ca", + "sha256:f94190df587738280d544971500b9cafc9b950d32efcb1fba9ac10d84e6aa4e6", + "sha256:fa7d686ed9883f3d664d39d5a8e74d3c5f63e603c2e3ff0abcba23eac6542635", + "sha256:fb532dd9900381d2e8f48172ddc5a59db4c445a11b9fab40b3b786da40d3b56b", + "sha256:fe32482b37b4b00c7a52a07211b479653b7fe4f22b2e481b9a9b099d8a430f2f" ], - "markers": "python_version >= '3.7'", - "version": "==2.1.5" + "markers": "python_version >= '3.9'", + "version": "==3.0.1" }, "mdurl": { "hashes": [ @@ -1570,15 +1593,109 @@ "markers": "python_version >= '3.7'", "version": "==3.3.0" }, - "passlib": { - "extras": [ - "bcrypt" - ], - "hashes": [ - "sha256:aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1", - "sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04" + "propcache": { + "hashes": [ + "sha256:00181262b17e517df2cd85656fcd6b4e70946fe62cd625b9d74ac9977b64d8d9", + "sha256:0e53cb83fdd61cbd67202735e6a6687a7b491c8742dfc39c9e01e80354956763", + "sha256:1235c01ddaa80da8235741e80815ce381c5267f96cc49b1477fdcf8c047ef325", + "sha256:140fbf08ab3588b3468932974a9331aff43c0ab8a2ec2c608b6d7d1756dbb6cb", + "sha256:191db28dc6dcd29d1a3e063c3be0b40688ed76434622c53a284e5427565bbd9b", + "sha256:1e41d67757ff4fbc8ef2af99b338bfb955010444b92929e9e55a6d4dcc3c4f09", + "sha256:1ec43d76b9677637a89d6ab86e1fef70d739217fefa208c65352ecf0282be957", + "sha256:20a617c776f520c3875cf4511e0d1db847a076d720714ae35ffe0df3e440be68", + "sha256:218db2a3c297a3768c11a34812e63b3ac1c3234c3a086def9c0fee50d35add1f", + "sha256:22aa8f2272d81d9317ff5756bb108021a056805ce63dd3630e27d042c8092798", + "sha256:25a1f88b471b3bc911d18b935ecb7115dff3a192b6fef46f0bfaf71ff4f12418", + "sha256:25c8d773a62ce0451b020c7b29a35cfbc05de8b291163a7a0f3b7904f27253e6", + "sha256:2a60ad3e2553a74168d275a0ef35e8c0a965448ffbc3b300ab3a5bb9956c2162", + "sha256:2a66df3d4992bc1d725b9aa803e8c5a66c010c65c741ad901e260ece77f58d2f", + "sha256:2ccc28197af5313706511fab3a8b66dcd6da067a1331372c82ea1cb74285e036", + "sha256:2e900bad2a8456d00a113cad8c13343f3b1f327534e3589acc2219729237a2e8", + "sha256:2ee7606193fb267be4b2e3b32714f2d58cad27217638db98a60f9efb5efeccc2", + "sha256:33ac8f098df0585c0b53009f039dfd913b38c1d2edafed0cedcc0c32a05aa110", + "sha256:3444cdba6628accf384e349014084b1cacd866fbb88433cd9d279d90a54e0b23", + "sha256:363ea8cd3c5cb6679f1c2f5f1f9669587361c062e4899fce56758efa928728f8", + "sha256:375a12d7556d462dc64d70475a9ee5982465fbb3d2b364f16b86ba9135793638", + "sha256:388f3217649d6d59292b722d940d4d2e1e6a7003259eb835724092a1cca0203a", + "sha256:3947483a381259c06921612550867b37d22e1df6d6d7e8361264b6d037595f44", + "sha256:39e104da444a34830751715f45ef9fc537475ba21b7f1f5b0f4d71a3b60d7fe2", + "sha256:3c997f8c44ec9b9b0bcbf2d422cc00a1d9b9c681f56efa6ca149a941e5560da2", + "sha256:3dfafb44f7bb35c0c06eda6b2ab4bfd58f02729e7c4045e179f9a861b07c9850", + "sha256:3ebbcf2a07621f29638799828b8d8668c421bfb94c6cb04269130d8de4fb7136", + "sha256:3f88a4095e913f98988f5b338c1d4d5d07dbb0b6bad19892fd447484e483ba6b", + "sha256:439e76255daa0f8151d3cb325f6dd4a3e93043e6403e6491813bcaaaa8733887", + "sha256:4569158070180c3855e9c0791c56be3ceeb192defa2cdf6a3f39e54319e56b89", + "sha256:466c219deee4536fbc83c08d09115249db301550625c7fef1c5563a584c9bc87", + "sha256:4a9d9b4d0a9b38d1c391bb4ad24aa65f306c6f01b512e10a8a34a2dc5675d348", + "sha256:4c7dde9e533c0a49d802b4f3f218fa9ad0a1ce21f2c2eb80d5216565202acab4", + "sha256:53d1bd3f979ed529f0805dd35ddaca330f80a9a6d90bc0121d2ff398f8ed8861", + "sha256:55346705687dbd7ef0d77883ab4f6fabc48232f587925bdaf95219bae072491e", + "sha256:56295eb1e5f3aecd516d91b00cfd8bf3a13991de5a479df9e27dd569ea23959c", + "sha256:56bb5c98f058a41bb58eead194b4db8c05b088c93d94d5161728515bd52b052b", + "sha256:5a5b3bb545ead161be780ee85a2b54fdf7092815995661947812dde94a40f6fb", + "sha256:5f2564ec89058ee7c7989a7b719115bdfe2a2fb8e7a4543b8d1c0cc4cf6478c1", + "sha256:608cce1da6f2672a56b24a015b42db4ac612ee709f3d29f27a00c943d9e851de", + "sha256:63f13bf09cc3336eb04a837490b8f332e0db41da66995c9fd1ba04552e516354", + "sha256:662dd62358bdeaca0aee5761de8727cfd6861432e3bb828dc2a693aa0471a563", + "sha256:676135dcf3262c9c5081cc8f19ad55c8a64e3f7282a21266d05544450bffc3a5", + "sha256:67aeb72e0f482709991aa91345a831d0b707d16b0257e8ef88a2ad246a7280bf", + "sha256:67b69535c870670c9f9b14a75d28baa32221d06f6b6fa6f77a0a13c5a7b0a5b9", + "sha256:682a7c79a2fbf40f5dbb1eb6bfe2cd865376deeac65acf9beb607505dced9e12", + "sha256:6994984550eaf25dd7fc7bd1b700ff45c894149341725bb4edc67f0ffa94efa4", + "sha256:69d3a98eebae99a420d4b28756c8ce6ea5a29291baf2dc9ff9414b42676f61d5", + "sha256:6e2e54267980349b723cff366d1e29b138b9a60fa376664a157a342689553f71", + "sha256:73e4b40ea0eda421b115248d7e79b59214411109a5bc47d0d48e4c73e3b8fcf9", + "sha256:74acd6e291f885678631b7ebc85d2d4aec458dd849b8c841b57ef04047833bed", + "sha256:7665f04d0c7f26ff8bb534e1c65068409bf4687aa2534faf7104d7182debb336", + "sha256:7735e82e3498c27bcb2d17cb65d62c14f1100b71723b68362872bca7d0913d90", + "sha256:77a86c261679ea5f3896ec060be9dc8e365788248cc1e049632a1be682442063", + "sha256:7cf18abf9764746b9c8704774d8b06714bcb0a63641518a3a89c7f85cc02c2ad", + "sha256:83928404adf8fb3d26793665633ea79b7361efa0287dfbd372a7e74311d51ee6", + "sha256:8e40876731f99b6f3c897b66b803c9e1c07a989b366c6b5b475fafd1f7ba3fb8", + "sha256:8f188cfcc64fb1266f4684206c9de0e80f54622c3f22a910cbd200478aeae61e", + "sha256:91997d9cb4a325b60d4e3f20967f8eb08dfcb32b22554d5ef78e6fd1dda743a2", + "sha256:91ee8fc02ca52e24bcb77b234f22afc03288e1dafbb1f88fe24db308910c4ac7", + "sha256:92fe151145a990c22cbccf9ae15cae8ae9eddabfc949a219c9f667877e40853d", + "sha256:945db8ee295d3af9dbdbb698cce9bbc5c59b5c3fe328bbc4387f59a8a35f998d", + "sha256:9517d5e9e0731957468c29dbfd0f976736a0e55afaea843726e887f36fe017df", + "sha256:952e0d9d07609d9c5be361f33b0d6d650cd2bae393aabb11d9b719364521984b", + "sha256:97a58a28bcf63284e8b4d7b460cbee1edaab24634e82059c7b8c09e65284f178", + "sha256:97e48e8875e6c13909c800fa344cd54cc4b2b0db1d5f911f840458a500fde2c2", + "sha256:9e0f07b42d2a50c7dd2d8675d50f7343d998c64008f1da5fef888396b7f84630", + "sha256:a3dc1a4b165283bd865e8f8cb5f0c64c05001e0718ed06250d8cac9bec115b48", + "sha256:a3ebe9a75be7ab0b7da2464a77bb27febcb4fab46a34f9288f39d74833db7f61", + "sha256:a64e32f8bd94c105cc27f42d3b658902b5bcc947ece3c8fe7bc1b05982f60e89", + "sha256:a6ed8db0a556343d566a5c124ee483ae113acc9a557a807d439bcecc44e7dfbb", + "sha256:ad9c9b99b05f163109466638bd30ada1722abb01bbb85c739c50b6dc11f92dc3", + "sha256:b33d7a286c0dc1a15f5fc864cc48ae92a846df287ceac2dd499926c3801054a6", + "sha256:bc092ba439d91df90aea38168e11f75c655880c12782facf5cf9c00f3d42b562", + "sha256:c436130cc779806bdf5d5fae0d848713105472b8566b75ff70048c47d3961c5b", + "sha256:c5869b8fd70b81835a6f187c5fdbe67917a04d7e52b6e7cc4e5fe39d55c39d58", + "sha256:c5ecca8f9bab618340c8e848d340baf68bcd8ad90a8ecd7a4524a81c1764b3db", + "sha256:cfac69017ef97db2438efb854edf24f5a29fd09a536ff3a992b75990720cdc99", + "sha256:d2f0d0f976985f85dfb5f3d685697ef769faa6b71993b46b295cdbbd6be8cc37", + "sha256:d5bed7f9805cc29c780f3aee05de3262ee7ce1f47083cfe9f77471e9d6777e83", + "sha256:d6a21ef516d36909931a2967621eecb256018aeb11fc48656e3257e73e2e247a", + "sha256:d9b6ddac6408194e934002a69bcaadbc88c10b5f38fb9307779d1c629181815d", + "sha256:db47514ffdbd91ccdc7e6f8407aac4ee94cc871b15b577c1c324236b013ddd04", + "sha256:df81779732feb9d01e5d513fad0122efb3d53bbc75f61b2a4f29a020bc985e70", + "sha256:e4a91d44379f45f5e540971d41e4626dacd7f01004826a18cb048e7da7e96544", + "sha256:e63e3e1e0271f374ed489ff5ee73d4b6e7c60710e1f76af5f0e1a6117cd26394", + "sha256:e70fac33e8b4ac63dfc4c956fd7d85a0b1139adcfc0d964ce288b7c527537fea", + "sha256:ecddc221a077a8132cf7c747d5352a15ed763b674c0448d811f408bf803d9ad7", + "sha256:f45eec587dafd4b2d41ac189c2156461ebd0c1082d2fe7013571598abb8505d1", + "sha256:f52a68c21363c45297aca15561812d542f8fc683c85201df0bebe209e349f793", + "sha256:f571aea50ba5623c308aa146eb650eebf7dbe0fd8c5d946e28343cb3b5aad577", + "sha256:f60f0ac7005b9f5a6091009b09a419ace1610e163fa5deaba5ce3484341840e7", + "sha256:f6475a1b2ecb310c98c28d271a30df74f9dd436ee46d09236a6b750a7599ce57", + "sha256:f6d5749fdd33d90e34c2efb174c7e236829147a2713334d708746e94c4bde40d", + "sha256:f902804113e032e2cdf8c71015651c97af6418363bea8d78dc0911d56c335032", + "sha256:fa1076244f54bb76e65e22cb6910365779d5c3d71d1f18b275f1dfc7b0d71b4d", + "sha256:fc2db02409338bf36590aa985a461b2c96fce91f8e7e0f14c50c5fcc4f229016", + "sha256:ffcad6c564fe6b9b8916c1aefbb37a362deebf9394bd2974e9d84232e3e08504" ], - "version": "==1.7.4" + "markers": "python_version >= '3.8'", + "version": "==0.2.0" }, "proto-plus": { "hashes": [ @@ -1590,20 +1707,20 @@ }, "protobuf": { "hashes": [ - "sha256:051e97ce9fa6067a4546e75cb14f90cf0232dcb3e3d508c448b8d0e4265b61c1", - "sha256:0dc4a62cc4052a036ee2204d26fe4d835c62827c855c8a03f29fe6da146b380d", - "sha256:3319e073562e2515c6ddc643eb92ce20809f5d8f10fead3332f71c63be6a7040", - "sha256:4c8a70fdcb995dcf6c8966cfa3a29101916f7225e9afe3ced4395359955d3835", - "sha256:7e372cbbda66a63ebca18f8ffaa6948455dfecc4e9c1029312f6c2edcd86c4e1", - "sha256:90bf6fd378494eb698805bbbe7afe6c5d12c8e17fca817a646cd6a1818c696ca", - "sha256:ac79a48d6b99dfed2729ccccee547b34a1d3d63289c71cef056653a846a2240f", - "sha256:ba3d8504116a921af46499471c63a85260c1a5fc23333154a427a310e015d26d", - "sha256:bfbebc1c8e4793cfd58589acfb8a1026be0003e852b9da7db5a4285bde996978", - "sha256:db9fd45183e1a67722cafa5c1da3e85c6492a5383f127c86c4c4aa4845867dc4", - "sha256:eecd41bfc0e4b1bd3fa7909ed93dd14dd5567b98c941d6c1ad08fdcab3d6884b" + "sha256:0aebecb809cae990f8129ada5ca273d9d670b76d9bfc9b1809f0a9c02b7dbf41", + "sha256:4be0571adcbe712b282a330c6e89eae24281344429ae95c6d85e79e84780f5ea", + "sha256:5e61fd921603f58d2f5acb2806a929b4675f8874ff5f330b7d6f7e2e784bbcd8", + "sha256:7a183f592dc80aa7c8da7ad9e55091c4ffc9497b3054452d629bb85fa27c2a45", + "sha256:7f8249476b4a9473645db7f8ab42b02fe1488cbe5fb72fddd445e0665afd8584", + "sha256:919ad92d9b0310070f8356c24b855c98df2b8bd207ebc1c0c6fcc9ab1e007f3d", + "sha256:98d8d8aa50de6a2747efd9cceba361c9034050ecce3e09136f90de37ddba66e1", + "sha256:abe32aad8561aa7cc94fc7ba4fdef646e576983edb94a73381b03c53728a626f", + "sha256:b0234dd5a03049e4ddd94b93400b67803c823cfc405689688f59b34e0742381a", + "sha256:b2fde3d805354df675ea4c7c6338c1aecd254dfc9925e88c6d31a2bcb97eb173", + "sha256:fe14e16c22be926d3abfcb500e60cab068baf10b542b8c858fa27e098123e331" ], "markers": "python_version >= '3.8'", - "version": "==4.25.4" + "version": "==4.25.5" }, "pyasn1": { "hashes": [ @@ -1631,9 +1748,11 @@ }, "pycron": { "hashes": [ - "sha256:b916044e3e8253d5409c68df3ac64a3472c4e608dab92f40e8f595e5d3acb3de" + "sha256:6de8a555f721c74aa0bb681071a97da3d784ebf8ccea1d2bb9a3e66460b87da2", + "sha256:bf676a66b8dcf69edf1d3fd1d8f3f2b9468a2a007012c89a14e9d087d3f76198" ], - "version": "==3.0.0" + "markers": "python_version < '3.13' and python_version >= '3.9'", + "version": "==3.1.1" }, "pydantic": { "extras": [ @@ -1703,65 +1822,75 @@ "sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850", "sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c" ], + "index": "pypi", "markers": "python_version >= '3.8'", "version": "==2.9.0" }, "pymongo": { "hashes": [ - "sha256:0fc18b3a093f3db008c5fea0e980dbd3b743449eee29b5718bc2dc15ab5088bb", - "sha256:16e5019f75f6827bb5354b6fef8dfc9d6c7446894a27346e03134d290eb9e758", - "sha256:180d5eb1dc28b62853e2f88017775c4500b07548ed28c0bd9c005c3d7bc52526", - "sha256:18c9d8f975dd7194c37193583fd7d1eb9aea0c21ee58955ecf35362239ff31ac", - "sha256:236bbd7d0aef62e64caf4b24ca200f8c8670d1a6f5ea828c39eccdae423bc2b2", - "sha256:284d0717d1a7707744018b0b6ee7801b1b1ff044c42f7be7a01bb013de639470", - "sha256:2ecd71b9226bd1d49416dc9f999772038e56f415a713be51bf18d8676a0841c8", - "sha256:31e4d21201bdf15064cf47ce7b74722d3e1aea2597c6785882244a3bb58c7eab", - "sha256:3b5802151fc2b51cd45492c80ed22b441d20090fb76d1fd53cd7760b340ff554", - "sha256:3c68fe128a171493018ca5c8020fc08675be130d012b7ab3efe9e22698c612a1", - "sha256:3ed1c316718a2836f7efc3d75b4b0ffdd47894090bc697de8385acd13c513a70", - "sha256:408b2f8fdbeca3c19e4156f28fff1ab11c3efb0407b60687162d49f68075e63c", - "sha256:417369ce39af2b7c2a9c7152c1ed2393edfd1cbaf2a356ba31eb8bcbd5c98dd7", - "sha256:454f2295875744dc70f1881e4b2eb99cdad008a33574bc8aaf120530f66c0cde", - "sha256:47ec8c3f0a7b2212dbc9be08d3bf17bc89abd211901093e3ef3f2adea7de7a69", - "sha256:4bf58e6825b93da63e499d1a58de7de563c31e575908d4e24876234ccb910eba", - "sha256:519d1bab2b5e5218c64340b57d555d89c3f6c9d717cecbf826fb9d42415e7750", - "sha256:52b4108ac9469febba18cea50db972605cc43978bedaa9fea413378877560ef8", - "sha256:658d0170f27984e0d89c09fe5c42296613b711a3ffd847eb373b0dbb5b648d5f", - "sha256:6b50040d9767197b77ed420ada29b3bf18a638f9552d80f2da817b7c4a4c9c68", - "sha256:7148419eedfea9ecb940961cfe465efaba90595568a1fb97585fb535ea63fe2b", - "sha256:77f53429515d2b3e86dcc83dadecf7ff881e538c168d575f3688698a8707b80a", - "sha256:87075a1feb1e602e539bdb1ef8f4324a3427eb0d64208c3182e677d2c0718b6f", - "sha256:8b18c8324809539c79bd6544d00e0607e98ff833ca21953df001510ca25915d1", - "sha256:9097c331577cecf8034422956daaba7ec74c26f7b255d718c584faddd7fa2e3c", - "sha256:920d4f8f157a71b3cb3f39bc09ce070693d6e9648fb0e30d00e2657d1dca4e49", - "sha256:9365166aa801c63dff1a3cb96e650be270da06e3464ab106727223123405510f", - "sha256:940d456774b17814bac5ea7fc28188c7a1338d4a233efbb6ba01de957bded2e8", - "sha256:aec2b9088cdbceb87e6ca9c639d0ff9b9d083594dda5ca5d3c4f6774f4c81b33", - "sha256:af3e98dd9702b73e4e6fd780f6925352237f5dce8d99405ff1543f3771201704", - "sha256:b6564780cafd6abeea49759fe661792bd5a67e4f51bca62b88faab497ab5fe89", - "sha256:b747c0e257b9d3e6495a018309b9e0c93b7f0d65271d1d62e572747f4ffafc88", - "sha256:bf821bd3befb993a6db17229a2c60c1550e957de02a6ff4dd0af9476637b2e4d", - "sha256:c6b804bb4f2d9dc389cc9e827d579fa327272cdb0629a99bfe5b83cb3e269ebf", - "sha256:cc8b8582f4209c2459b04b049ac03c72c618e011d3caa5391ff86d1bda0cc486", - "sha256:cd39455b7ee70aabee46f7399b32ab38b86b236c069ae559e22be6b46b2bbfc4", - "sha256:d0cf61450feadca81deb1a1489cb1a3ae1e4266efd51adafecec0e503a8dcd84", - "sha256:d18d86bc9e103f4d3d4f18b85a0471c0e13ce5b79194e4a0389a224bb70edd53", - "sha256:d5428dbcd43d02f6306e1c3c95f692f68b284e6ee5390292242f509004c9e3a8", - "sha256:de3a860f037bb51f968de320baef85090ff0bbb42ec4f28ec6a5ddf88be61871", - "sha256:e0061af6e8c5e68b13f1ec9ad5251247726653c5af3c0bbdfbca6cf931e99216", - "sha256:e5df28f74002e37bcbdfdc5109799f670e4dfef0fb527c391ff84f078050e7b5", - "sha256:e6a720a3d22b54183352dc65f08cd1547204d263e0651b213a0a2e577e838526", - "sha256:e8400587d594761e5136a3423111f499574be5fd53cf0aefa0d0f05b180710b0", - "sha256:e84bc7707492f06fbc37a9f215374d2977d21b72e10a67f1b31893ec5a140ad8", - "sha256:ef7225755ed27bfdb18730c68f6cb023d06c28f2b734597480fb4c0e500feb6f", - "sha256:f2b7bec27e047e84947fbd41c782f07c54c30c76d14f3b8bf0c89f7413fac67a", - "sha256:f2fbdb87fe5075c8beb17a5c16348a1ea3c8b282a5cb72d173330be2fecf22f5", - "sha256:f5bf0eb8b6ef40fa22479f09375468c33bebb7fe49d14d9c96c8fd50355188b0", - "sha256:fdc20cd1e1141b04696ffcdb7c71e8a4a665db31fe72e51ec706b3bdd2d09f36" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==4.8.0" + "sha256:0783e0c8e95397c84e9cf8ab092ab1e5dd7c769aec0ef3a5838ae7173b98dea0", + "sha256:0f56707497323150bd2ed5d63067f4ffce940d0549d4ea2dfae180deec7f9363", + "sha256:11280809e5dacaef4971113f0b4ff4696ee94cfdb720019ff4fa4f9635138252", + "sha256:15a624d752dd3c89d10deb0ef6431559b6d074703cab90a70bb849ece02adc6b", + "sha256:15b1492cc5c7cd260229590be7218261e81684b8da6d6de2660cf743445500ce", + "sha256:1a970fd3117ab40a4001c3dad333bbf3c43687d90f35287a6237149b5ccae61d", + "sha256:1ec3fa88b541e0481aff3c35194c9fac96e4d57ec5d1c122376000eb28c01431", + "sha256:1ecc2455e3974a6c429687b395a0bc59636f2d6aedf5785098cf4e1f180f1c71", + "sha256:23e1d62df5592518204943b507be7b457fb8a4ad95a349440406fd42db5d0923", + "sha256:29e1c323c28a4584b7095378ff046815e39ff82cdb8dc4cc6dfe3acf6f9ad1f8", + "sha256:2e3a593333e20c87415420a4fb76c00b7aae49b6361d2e2205b6fece0563bf40", + "sha256:345f8d340802ebce509f49d5833cc913da40c82f2e0daf9f60149cacc9ca680f", + "sha256:3a70d5efdc0387ac8cd50f9a5f379648ecfc322d14ec9e1ba8ec957e5d08c372", + "sha256:409ab7d6c4223e5c85881697f365239dd3ed1b58f28e4124b846d9d488c86880", + "sha256:442ca247f53ad24870a01e80a71cd81b3f2318655fd9d66748ee2bd1b1569d9e", + "sha256:45ee87a4e12337353242bc758accc7fb47a2f2d9ecc0382a61e64c8f01e86708", + "sha256:4924355245a9c79f77b5cda2db36e0f75ece5faf9f84d16014c0a297f6d66786", + "sha256:544890085d9641f271d4f7a47684450ed4a7344d6b72d5968bfae32203b1bb7c", + "sha256:57ee6becae534e6d47848c97f6a6dff69e3cce7c70648d6049bd586764febe59", + "sha256:594dd721b81f301f33e843453638e02d92f63c198358e5a0fa8b8d0b1218dabc", + "sha256:5ded27a4a5374dae03a92e084a60cdbcecd595306555bda553b833baf3fc4868", + "sha256:6131bc6568b26e7495a9f3ef2b1700566b76bbecd919f4472bfe90038a61f425", + "sha256:6f437a612f4d4f7aca1812311b1e84477145e950fdafe3285b687ab8c52541f3", + "sha256:6fb6a72e88df46d1c1040fd32cd2d2c5e58722e5d3e31060a0393f04ad3283de", + "sha256:70645abc714f06b4ad6b72d5bf73792eaad14e3a2cfe29c62a9c81ada69d9e4b", + "sha256:72e2ace7456167c71cfeca7dcb47bd5dceda7db2231265b80fc625c5e8073186", + "sha256:778ac646ce6ac1e469664062dfe9ae1f5c9961f7790682809f5ec3b8fda29d65", + "sha256:7bd26b2aec8ceeb95a5d948d5cc0f62b0eb6d66f3f4230705c1e3d3d2c04ec76", + "sha256:7c4d0e7cd08ef9f8fbf2d15ba281ed55604368a32752e476250724c3ce36c72e", + "sha256:88dc4aa45f8744ccfb45164aedb9a4179c93567bbd98a33109d7dc400b00eb08", + "sha256:8ad05eb9c97e4f589ed9e74a00fcaac0d443ccd14f38d1258eb4c39a35dd722b", + "sha256:90bc6912948dfc8c363f4ead54d54a02a15a7fee6cfafb36dc450fc8962d2cb7", + "sha256:9235fa319993405ae5505bf1333366388add2e06848db7b3deee8f990b69808e", + "sha256:93a0833c10a967effcd823b4e7445ec491f0bf6da5de0ca33629c0528f42b748", + "sha256:95207503c41b97e7ecc7e596d84a61f441b4935f11aa8332828a754e7ada8c82", + "sha256:9df4ab5594fdd208dcba81be815fa8a8a5d8dedaf3b346cbf8b61c7296246a7a", + "sha256:a920fee41f7d0259f5f72c1f1eb331bc26ffbdc952846f9bd8c3b119013bb52c", + "sha256:a9de02be53b6bb98efe0b9eda84ffa1ec027fcb23a2de62c4f941d9a2f2f3330", + "sha256:ae2fd94c9fe048c94838badcc6e992d033cb9473eb31e5710b3707cba5e8aee2", + "sha256:b3337804ea0394a06e916add4e5fac1c89902f1b6f33936074a12505cab4ff05", + "sha256:ba164e73fdade9b4614a2497321c5b7512ddf749ed508950bdecc28d8d76a2d9", + "sha256:bb99f003c720c6d83be02c8f1a7787c22384a8ca9a4181e406174db47a048619", + "sha256:ca6f700cff6833de4872a4e738f43123db34400173558b558ae079b5535857a4", + "sha256:cec237c305fcbeef75c0bcbe9d223d1e22a6e3ba1b53b2f0b79d3d29c742b45b", + "sha256:dabe8bf1ad644e6b93f3acf90ff18536d94538ca4d27e583c6db49889e98e48f", + "sha256:dac78a650dc0637d610905fd06b5fa6419ae9028cf4d04d6a2657bc18a66bbce", + "sha256:dcc07b1277e8b4bf4d7382ca133850e323b7ab048b8353af496d050671c7ac52", + "sha256:e0a15665b2d6cf364f4cd114d62452ce01d71abfbd9c564ba8c74dcd7bbd6822", + "sha256:e0e961923a7b8a1c801c43552dcb8153e45afa41749d9efbd3a6d33f45489f7a", + "sha256:e4a65567bd17d19f03157c7ec992c6530eafd8191a4e5ede25566792c4fe3fa2", + "sha256:e5d55f2a82e5eb23795f724991cac2bffbb1c0f219c0ba3bf73a835f97f1bb2e", + "sha256:e699aa68c4a7dea2ab5a27067f7d3e08555f8d2c0dc6a0c8c60cfd9ff2e6a4b1", + "sha256:e974ab16a60be71a8dfad4e5afccf8dd05d41c758060f5d5bda9a758605d9a5d", + "sha256:ee4c86d8e6872a61f7888fc96577b0ea165eb3bdb0d841962b444fa36001e2bb", + "sha256:f1945d48fb9b8a87d515da07f37e5b2c35b364a435f534c122e92747881f4a7c", + "sha256:f2bc1ee4b1ca2c4e7e6b7a5e892126335ec8d9215bcd3ac2fe075870fefc3358", + "sha256:fb104c3c2a78d9d85571c8ac90ec4f95bca9b297c6eee5ada71fabf1129e1674", + "sha256:fbedc4617faa0edf423621bb0b3b8707836687161210d470e69a4184be9ca011", + "sha256:fdeba88c540c9ed0338c0b2062d9f81af42b18d6646b3e6dda05cf6edd46ada9" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==4.10.1" }, "pyopenssl": { "hashes": [ @@ -1774,18 +1903,18 @@ }, "pyparsing": { "hashes": [ - "sha256:a6a7ee4235a3f944aa1fa2249307708f893fe5717dc603503c6c7969c070fb7c", - "sha256:f86ec8d1a83f11977c9a6ea7598e8c27fc5cddfa5b07ea2241edbbde1d7bc032" + "sha256:93d9577b88da0bbea8cc8334ee8b918ed014968fd2ec383e868fb8afb1ccef84", + "sha256:cbf74e27246d595d9a74b186b810f6fbb86726dbf3b9532efb343f6d7294fe9c" ], - "markers": "python_version >= '3.1'", - "version": "==3.1.4" + "markers": "python_version > '3.0'", + "version": "==3.2.0" }, "python-dateutil": { "hashes": [ "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", "version": "==2.9.0.post0" }, "python-dotenv": { @@ -1795,24 +1924,14 @@ ], "version": "==1.0.1" }, - "python-jose": { - "extras": [ - "cryptography" - ], - "hashes": [ - "sha256:55779b5e6ad599c6336191246e95eb2293a9ddebd555f796a65f838f07e5d78a", - "sha256:9b1376b023f8b298536eedd47ae1089bcdb848f1535ab30555cd92002d78923a" - ], - "version": "==3.3.0" - }, "python-multipart": { "hashes": [ - "sha256:03f54688c663f1b7977105f021043b0793151e4cb1c1a9d4a11fc13d622c4026", - "sha256:97ca7b8ea7b05f977dc3849c3ba99d51689822fab725c3703af7c866a0c2b215" + "sha256:045e1f98d719c1ce085ed7f7e1ef9d8ccc8c02ba02b5566d5f7521410ced58cb", + "sha256:43dcf96cf65888a9cd3423544dd0d75ac10f7aa0c3c28a175bbcd00c9ce1aebf" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==0.0.9" + "version": "==0.0.12" }, "pytz": { "hashes": [ @@ -1881,12 +2000,12 @@ }, "redis": { "hashes": [ - "sha256:0c5b10d387568dfe0698c6fad6615750c24170e548ca2deac10c649d463e9870", - "sha256:56134ee08ea909106090934adc36f65c9bcbbaecea5b21ba704ba6fb561f8eb4" + "sha256:b756df1e4a3858fcc0ef861f3fc53623a96c41e2b1f5304e09e0fe758d333d40", + "sha256:fd4fccba0d7f6aa48c58a78d76ddb4afc698f5da4a2c1d03d916e4fd7ab88cdd" ], "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==5.0.8" + "markers": "python_version >= '3.8'", + "version": "==5.1.0" }, "requests": { "hashes": [ @@ -1898,11 +2017,11 @@ }, "rich": { "hashes": [ - "sha256:1760a3c0848469b97b558fc61c85233e3dafb69c7a071b4d60c38099d3cd4c06", - "sha256:8260cda28e3db6bf04d2d1ef4dbc03ba80a824c88b0e7668a0f23126a424844a" + "sha256:51a2c62057461aaf7152b4d611168f93a9fc73068f8ded2790f29fe2b5366d0c", + "sha256:8c82a3d3f8dcfe9e734771313e606b39d8247bb6b826e196f4914b333b743cf1" ], - "markers": "python_full_version >= '3.7.0'", - "version": "==13.8.1" + "markers": "python_full_version >= '3.8.0'", + "version": "==13.9.2" }, "rsa": { "hashes": [ @@ -1922,20 +2041,20 @@ }, "sentry-sdk": { "hashes": [ - "sha256:1e0e2eaf6dad918c7d1e0edac868a7bf20017b177f242cefe2a6bcd47955961d", - "sha256:b8bc3dc51d06590df1291b7519b85c75e2ced4f28d9ea655b6d54033503b5bf4" + "sha256:49139c31ebcd398f4f6396b18910610a0c1602f6e67083240c33019d1f6aa30c", + "sha256:90f733b32e15dfc1999e6b7aca67a38688a567329de4d6e184154a73f96c6892" ], "index": "pypi", "markers": "python_version >= '3.6'", - "version": "==2.14.0" + "version": "==2.16.0" }, "setuptools": { "hashes": [ - "sha256:5f4c08aa4d3ebcb57a50c33b1b07e94315d7fc7230f7115e47fc99776c8ce308", - "sha256:95b40ed940a1c67eb70fc099094bd6e99c6ee7c23aa2306f4d2697ba7916f9c6" + "sha256:35ab7fd3bcd95e6b7fd704e4a1539513edad446c097797f2985e0e4b960772f2", + "sha256:d59a21b17a275fb872a9c3dae73963160ae079f1049ed956880cd7c09b120538" ], "markers": "python_version >= '3.8'", - "version": "==74.1.2" + "version": "==75.1.0" }, "shellingham": { "hashes": [ @@ -1950,7 +2069,7 @@ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", "version": "==1.16.0" }, "sniffio": { @@ -2053,11 +2172,11 @@ }, "taskiq-dependencies": { "hashes": [ - "sha256:ee52d01e6683cafbeb0a0b0e4abf58b2d304d7db0769e024fe0a0e8bcedadc57", - "sha256:ffa81997b8d6f4be0b2e08280b241dc3cecd9b49ff1fd259688e244d977cadd4" + "sha256:04546a5786e0f8cb2e008af19cdf415dd27d63d6d29ccf15eda8fa6b8b6b8006", + "sha256:8b10d2635a8ada8774f1b555e0a6d72c4fb5e6089601858d38dd95ff6d214a4c" ], "markers": "python_full_version >= '3.8.1' and python_full_version < '4.0.0'", - "version": "==1.5.3" + "version": "==1.5.4" }, "taskiq-fastapi": { "hashes": [ @@ -2070,12 +2189,12 @@ }, "taskiq-redis": { "hashes": [ - "sha256:45b2ac312a61725b4a5bdc5595f160d83986eac21eb5bc080ede5e6272d87d61", - "sha256:867949594e63402bdb8378fcc9f1e4e1a18360cb7d3da30fe06d8c33cb74822f" + "sha256:9a8e8b8e26847e25fbe6e6f8f910632a66f3d38bb5249699193efcfd1e84e25f", + "sha256:d24c4ba34560eb882af351ec34eab4fc90ff6b82ef9b3245d0a499d335b92086" ], "index": "pypi", "markers": "python_full_version >= '3.8.1' and python_full_version < '4.0.0'", - "version": "==1.0.0" + "version": "==1.0.2" }, "typer": { "extras": [ @@ -2107,11 +2226,11 @@ }, "urllib3": { "hashes": [ - "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472", - "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168" + "sha256:0ed14ccfbf1c30a9072c7ca157e4319b70d65f623e91e7b32fadb2853431016e", + "sha256:40c2dc0c681e47eb8f90e7e27bf6ff7df2e677421fd46756da1161c39ca70d32" ], - "markers": "python_version >= '3.8'", - "version": "==2.2.2" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==1.26.20" }, "uvicorn": { "extras": [ @@ -2126,39 +2245,45 @@ }, "uvloop": { "hashes": [ - "sha256:265a99a2ff41a0fd56c19c3838b29bf54d1d177964c300dad388b27e84fd7847", - "sha256:2beee18efd33fa6fdb0976e18475a4042cd31c7433c866e8a09ab604c7c22ff2", - "sha256:35968fc697b0527a06e134999eef859b4034b37aebca537daeb598b9d45a137b", - "sha256:36c530d8fa03bfa7085af54a48f2ca16ab74df3ec7108a46ba82fd8b411a2315", - "sha256:3a609780e942d43a275a617c0839d85f95c334bad29c4c0918252085113285b5", - "sha256:4603ca714a754fc8d9b197e325db25b2ea045385e8a3ad05d3463de725fdf469", - "sha256:4b75f2950ddb6feed85336412b9a0c310a2edbcf4cf931aa5cfe29034829676d", - "sha256:4f44af67bf39af25db4c1ac27e82e9665717f9c26af2369c404be865c8818dcf", - "sha256:6462c95f48e2d8d4c993a2950cd3d31ab061864d1c226bbf0ee2f1a8f36674b9", - "sha256:649c33034979273fa71aa25d0fe120ad1777c551d8c4cd2c0c9851d88fcb13ab", - "sha256:746242cd703dc2b37f9d8b9f173749c15e9a918ddb021575a0205ec29a38d31e", - "sha256:77fbc69c287596880ecec2d4c7a62346bef08b6209749bf6ce8c22bbaca0239e", - "sha256:80dc1b139516be2077b3e57ce1cb65bfed09149e1d175e0478e7a987863b68f0", - "sha256:82edbfd3df39fb3d108fc079ebc461330f7c2e33dbd002d146bf7c445ba6e756", - "sha256:89e8d33bb88d7263f74dc57d69f0063e06b5a5ce50bb9a6b32f5fcbe655f9e73", - "sha256:94707205efbe809dfa3a0d09c08bef1352f5d3d6612a506f10a319933757c006", - "sha256:95720bae002ac357202e0d866128eb1ac82545bcf0b549b9abe91b5178d9b541", - "sha256:9b04d96188d365151d1af41fa2d23257b674e7ead68cfd61c725a422764062ae", - "sha256:9d0fba61846f294bce41eb44d60d58136090ea2b5b99efd21cbdf4e21927c56a", - "sha256:9ebafa0b96c62881d5cafa02d9da2e44c23f9f0cd829f3a32a6aff771449c996", - "sha256:a0fac7be202596c7126146660725157d4813aa29a4cc990fe51346f75ff8fde7", - "sha256:aea15c78e0d9ad6555ed201344ae36db5c63d428818b4b2a42842b3870127c00", - "sha256:b10c2956efcecb981bf9cfb8184d27d5d64b9033f917115a960b83f11bfa0d6b", - "sha256:b16696f10e59d7580979b420eedf6650010a4a9c3bd8113f24a103dfdb770b10", - "sha256:d8c36fdf3e02cec92aed2d44f63565ad1522a499c654f07935c8f9d04db69e95", - "sha256:e237f9c1e8a00e7d9ddaa288e535dc337a39bcbf679f290aee9d26df9e72bce9", - "sha256:e50289c101495e0d1bb0bfcb4a60adde56e32f4449a67216a1ab2750aa84f037", - "sha256:e7d61fe8e8d9335fac1bf8d5d82820b4808dd7a43020c149b63a1ada953d48a6", - "sha256:e97152983442b499d7a71e44f29baa75b3b02e65d9c44ba53b10338e98dedb66", - "sha256:f0e94b221295b5e69de57a1bd4aeb0b3a29f61be6e1b478bb8a69a73377db7ba", - "sha256:fee6044b64c965c425b65a4e17719953b96e065c5b7e09b599ff332bb2744bdf" - ], - "version": "==0.20.0" + "sha256:0878c2640cf341b269b7e128b1a5fed890adc4455513ca710d77d5e93aa6d6a0", + "sha256:10d66943def5fcb6e7b37310eb6b5639fd2ccbc38df1177262b0640c3ca68c1f", + "sha256:10da8046cc4a8f12c91a1c39d1dd1585c41162a15caaef165c2174db9ef18bdc", + "sha256:17df489689befc72c39a08359efac29bbee8eee5209650d4b9f34df73d22e414", + "sha256:183aef7c8730e54c9a3ee3227464daed66e37ba13040bb3f350bc2ddc040f22f", + "sha256:196274f2adb9689a289ad7d65700d37df0c0930fd8e4e743fa4834e850d7719d", + "sha256:221f4f2a1f46032b403bf3be628011caf75428ee3cc204a22addf96f586b19fd", + "sha256:2d1f581393673ce119355d56da84fe1dd9d2bb8b3d13ce792524e1607139feff", + "sha256:359ec2c888397b9e592a889c4d72ba3d6befba8b2bb01743f72fffbde663b59c", + "sha256:3bf12b0fda68447806a7ad847bfa591613177275d35b6724b1ee573faa3704e3", + "sha256:4509360fcc4c3bd2c70d87573ad472de40c13387f5fda8cb58350a1d7475e58d", + "sha256:460def4412e473896ef179a1671b40c039c7012184b627898eea5072ef6f017a", + "sha256:461d9ae6660fbbafedd07559c6a2e57cd553b34b0065b6550685f6653a98c1cb", + "sha256:46923b0b5ee7fc0020bef24afe7836cb068f5050ca04caf6b487c513dc1a20b2", + "sha256:53e420a3afe22cdcf2a0f4846e377d16e718bc70103d7088a4f7623567ba5fb0", + "sha256:5ee4d4ef48036ff6e5cfffb09dd192c7a5027153948d85b8da7ff705065bacc6", + "sha256:67dd654b8ca23aed0a8e99010b4c34aca62f4b7fce88f39d452ed7622c94845c", + "sha256:787ae31ad8a2856fc4e7c095341cccc7209bd657d0e71ad0dc2ea83c4a6fa8af", + "sha256:86975dca1c773a2c9864f4c52c5a55631038e387b47eaf56210f873887b6c8dc", + "sha256:87c43e0f13022b998eb9b973b5e97200c8b90823454d4bc06ab33829e09fb9bb", + "sha256:88cb67cdbc0e483da00af0b2c3cdad4b7c61ceb1ee0f33fe00e09c81e3a6cb75", + "sha256:8a375441696e2eda1c43c44ccb66e04d61ceeffcd76e4929e527b7fa401b90fb", + "sha256:a5c39f217ab3c663dc699c04cbd50c13813e31d917642d459fdcec07555cc553", + "sha256:b9fb766bb57b7388745d8bcc53a359b116b8a04c83a2288069809d2b3466c37e", + "sha256:baa0e6291d91649c6ba4ed4b2f982f9fa165b5bbd50a9e203c416a2797bab3c6", + "sha256:baa4dcdbd9ae0a372f2167a207cd98c9f9a1ea1188a8a526431eef2f8116cc8d", + "sha256:bc09f0ff191e61c2d592a752423c767b4ebb2986daa9ed62908e2b1b9a9ae206", + "sha256:bd53ecc9a0f3d87ab847503c2e1552b690362e005ab54e8a48ba97da3924c0dc", + "sha256:bfd55dfcc2a512316e65f16e503e9e450cab148ef11df4e4e679b5e8253a5281", + "sha256:c097078b8031190c934ed0ebfee8cc5f9ba9642e6eb88322b9958b649750f72b", + "sha256:c0f3fa6200b3108919f8bdabb9a7f87f20e7097ea3c543754cabc7d717d95cf8", + "sha256:e678ad6fe52af2c58d2ae3c73dc85524ba8abe637f134bf3564ed07f555c5e79", + "sha256:ec7e6b09a6fdded42403182ab6b832b71f4edaf7f37a9a0e371a01db5f0cb45f", + "sha256:f0ce1b49560b1d2d8a2977e3ba4afb2414fb46b86a1b64056bc4ab929efdafbe", + "sha256:f38b2e090258d051d68a5b14d1da7203a3c3677321cf32a95a6f4db4dd8b6f26", + "sha256:f3df876acd7ec037a3d005b3ab85a7e4110422e4d9c1571d4fc89b0fc41b6816", + "sha256:f7089d2dc73179ce5ac255bdf37c236a9f914b264825fdaacaded6990a7fb4c2" + ], + "version": "==0.21.0" }, "watchdog": { "hashes": [ @@ -2283,94 +2408,94 @@ }, "websockets": { "hashes": [ - "sha256:00fd961943b6c10ee6f0b1130753e50ac5dcd906130dcd77b0003c3ab797d026", - "sha256:03d3f9ba172e0a53e37fa4e636b86cc60c3ab2cfee4935e66ed1d7acaa4625ad", - "sha256:0513c727fb8adffa6d9bf4a4463b2bade0186cbd8c3604ae5540fae18a90cb99", - "sha256:05e70fec7c54aad4d71eae8e8cab50525e899791fc389ec6f77b95312e4e9920", - "sha256:0617fd0b1d14309c7eab6ba5deae8a7179959861846cbc5cb528a7531c249448", - "sha256:06c0a667e466fcb56a0886d924b5f29a7f0886199102f0a0e1c60a02a3751cb4", - "sha256:0f52504023b1480d458adf496dc1c9e9811df4ba4752f0bc1f89ae92f4f07d0c", - "sha256:10a0dc7242215d794fb1918f69c6bb235f1f627aaf19e77f05336d147fce7c37", - "sha256:11f9976ecbc530248cf162e359a92f37b7b282de88d1d194f2167b5e7ad80ce3", - "sha256:132511bfd42e77d152c919147078460c88a795af16b50e42a0bd14f0ad71ddd2", - "sha256:139add0f98206cb74109faf3611b7783ceafc928529c62b389917a037d4cfdf4", - "sha256:14b9c006cac63772b31abbcd3e3abb6228233eec966bf062e89e7fa7ae0b7333", - "sha256:15c7d62ee071fa94a2fc52c2b472fed4af258d43f9030479d9c4a2de885fd543", - "sha256:165bedf13556f985a2aa064309baa01462aa79bf6112fbd068ae38993a0e1f1b", - "sha256:17118647c0ea14796364299e942c330d72acc4b248e07e639d34b75067b3cdd8", - "sha256:1841c9082a3ba4a05ea824cf6d99570a6a2d8849ef0db16e9c826acb28089e8f", - "sha256:1a678532018e435396e37422a95e3ab87f75028ac79570ad11f5bf23cd2a7d8c", - "sha256:1ee4cc030a4bdab482a37462dbf3ffb7e09334d01dd37d1063be1136a0d825fa", - "sha256:1f3cf6d6ec1142412d4535adabc6bd72a63f5f148c43fe559f06298bc21953c9", - "sha256:1f613289f4a94142f914aafad6c6c87903de78eae1e140fa769a7385fb232fdf", - "sha256:1fa082ea38d5de51dd409434edc27c0dcbd5fed2b09b9be982deb6f0508d25bc", - "sha256:249aab278810bee585cd0d4de2f08cfd67eed4fc75bde623be163798ed4db2eb", - "sha256:254ecf35572fca01a9f789a1d0f543898e222f7b69ecd7d5381d8d8047627bdb", - "sha256:2a02b0161c43cc9e0232711eff846569fad6ec836a7acab16b3cf97b2344c060", - "sha256:30d3a1f041360f029765d8704eae606781e673e8918e6b2c792e0775de51352f", - "sha256:3624fd8664f2577cf8de996db3250662e259bfbc870dd8ebdcf5d7c6ac0b5185", - "sha256:3f55b36d17ac50aa8a171b771e15fbe1561217510c8768af3d546f56c7576cdc", - "sha256:46af561eba6f9b0848b2c9d2427086cabadf14e0abdd9fde9d72d447df268418", - "sha256:47236c13be337ef36546004ce8c5580f4b1150d9538b27bf8a5ad8edf23ccfab", - "sha256:4a365bcb7be554e6e1f9f3ed64016e67e2fa03d7b027a33e436aecf194febb63", - "sha256:4d6ece65099411cfd9a48d13701d7438d9c34f479046b34c50ff60bb8834e43e", - "sha256:4e85f46ce287f5c52438bb3703d86162263afccf034a5ef13dbe4318e98d86e7", - "sha256:4f0426d51c8f0926a4879390f53c7f5a855e42d68df95fff6032c82c888b5f36", - "sha256:518f90e6dd089d34eaade01101fd8a990921c3ba18ebbe9b0165b46ebff947f0", - "sha256:52aed6ef21a0f1a2a5e310fb5c42d7555e9c5855476bbd7173c3aa3d8a0302f2", - "sha256:556e70e4f69be1082e6ef26dcb70efcd08d1850f5d6c5f4f2bcb4e397e68f01f", - "sha256:56a952fa2ae57a42ba7951e6b2605e08a24801a4931b5644dfc68939e041bc7f", - "sha256:59197afd478545b1f73367620407b0083303569c5f2d043afe5363676f2697c9", - "sha256:5df891c86fe68b2c38da55b7aea7095beca105933c697d719f3f45f4220a5e0e", - "sha256:63848cdb6fcc0bf09d4a155464c46c64ffdb5807ede4fb251da2c2692559ce75", - "sha256:64a11aae1de4c178fa653b07d90f2fb1a2ed31919a5ea2361a38760192e1858b", - "sha256:6724b554b70d6195ba19650fef5759ef11346f946c07dbbe390e039bcaa7cc3d", - "sha256:67494e95d6565bf395476e9d040037ff69c8b3fa356a886b21d8422ad86ae075", - "sha256:67648f5e50231b5a7f6d83b32f9c525e319f0ddc841be0de64f24928cd75a603", - "sha256:68264802399aed6fe9652e89761031acc734fc4c653137a5911c2bfa995d6d6d", - "sha256:699ba9dd6a926f82a277063603fc8d586b89f4cb128efc353b749b641fcddda7", - "sha256:6aa74a45d4cdc028561a7d6ab3272c8b3018e23723100b12e58be9dfa5a24491", - "sha256:6b41a1b3b561f1cba8321fb32987552a024a8f67f0d05f06fcf29f0090a1b956", - "sha256:71e6e5a3a3728886caee9ab8752e8113670936a193284be9d6ad2176a137f376", - "sha256:7d20516990d8ad557b5abeb48127b8b779b0b7e6771a265fa3e91767596d7d97", - "sha256:80e4ba642fc87fa532bac07e5ed7e19d56940b6af6a8c61d4429be48718a380f", - "sha256:872afa52a9f4c414d6955c365b6588bc4401272c629ff8321a55f44e3f62b553", - "sha256:8eb2b9a318542153674c6e377eb8cb9ca0fc011c04475110d3477862f15d29f0", - "sha256:9bbc525f4be3e51b89b2a700f5746c2a6907d2e2ef4513a8daafc98198b92237", - "sha256:a1a2e272d067030048e1fe41aa1ec8cfbbaabce733b3d634304fa2b19e5c897f", - "sha256:a5dc0c42ded1557cc7c3f0240b24129aefbad88af4f09346164349391dea8e58", - "sha256:acab3539a027a85d568c2573291e864333ec9d912675107d6efceb7e2be5d980", - "sha256:acbebec8cb3d4df6e2488fbf34702cbc37fc39ac7abf9449392cefb3305562e9", - "sha256:ad327ac80ba7ee61da85383ca8822ff808ab5ada0e4a030d66703cc025b021c4", - "sha256:b448a0690ef43db5ef31b3a0d9aea79043882b4632cfc3eaab20105edecf6097", - "sha256:b5a06d7f60bc2fc378a333978470dfc4e1415ee52f5f0fce4f7853eb10c1e9df", - "sha256:b74593e9acf18ea5469c3edaa6b27fa7ecf97b30e9dabd5a94c4c940637ab96e", - "sha256:b79915a1179a91f6c5f04ece1e592e2e8a6bd245a0e45d12fd56b2b59e559a32", - "sha256:b80f0c51681c517604152eb6a572f5a9378f877763231fddb883ba2f968e8817", - "sha256:b8ac5b46fd798bbbf2ac6620e0437c36a202b08e1f827832c4bf050da081b501", - "sha256:c3c493d0e5141ec055a7d6809a28ac2b88d5b878bb22df8c621ebe79a61123d0", - "sha256:c44ca9ade59b2e376612df34e837013e2b273e6c92d7ed6636d0556b6f4db93d", - "sha256:c4a6343e3b0714e80da0b0893543bf9a5b5fa71b846ae640e56e9abc6fbc4c83", - "sha256:c5870b4a11b77e4caa3937142b650fbbc0914a3e07a0cf3131f35c0587489c1c", - "sha256:ca48914cdd9f2ccd94deab5bcb5ac98025a5ddce98881e5cce762854a5de330b", - "sha256:cf2fae6d85e5dc384bf846f8243ddaa9197f3a1a70044f59399af001fd1f51d4", - "sha256:d450f5a7a35662a9b91a64aefa852f0c0308ee256122f5218a42f1d13577d71e", - "sha256:d6716c087e4aa0b9260c4e579bb82e068f84faddb9bfba9906cb87726fa2e870", - "sha256:d93572720d781331fb10d3da9ca1067817d84ad1e7c31466e9f5e59965618096", - "sha256:dbb0b697cc0655719522406c059eae233abaa3243821cfdfab1215d02ac10231", - "sha256:e33505534f3f673270dd67f81e73550b11de5b538c56fe04435d63c02c3f26b5", - "sha256:e801ca2f448850685417d723ec70298feff3ce4ff687c6f20922c7474b4746ae", - "sha256:e82db3756ccb66266504f5a3de05ac6b32f287faacff72462612120074103329", - "sha256:ef48e4137e8799998a343706531e656fdec6797b80efd029117edacb74b0a10a", - "sha256:f1d3d1f2eb79fe7b0fb02e599b2bf76a7619c79300fc55f0b5e2d382881d4f7f", - "sha256:f3fea72e4e6edb983908f0db373ae0732b275628901d909c382aae3b592589f2", - "sha256:f40de079779acbcdbb6ed4c65af9f018f8b77c5ec4e17a4b737c05c2db554491", - "sha256:f73e676a46b0fe9426612ce8caeca54c9073191a77c3e9d5c94697aef99296af", - "sha256:f9c9e258e3d5efe199ec23903f5da0eeaad58cf6fccb3547b74fd4750e5ac47a", - "sha256:fac2d146ff30d9dd2fcf917e5d147db037a5c573f0446c564f16f1f94cf87462", - "sha256:faef9ec6354fe4f9a2c0bbb52fb1ff852effc897e2a4501e25eb3a47cb0a4f89" - ], - "version": "==13.0.1" + "sha256:004280a140f220c812e65f36944a9ca92d766b6cc4560be652a0a3883a79ed8a", + "sha256:035233b7531fb92a76beefcbf479504db8c72eb3bff41da55aecce3a0f729e54", + "sha256:149e622dc48c10ccc3d2760e5f36753db9cacf3ad7bc7bbbfd7d9c819e286f23", + "sha256:163e7277e1a0bd9fb3c8842a71661ad19c6aa7bb3d6678dc7f89b17fbcc4aeb7", + "sha256:18503d2c5f3943e93819238bf20df71982d193f73dcecd26c94514f417f6b135", + "sha256:1971e62d2caa443e57588e1d82d15f663b29ff9dfe7446d9964a4b6f12c1e700", + "sha256:204e5107f43095012b00f1451374693267adbb832d29966a01ecc4ce1db26faf", + "sha256:2510c09d8e8df777177ee3d40cd35450dc169a81e747455cc4197e63f7e7bfe5", + "sha256:25c35bf84bf7c7369d247f0b8cfa157f989862c49104c5cf85cb5436a641d93e", + "sha256:2f85cf4f2a1ba8f602298a853cec8526c2ca42a9a4b947ec236eaedb8f2dc80c", + "sha256:308e20f22c2c77f3f39caca508e765f8725020b84aa963474e18c59accbf4c02", + "sha256:325b1ccdbf5e5725fdcb1b0e9ad4d2545056479d0eee392c291c1bf76206435a", + "sha256:327b74e915cf13c5931334c61e1a41040e365d380f812513a255aa804b183418", + "sha256:346bee67a65f189e0e33f520f253d5147ab76ae42493804319b5716e46dddf0f", + "sha256:38377f8b0cdeee97c552d20cf1865695fcd56aba155ad1b4ca8779a5b6ef4ac3", + "sha256:3c78383585f47ccb0fcf186dcb8a43f5438bd7d8f47d69e0b56f71bf431a0a68", + "sha256:4059f790b6ae8768471cddb65d3c4fe4792b0ab48e154c9f0a04cefaabcd5978", + "sha256:459bf774c754c35dbb487360b12c5727adab887f1622b8aed5755880a21c4a20", + "sha256:463e1c6ec853202dd3657f156123d6b4dad0c546ea2e2e38be2b3f7c5b8e7295", + "sha256:4676df3fe46956fbb0437d8800cd5f2b6d41143b6e7e842e60554398432cf29b", + "sha256:485307243237328c022bc908b90e4457d0daa8b5cf4b3723fd3c4a8012fce4c6", + "sha256:48a2ef1381632a2f0cb4efeff34efa97901c9fbc118e01951ad7cfc10601a9bb", + "sha256:4b889dbd1342820cc210ba44307cf75ae5f2f96226c0038094455a96e64fb07a", + "sha256:586a356928692c1fed0eca68b4d1c2cbbd1ca2acf2ac7e7ebd3b9052582deefa", + "sha256:58cf7e75dbf7e566088b07e36ea2e3e2bd5676e22216e4cad108d4df4a7402a0", + "sha256:5993260f483d05a9737073be197371940c01b257cc45ae3f1d5d7adb371b266a", + "sha256:5dd6da9bec02735931fccec99d97c29f47cc61f644264eb995ad6c0c27667238", + "sha256:5f2e75431f8dc4a47f31565a6e1355fb4f2ecaa99d6b89737527ea917066e26c", + "sha256:5f9fee94ebafbc3117c30be1844ed01a3b177bb6e39088bc6b2fa1dc15572084", + "sha256:61fc0dfcda609cda0fc9fe7977694c0c59cf9d749fbb17f4e9483929e3c48a19", + "sha256:624459daabeb310d3815b276c1adef475b3e6804abaf2d9d2c061c319f7f187d", + "sha256:62d516c325e6540e8a57b94abefc3459d7dab8ce52ac75c96cad5549e187e3a7", + "sha256:6548f29b0e401eea2b967b2fdc1c7c7b5ebb3eeb470ed23a54cd45ef078a0db9", + "sha256:6d2aad13a200e5934f5a6767492fb07151e1de1d6079c003ab31e1823733ae79", + "sha256:6d6855bbe70119872c05107e38fbc7f96b1d8cb047d95c2c50869a46c65a8e96", + "sha256:70c5be9f416aa72aab7a2a76c90ae0a4fe2755c1816c153c1a2bcc3333ce4ce6", + "sha256:730f42125ccb14602f455155084f978bd9e8e57e89b569b4d7f0f0c17a448ffe", + "sha256:7a43cfdcddd07f4ca2b1afb459824dd3c6d53a51410636a2c7fc97b9a8cf4842", + "sha256:7bd6abf1e070a6b72bfeb71049d6ad286852e285f146682bf30d0296f5fbadfa", + "sha256:7c1e90228c2f5cdde263253fa5db63e6653f1c00e7ec64108065a0b9713fa1b3", + "sha256:7c65ffa900e7cc958cd088b9a9157a8141c991f8c53d11087e6fb7277a03f81d", + "sha256:80c421e07973a89fbdd93e6f2003c17d20b69010458d3a8e37fb47874bd67d51", + "sha256:82d0ba76371769d6a4e56f7e83bb8e81846d17a6190971e38b5de108bde9b0d7", + "sha256:83f91d8a9bb404b8c2c41a707ac7f7f75b9442a0a876df295de27251a856ad09", + "sha256:87c6e35319b46b99e168eb98472d6c7d8634ee37750d7693656dc766395df096", + "sha256:8d23b88b9388ed85c6faf0e74d8dec4f4d3baf3ecf20a65a47b836d56260d4b9", + "sha256:9156c45750b37337f7b0b00e6248991a047be4aa44554c9886fe6bdd605aab3b", + "sha256:91a0fa841646320ec0d3accdff5b757b06e2e5c86ba32af2e0815c96c7a603c5", + "sha256:95858ca14a9f6fa8413d29e0a585b31b278388aa775b8a81fa24830123874678", + "sha256:95df24ca1e1bd93bbca51d94dd049a984609687cb2fb08a7f2c56ac84e9816ea", + "sha256:9b37c184f8b976f0c0a231a5f3d6efe10807d41ccbe4488df8c74174805eea7d", + "sha256:9b6f347deb3dcfbfde1c20baa21c2ac0751afaa73e64e5b693bb2b848efeaa49", + "sha256:9d75baf00138f80b48f1eac72ad1535aac0b6461265a0bcad391fc5aba875cfc", + "sha256:9ef8aa8bdbac47f4968a5d66462a2a0935d044bf35c0e5a8af152d58516dbeb5", + "sha256:a11e38ad8922c7961447f35c7b17bffa15de4d17c70abd07bfbe12d6faa3e027", + "sha256:a1b54689e38d1279a51d11e3467dd2f3a50f5f2e879012ce8f2d6943f00e83f0", + "sha256:a3b3366087c1bc0a2795111edcadddb8b3b59509d5db5d7ea3fdd69f954a8878", + "sha256:a569eb1b05d72f9bce2ebd28a1ce2054311b66677fcd46cf36204ad23acead8c", + "sha256:a7affedeb43a70351bb811dadf49493c9cfd1ed94c9c70095fd177e9cc1541fa", + "sha256:a9a396a6ad26130cdae92ae10c36af09d9bfe6cafe69670fd3b6da9b07b4044f", + "sha256:a9ab1e71d3d2e54a0aa646ab6d4eebfaa5f416fe78dfe4da2839525dc5d765c6", + "sha256:a9cd1af7e18e5221d2878378fbc287a14cd527fdd5939ed56a18df8a31136bb2", + "sha256:a9dcaf8b0cc72a392760bb8755922c03e17a5a54e08cca58e8b74f6902b433cf", + "sha256:b9d7439d7fab4dce00570bb906875734df13d9faa4b48e261c440a5fec6d9708", + "sha256:bcc03c8b72267e97b49149e4863d57c2d77f13fae12066622dc78fe322490fe6", + "sha256:c11d4d16e133f6df8916cc5b7e3e96ee4c44c936717d684a94f48f82edb7c92f", + "sha256:c1dca61c6db1166c48b95198c0b7d9c990b30c756fc2923cc66f68d17dc558fd", + "sha256:c518e84bb59c2baae725accd355c8dc517b4a3ed8db88b4bc93c78dae2974bf2", + "sha256:c7934fd0e920e70468e676fe7f1b7261c1efa0d6c037c6722278ca0228ad9d0d", + "sha256:c7e72ce6bda6fb9409cc1e8164dd41d7c91466fb599eb047cfda72fe758a34a7", + "sha256:c90d6dec6be2c7d03378a574de87af9b1efea77d0c52a8301dd831ece938452f", + "sha256:ceec59f59d092c5007e815def4ebb80c2de330e9588e101cf8bd94c143ec78a5", + "sha256:cf1781ef73c073e6b0f90af841aaf98501f975d306bbf6221683dd594ccc52b6", + "sha256:d04f13a1d75cb2b8382bdc16ae6fa58c97337253826dfe136195b7f89f661557", + "sha256:d6d300f8ec35c24025ceb9b9019ae9040c1ab2f01cddc2bcc0b518af31c75c14", + "sha256:d8dbb1bf0c0a4ae8b40bdc9be7f644e2f3fb4e8a9aca7145bfa510d4a374eeb7", + "sha256:de58647e3f9c42f13f90ac7e5f58900c80a39019848c5547bc691693098ae1bd", + "sha256:deeb929efe52bed518f6eb2ddc00cc496366a14c726005726ad62c2dd9017a3c", + "sha256:df01aea34b6e9e33572c35cd16bae5a47785e7d5c8cb2b54b2acdb9678315a17", + "sha256:e2620453c075abeb0daa949a292e19f56de518988e079c36478bacf9546ced23", + "sha256:e4450fc83a3df53dec45922b576e91e94f5578d06436871dce3a6be38e40f5db", + "sha256:e54affdeb21026329fb0744ad187cf812f7d3c2aa702a5edb562b325191fcab6", + "sha256:e9875a0143f07d74dc5e1ded1c4581f0d9f7ab86c78994e2ed9e95050073c94d", + "sha256:f1c3cf67185543730888b20682fb186fc8d0fa6f07ccc3ef4390831ab4b388d9", + "sha256:f48c749857f8fb598fb890a75f540e3221d0976ed0bf879cf3c7eef34151acee", + "sha256:f779498eeec470295a2b1a5d97aa1bc9814ecd25e1eb637bd9d1c73a327387f6" + ], + "version": "==13.1" }, "wrapt": { "hashes": [ @@ -2450,109 +2575,115 @@ }, "yarl": { "hashes": [ - "sha256:01a8697ec24f17c349c4f655763c4db70eebc56a5f82995e5e26e837c6eb0e49", - "sha256:02da8759b47d964f9173c8675710720b468aa1c1693be0c9c64abb9d8d9a4867", - "sha256:04293941646647b3bfb1719d1d11ff1028e9c30199509a844da3c0f5919dc520", - "sha256:067b961853c8e62725ff2893226fef3d0da060656a9827f3f520fb1d19b2b68a", - "sha256:077da604852be488c9a05a524068cdae1e972b7dc02438161c32420fb4ec5e14", - "sha256:09696438cb43ea6f9492ef237761b043f9179f455f405279e609f2bc9100212a", - "sha256:0b8486f322d8f6a38539136a22c55f94d269addb24db5cb6f61adc61eabc9d93", - "sha256:0ea9682124fc062e3d931c6911934a678cb28453f957ddccf51f568c2f2b5e05", - "sha256:0f351fa31234699d6084ff98283cb1e852270fe9e250a3b3bf7804eb493bd937", - "sha256:14438dfc5015661f75f85bc5adad0743678eefee266ff0c9a8e32969d5d69f74", - "sha256:15061ce6584ece023457fb8b7a7a69ec40bf7114d781a8c4f5dcd68e28b5c53b", - "sha256:15439f3c5c72686b6c3ff235279630d08936ace67d0fe5c8d5bbc3ef06f5a420", - "sha256:17b5a386d0d36fb828e2fb3ef08c8829c1ebf977eef88e5367d1c8c94b454639", - "sha256:18ac56c9dd70941ecad42b5a906820824ca72ff84ad6fa18db33c2537ae2e089", - "sha256:1bb2d9e212fb7449b8fb73bc461b51eaa17cc8430b4a87d87be7b25052d92f53", - "sha256:1e969fa4c1e0b1a391f3fcbcb9ec31e84440253325b534519be0d28f4b6b533e", - "sha256:1fa2e7a406fbd45b61b4433e3aa254a2c3e14c4b3186f6e952d08a730807fa0c", - "sha256:2164cd9725092761fed26f299e3f276bb4b537ca58e6ff6b252eae9631b5c96e", - "sha256:21a7c12321436b066c11ec19c7e3cb9aec18884fe0d5b25d03d756a9e654edfe", - "sha256:238a21849dd7554cb4d25a14ffbfa0ef380bb7ba201f45b144a14454a72ffa5a", - "sha256:250e888fa62d73e721f3041e3a9abf427788a1934b426b45e1b92f62c1f68366", - "sha256:25861303e0be76b60fddc1250ec5986c42f0a5c0c50ff57cc30b1be199c00e63", - "sha256:267b24f891e74eccbdff42241c5fb4f974de2d6271dcc7d7e0c9ae1079a560d9", - "sha256:27fcb271a41b746bd0e2a92182df507e1c204759f460ff784ca614e12dd85145", - "sha256:2909fa3a7d249ef64eeb2faa04b7957e34fefb6ec9966506312349ed8a7e77bf", - "sha256:3257978c870728a52dcce8c2902bf01f6c53b65094b457bf87b2644ee6238ddc", - "sha256:327c724b01b8641a1bf1ab3b232fb638706e50f76c0b5bf16051ab65c868fac5", - "sha256:3de5292f9f0ee285e6bd168b2a77b2a00d74cbcfa420ed078456d3023d2f6dff", - "sha256:3fce4da3703ee6048ad4138fe74619c50874afe98b1ad87b2698ef95bf92c96d", - "sha256:3ff6b1617aa39279fe18a76c8d165469c48b159931d9b48239065767ee455b2b", - "sha256:400cd42185f92de559d29eeb529e71d80dfbd2f45c36844914a4a34297ca6f00", - "sha256:4179522dc0305c3fc9782549175c8e8849252fefeb077c92a73889ccbcd508ad", - "sha256:4307d9a3417eea87715c9736d050c83e8c1904e9b7aada6ce61b46361b733d92", - "sha256:476e20c433b356e16e9a141449f25161e6b69984fb4cdbd7cd4bd54c17844998", - "sha256:489fa8bde4f1244ad6c5f6d11bb33e09cf0d1d0367edb197619c3e3fc06f3d91", - "sha256:48a28bed68ab8fb7e380775f0029a079f08a17799cb3387a65d14ace16c12e2b", - "sha256:48dfd117ab93f0129084577a07287376cc69c08138694396f305636e229caa1a", - "sha256:4973eac1e2ff63cf187073cd4e1f1148dcd119314ab79b88e1b3fad74a18c9d5", - "sha256:498442e3af2a860a663baa14fbf23fb04b0dd758039c0e7c8f91cb9279799bff", - "sha256:501c503eed2bb306638ccb60c174f856cc3246c861829ff40eaa80e2f0330367", - "sha256:504cf0d4c5e4579a51261d6091267f9fd997ef58558c4ffa7a3e1460bd2336fa", - "sha256:61a5f2c14d0a1adfdd82258f756b23a550c13ba4c86c84106be4c111a3a4e413", - "sha256:637c7ddb585a62d4469f843dac221f23eec3cbad31693b23abbc2c366ad41ff4", - "sha256:66b63c504d2ca43bf7221a1f72fbe981ff56ecb39004c70a94485d13e37ebf45", - "sha256:67459cf8cf31da0e2cbdb4b040507e535d25cfbb1604ca76396a3a66b8ba37a6", - "sha256:688654f8507464745ab563b041d1fb7dab5d9912ca6b06e61d1c4708366832f5", - "sha256:6907daa4b9d7a688063ed098c472f96e8181733c525e03e866fb5db480a424df", - "sha256:69721b8effdb588cb055cc22f7c5105ca6fdaa5aeb3ea09021d517882c4a904c", - "sha256:6d23754b9939cbab02c63434776df1170e43b09c6a517585c7ce2b3d449b7318", - "sha256:7175a87ab8f7fbde37160a15e58e138ba3b2b0e05492d7351314a250d61b1591", - "sha256:72bf26f66456baa0584eff63e44545c9f0eaed9b73cb6601b647c91f14c11f38", - "sha256:74db2ef03b442276d25951749a803ddb6e270d02dda1d1c556f6ae595a0d76a8", - "sha256:750f656832d7d3cb0c76be137ee79405cc17e792f31e0a01eee390e383b2936e", - "sha256:75e0ae31fb5ccab6eda09ba1494e87eb226dcbd2372dae96b87800e1dcc98804", - "sha256:768ecc550096b028754ea28bf90fde071c379c62c43afa574edc6f33ee5daaec", - "sha256:7d51324a04fc4b0e097ff8a153e9276c2593106a811704025bbc1d6916f45ca6", - "sha256:7e975a2211952a8a083d1b9d9ba26472981ae338e720b419eb50535de3c02870", - "sha256:8215f6f21394d1f46e222abeb06316e77ef328d628f593502d8fc2a9117bde83", - "sha256:8258c86f47e080a258993eed877d579c71da7bda26af86ce6c2d2d072c11320d", - "sha256:8418c053aeb236b20b0ab8fa6bacfc2feaaf7d4683dd96528610989c99723d5f", - "sha256:87f020d010ba80a247c4abc335fc13421037800ca20b42af5ae40e5fd75e7909", - "sha256:884eab2ce97cbaf89f264372eae58388862c33c4f551c15680dd80f53c89a269", - "sha256:8a336eaa7ee7e87cdece3cedb395c9657d227bfceb6781295cf56abcd3386a26", - "sha256:8aef1b64da41d18026632d99a06b3fefe1d08e85dd81d849fa7c96301ed22f1b", - "sha256:8aef97ba1dd2138112890ef848e17d8526fe80b21f743b4ee65947ea184f07a2", - "sha256:8ed653638ef669e0efc6fe2acb792275cb419bf9cb5c5049399f3556995f23c7", - "sha256:9361628f28f48dcf8b2f528420d4d68102f593f9c2e592bfc842f5fb337e44fd", - "sha256:946eedc12895873891aaceb39bceb484b4977f70373e0122da483f6c38faaa68", - "sha256:94d0caaa912bfcdc702a4204cd5e2bb01eb917fc4f5ea2315aa23962549561b0", - "sha256:964a428132227edff96d6f3cf261573cb0f1a60c9a764ce28cda9525f18f7786", - "sha256:999bfee0a5b7385a0af5ffb606393509cfde70ecca4f01c36985be6d33e336da", - "sha256:a08ea567c16f140af8ddc7cb58e27e9138a1386e3e6e53982abaa6f2377b38cc", - "sha256:a28b70c9e2213de425d9cba5ab2e7f7a1c8ca23a99c4b5159bf77b9c31251447", - "sha256:a34e1e30f1774fa35d37202bbeae62423e9a79d78d0874e5556a593479fdf239", - "sha256:a4264515f9117be204935cd230fb2a052dd3792789cc94c101c535d349b3dab0", - "sha256:a7915ea49b0c113641dc4d9338efa9bd66b6a9a485ffe75b9907e8573ca94b84", - "sha256:aac44097d838dda26526cffb63bdd8737a2dbdf5f2c68efb72ad83aec6673c7e", - "sha256:b91044952da03b6f95fdba398d7993dd983b64d3c31c358a4c89e3c19b6f7aef", - "sha256:ba444bdd4caa2a94456ef67a2f383710928820dd0117aae6650a4d17029fa25e", - "sha256:c2dc4250fe94d8cd864d66018f8344d4af50e3758e9d725e94fecfa27588ff82", - "sha256:c35f493b867912f6fda721a59cc7c4766d382040bdf1ddaeeaa7fa4d072f4675", - "sha256:c92261eb2ad367629dc437536463dc934030c9e7caca861cc51990fe6c565f26", - "sha256:ce928c9c6409c79e10f39604a7e214b3cb69552952fbda8d836c052832e6a979", - "sha256:d95b52fbef190ca87d8c42f49e314eace4fc52070f3dfa5f87a6594b0c1c6e46", - "sha256:dae7bd0daeb33aa3e79e72877d3d51052e8b19c9025ecf0374f542ea8ec120e4", - "sha256:e286580b6511aac7c3268a78cdb861ec739d3e5a2a53b4809faef6b49778eaff", - "sha256:e4b53f73077e839b3f89c992223f15b1d2ab314bdbdf502afdc7bb18e95eae27", - "sha256:e8f63904df26d1a66aabc141bfd258bf738b9bc7bc6bdef22713b4f5ef789a4c", - "sha256:f3a6d90cab0bdf07df8f176eae3a07127daafcf7457b997b2bf46776da2c7eb7", - "sha256:f41fa79114a1d2eddb5eea7b912d6160508f57440bd302ce96eaa384914cd265", - "sha256:f46f81501160c28d0c0b7333b4f7be8983dbbc161983b6fb814024d1b4952f79", - "sha256:f61db3b7e870914dbd9434b560075e0366771eecbe6d2b5561f5bc7485f39efd" - ], - "markers": "python_version >= '3.8'", - "version": "==1.11.1" + "sha256:0545de8c688fbbf3088f9e8b801157923be4bf8e7b03e97c2ecd4dfa39e48e0e", + "sha256:076b1ed2ac819933895b1a000904f62d615fe4533a5cf3e052ff9a1da560575c", + "sha256:0afad2cd484908f472c8fe2e8ef499facee54a0a6978be0e0cff67b1254fd747", + "sha256:0ccaa1bc98751fbfcf53dc8dfdb90d96e98838010fc254180dd6707a6e8bb179", + "sha256:0d3105efab7c5c091609abacad33afff33bdff0035bece164c98bcf5a85ef90a", + "sha256:0e1af74a9529a1137c67c887ed9cde62cff53aa4d84a3adbec329f9ec47a3936", + "sha256:136f9db0f53c0206db38b8cd0c985c78ded5fd596c9a86ce5c0b92afb91c3a19", + "sha256:156ececdf636143f508770bf8a3a0498de64da5abd890c7dbb42ca9e3b6c05b8", + "sha256:15c87339490100c63472a76d87fe7097a0835c705eb5ae79fd96e343473629ed", + "sha256:1695497bb2a02a6de60064c9f077a4ae9c25c73624e0d43e3aa9d16d983073c2", + "sha256:173563f3696124372831007e3d4b9821746964a95968628f7075d9231ac6bb33", + "sha256:173866d9f7409c0fb514cf6e78952e65816600cb888c68b37b41147349fe0057", + "sha256:23ec1d3c31882b2a8a69c801ef58ebf7bae2553211ebbddf04235be275a38548", + "sha256:243fbbbf003754fe41b5bdf10ce1e7f80bcc70732b5b54222c124d6b4c2ab31c", + "sha256:28c6cf1d92edf936ceedc7afa61b07e9d78a27b15244aa46bbcd534c7458ee1b", + "sha256:2aa738e0282be54eede1e3f36b81f1e46aee7ec7602aa563e81e0e8d7b67963f", + "sha256:2cf441c4b6e538ba0d2591574f95d3fdd33f1efafa864faa077d9636ecc0c4e9", + "sha256:30c3ff305f6e06650a761c4393666f77384f1cc6c5c0251965d6bfa5fbc88f7f", + "sha256:31561a5b4d8dbef1559b3600b045607cf804bae040f64b5f5bca77da38084a8a", + "sha256:32b66be100ac5739065496c74c4b7f3015cef792c3174982809274d7e51b3e04", + "sha256:3433da95b51a75692dcf6cc8117a31410447c75a9a8187888f02ad45c0a86c50", + "sha256:34a2d76a1984cac04ff8b1bfc939ec9dc0914821264d4a9c8fd0ed6aa8d4cfd2", + "sha256:353665775be69bbfc6d54c8d134bfc533e332149faeddd631b0bc79df0897f46", + "sha256:38d0124fa992dbacd0c48b1b755d3ee0a9f924f427f95b0ef376556a24debf01", + "sha256:3c56ec1eacd0a5d35b8a29f468659c47f4fe61b2cab948ca756c39b7617f0aa5", + "sha256:3db817b4e95eb05c362e3b45dafe7144b18603e1211f4a5b36eb9522ecc62bcf", + "sha256:3e52474256a7db9dcf3c5f4ca0b300fdea6c21cca0148c8891d03a025649d935", + "sha256:416f2e3beaeae81e2f7a45dc711258be5bdc79c940a9a270b266c0bec038fb84", + "sha256:435aca062444a7f0c884861d2e3ea79883bd1cd19d0a381928b69ae1b85bc51d", + "sha256:4388c72174868884f76affcdd3656544c426407e0043c89b684d22fb265e04a5", + "sha256:43ebdcc120e2ca679dba01a779333a8ea76b50547b55e812b8b92818d604662c", + "sha256:458c0c65802d816a6b955cf3603186de79e8fdb46d4f19abaec4ef0a906f50a7", + "sha256:533a28754e7f7439f217550a497bb026c54072dbe16402b183fdbca2431935a9", + "sha256:553dad9af802a9ad1a6525e7528152a015b85fb8dbf764ebfc755c695f488367", + "sha256:5838f2b79dc8f96fdc44077c9e4e2e33d7089b10788464609df788eb97d03aad", + "sha256:5b48388ded01f6f2429a8c55012bdbd1c2a0c3735b3e73e221649e524c34a58d", + "sha256:5bc0df728e4def5e15a754521e8882ba5a5121bd6b5a3a0ff7efda5d6558ab3d", + "sha256:63eab904f8630aed5a68f2d0aeab565dcfc595dc1bf0b91b71d9ddd43dea3aea", + "sha256:66f629632220a4e7858b58e4857927dd01a850a4cef2fb4044c8662787165cf7", + "sha256:670eb11325ed3a6209339974b276811867defe52f4188fe18dc49855774fa9cf", + "sha256:69d5856d526802cbda768d3e6246cd0d77450fa2a4bc2ea0ea14f0d972c2894b", + "sha256:6e840553c9c494a35e449a987ca2c4f8372668ee954a03a9a9685075228e5036", + "sha256:711bdfae4e699a6d4f371137cbe9e740dc958530cb920eb6f43ff9551e17cfbc", + "sha256:74abb8709ea54cc483c4fb57fb17bb66f8e0f04438cff6ded322074dbd17c7ec", + "sha256:75119badf45f7183e10e348edff5a76a94dc19ba9287d94001ff05e81475967b", + "sha256:766dcc00b943c089349d4060b935c76281f6be225e39994c2ccec3a2a36ad627", + "sha256:78e6fdc976ec966b99e4daa3812fac0274cc28cd2b24b0d92462e2e5ef90d368", + "sha256:81dadafb3aa124f86dc267a2168f71bbd2bfb163663661ab0038f6e4b8edb810", + "sha256:82d5161e8cb8f36ec778fd7ac4d740415d84030f5b9ef8fe4da54784a1f46c94", + "sha256:833547179c31f9bec39b49601d282d6f0ea1633620701288934c5f66d88c3e50", + "sha256:856b7f1a7b98a8c31823285786bd566cf06226ac4f38b3ef462f593c608a9bd6", + "sha256:8657d3f37f781d987037f9cc20bbc8b40425fa14380c87da0cb8dfce7c92d0fb", + "sha256:93bed8a8084544c6efe8856c362af08a23e959340c87a95687fdbe9c9f280c8b", + "sha256:954dde77c404084c2544e572f342aef384240b3e434e06cecc71597e95fd1ce7", + "sha256:98f68df80ec6ca3015186b2677c208c096d646ef37bbf8b49764ab4a38183931", + "sha256:99e12d2bf587b44deb74e0d6170fec37adb489964dbca656ec41a7cd8f2ff178", + "sha256:9a13a07532e8e1c4a5a3afff0ca4553da23409fad65def1b71186fb867eeae8d", + "sha256:9c1e3ff4b89cdd2e1a24c214f141e848b9e0451f08d7d4963cb4108d4d798f1f", + "sha256:9ce2e0f6123a60bd1a7f5ae3b2c49b240c12c132847f17aa990b841a417598a2", + "sha256:9fcda20b2de7042cc35cf911702fa3d8311bd40055a14446c1e62403684afdc5", + "sha256:a32d58f4b521bb98b2c0aa9da407f8bd57ca81f34362bcb090e4a79e9924fefc", + "sha256:a39c36f4218a5bb668b4f06874d676d35a035ee668e6e7e3538835c703634b84", + "sha256:a5cafb02cf097a82d74403f7e0b6b9df3ffbfe8edf9415ea816314711764a27b", + "sha256:a7cf963a357c5f00cb55b1955df8bbe68d2f2f65de065160a1c26b85a1e44172", + "sha256:a880372e2e5dbb9258a4e8ff43f13888039abb9dd6d515f28611c54361bc5644", + "sha256:ace4cad790f3bf872c082366c9edd7f8f8f77afe3992b134cfc810332206884f", + "sha256:af8ff8d7dc07ce873f643de6dfbcd45dc3db2c87462e5c387267197f59e6d776", + "sha256:b47a6000a7e833ebfe5886b56a31cb2ff12120b1efd4578a6fcc38df16cc77bd", + "sha256:b71862a652f50babab4a43a487f157d26b464b1dedbcc0afda02fd64f3809d04", + "sha256:b7f227ca6db5a9fda0a2b935a2ea34a7267589ffc63c8045f0e4edb8d8dcf956", + "sha256:bc8936d06cd53fddd4892677d65e98af514c8d78c79864f418bbf78a4a2edde4", + "sha256:bed1b5dbf90bad3bfc19439258c97873eab453c71d8b6869c136346acfe497e7", + "sha256:c45817e3e6972109d1a2c65091504a537e257bc3c885b4e78a95baa96df6a3f8", + "sha256:c68e820879ff39992c7f148113b46efcd6ec765a4865581f2902b3c43a5f4bbb", + "sha256:c77494a2f2282d9bbbbcab7c227a4d1b4bb829875c96251f66fb5f3bae4fb053", + "sha256:c998d0558805860503bc3a595994895ca0f7835e00668dadc673bbf7f5fbfcbe", + "sha256:ccad2800dfdff34392448c4bf834be124f10a5bc102f254521d931c1c53c455a", + "sha256:cd126498171f752dd85737ab1544329a4520c53eed3997f9b08aefbafb1cc53b", + "sha256:ce44217ad99ffad8027d2fde0269ae368c86db66ea0571c62a000798d69401fb", + "sha256:d1ac2bc069f4a458634c26b101c2341b18da85cb96afe0015990507efec2e417", + "sha256:d417a4f6943112fae3924bae2af7112562285848d9bcee737fc4ff7cbd450e6c", + "sha256:d538df442c0d9665664ab6dd5fccd0110fa3b364914f9c85b3ef9b7b2e157980", + "sha256:ded1b1803151dd0f20a8945508786d57c2f97a50289b16f2629f85433e546d47", + "sha256:e2e93b88ecc8f74074012e18d679fb2e9c746f2a56f79cd5e2b1afcf2a8a786b", + "sha256:e4ca3b9f370f218cc2a0309542cab8d0acdfd66667e7c37d04d617012485f904", + "sha256:e4ee8b8639070ff246ad3649294336b06db37a94bdea0d09ea491603e0be73b8", + "sha256:e52f77a0cd246086afde8815039f3e16f8d2be51786c0a39b57104c563c5cbb0", + "sha256:eaea112aed589131f73d50d570a6864728bd7c0c66ef6c9154ed7b59f24da611", + "sha256:ed20a4bdc635f36cb19e630bfc644181dd075839b6fc84cac51c0f381ac472e2", + "sha256:eedc3f247ee7b3808ea07205f3e7d7879bc19ad3e6222195cd5fbf9988853e4d", + "sha256:f0e1844ad47c7bd5d6fa784f1d4accc5f4168b48999303a868fe0f8597bde715", + "sha256:f4fe99ce44128c71233d0d72152db31ca119711dfc5f2c82385ad611d8d7f897", + "sha256:f8cfd847e6b9ecf9f2f2531c8427035f291ec286c0a4944b0a9fce58c6446046", + "sha256:f9ca0e6ce7774dc7830dc0cc4bb6b3eec769db667f230e7c770a628c1aa5681b", + "sha256:fa2bea05ff0a8fb4d8124498e00e02398f06d23cdadd0fe027d84a3f7afde31e", + "sha256:fbbb63bed5fcd70cd3dd23a087cd78e4675fb5a2963b8af53f945cbbca79ae16", + "sha256:fbda058a9a68bec347962595f50546a8a4a34fd7b0654a7b9697917dc2bf810d", + "sha256:ffd591e22b22f9cb48e472529db6a47203c41c2c5911ff0a52e85723196c0d75" + ], + "markers": "python_version >= '3.8'", + "version": "==1.15.2" }, "zipp": { "hashes": [ - "sha256:9960cd8967c8f85a56f920d5d507274e74f9ff813a0ab8889a5b5be2daf44064", - "sha256:c22b14cc4763c5a5b04134207736c107db42e9d3ef2d9779d465f5f1bcba572b" + "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350", + "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29" ], "markers": "python_version >= '3.8'", - "version": "==3.20.1" + "version": "==3.20.2" } }, "develop": { @@ -2597,11 +2728,11 @@ }, "cattrs": { "hashes": [ - "sha256:16e94a13f9aaf6438bd5be5df521e072b1b00481b4cf807bcb1acbd49f814c08", - "sha256:ec8ce8fdc725de9d07547cd616f968670687c6fa7a2e263b088370c46d834d97" + "sha256:67c7495b760168d931a10233f979b28dc04daf853b30752246f4f8471c6d68d0", + "sha256:8028cfe1ff5382df59dd36474a86e02d817b06eaf8af84555441bac915d2ef85" ], "markers": "python_version >= '3.8'", - "version": "==24.1.1" + "version": "==24.1.2" }, "certifi": { "hashes": [ @@ -2621,99 +2752,114 @@ }, "charset-normalizer": { "hashes": [ - "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027", - "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087", - "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786", - "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8", - "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09", - "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185", - "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574", - "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e", - "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519", - "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898", - "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269", - "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3", - "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f", - "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6", - "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8", - "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a", - "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73", - "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc", - "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714", - "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2", - "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc", - "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce", - "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d", - "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e", - "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6", - "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269", - "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96", - "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d", - "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a", - "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4", - "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77", - "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d", - "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0", - "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed", - "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068", - "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac", - "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25", - "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8", - "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab", - "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26", - "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2", - "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db", - "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f", - "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5", - "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99", - "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c", - "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d", - "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811", - "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa", - "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a", - "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03", - "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b", - "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04", - "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c", - "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001", - "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458", - "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389", - "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99", - "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985", - "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537", - "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238", - "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f", - "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d", - "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796", - "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a", - "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143", - "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8", - "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c", - "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5", - "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5", - "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711", - "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4", - "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6", - "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c", - "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7", - "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4", - "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b", - "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae", - "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12", - "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c", - "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae", - "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8", - "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887", - "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b", - "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4", - "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f", - "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5", - "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33", - "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519", - "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561" + "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621", + "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6", + "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8", + "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912", + "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c", + "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b", + "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d", + "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d", + "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95", + "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e", + "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565", + "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64", + "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab", + "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be", + "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e", + "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907", + "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0", + "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2", + "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62", + "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62", + "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23", + "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc", + "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284", + "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca", + "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455", + "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858", + "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b", + "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594", + "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc", + "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db", + "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b", + "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea", + "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6", + "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920", + "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749", + "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7", + "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd", + "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99", + "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242", + "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee", + "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129", + "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2", + "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51", + "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee", + "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8", + "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b", + "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613", + "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742", + "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe", + "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3", + "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5", + "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631", + "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7", + "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15", + "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c", + "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea", + "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417", + "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250", + "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88", + "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca", + "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa", + "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99", + "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149", + "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41", + "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574", + "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0", + "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f", + "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d", + "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654", + "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3", + "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19", + "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90", + "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578", + "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9", + "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1", + "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51", + "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719", + "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236", + "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a", + "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c", + "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade", + "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944", + "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc", + "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6", + "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6", + "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27", + "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6", + "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2", + "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12", + "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf", + "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114", + "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7", + "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf", + "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d", + "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b", + "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed", + "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03", + "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4", + "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67", + "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365", + "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a", + "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748", + "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b", + "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079", + "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482" ], "markers": "python_full_version >= '3.7.0'", - "version": "==3.3.2" + "version": "==3.4.0" }, "ci-info": { "hashes": [ @@ -2736,96 +2882,86 @@ "toml" ], "hashes": [ - "sha256:06a737c882bd26d0d6ee7269b20b12f14a8704807a01056c80bb881a4b2ce6ca", - "sha256:07e2ca0ad381b91350c0ed49d52699b625aab2b44b65e1b4e02fa9df0e92ad2d", - "sha256:0c0420b573964c760df9e9e86d1a9a622d0d27f417e1a949a8a66dd7bcee7bc6", - "sha256:0dbde0f4aa9a16fa4d754356a8f2e36296ff4d83994b2c9d8398aa32f222f989", - "sha256:1125ca0e5fd475cbbba3bb67ae20bd2c23a98fac4e32412883f9bcbaa81c314c", - "sha256:13b0a73a0896988f053e4fbb7de6d93388e6dd292b0d87ee51d106f2c11b465b", - "sha256:166811d20dfea725e2e4baa71fffd6c968a958577848d2131f39b60043400223", - "sha256:170d444ab405852903b7d04ea9ae9b98f98ab6d7e63e1115e82620807519797f", - "sha256:1f4aa8219db826ce6be7099d559f8ec311549bfc4046f7f9fe9b5cea5c581c56", - "sha256:225667980479a17db1048cb2bf8bfb39b8e5be8f164b8f6628b64f78a72cf9d3", - "sha256:260933720fdcd75340e7dbe9060655aff3af1f0c5d20f46b57f262ab6c86a5e8", - "sha256:2bdb062ea438f22d99cba0d7829c2ef0af1d768d1e4a4f528087224c90b132cb", - "sha256:2c09f4ce52cb99dd7505cd0fc8e0e37c77b87f46bc9c1eb03fe3bc9991085388", - "sha256:3115a95daa9bdba70aea750db7b96b37259a81a709223c8448fa97727d546fe0", - "sha256:3e0cadcf6733c09154b461f1ca72d5416635e5e4ec4e536192180d34ec160f8a", - "sha256:3f1156e3e8f2872197af3840d8ad307a9dd18e615dc64d9ee41696f287c57ad8", - "sha256:4421712dbfc5562150f7554f13dde997a2e932a6b5f352edcce948a815efee6f", - "sha256:44df346d5215a8c0e360307d46ffaabe0f5d3502c8a1cefd700b34baf31d411a", - "sha256:502753043567491d3ff6d08629270127e0c31d4184c4c8d98f92c26f65019962", - "sha256:547f45fa1a93154bd82050a7f3cddbc1a7a4dd2a9bf5cb7d06f4ae29fe94eaf8", - "sha256:5621a9175cf9d0b0c84c2ef2b12e9f5f5071357c4d2ea6ca1cf01814f45d2391", - "sha256:609b06f178fe8e9f89ef676532760ec0b4deea15e9969bf754b37f7c40326dbc", - "sha256:645786266c8f18a931b65bfcefdbf6952dd0dea98feee39bd188607a9d307ed2", - "sha256:6878ef48d4227aace338d88c48738a4258213cd7b74fd9a3d4d7582bb1d8a155", - "sha256:6a89ecca80709d4076b95f89f308544ec8f7b4727e8a547913a35f16717856cb", - "sha256:6db04803b6c7291985a761004e9060b2bca08da6d04f26a7f2294b8623a0c1a0", - "sha256:6e2cd258d7d927d09493c8df1ce9174ad01b381d4729a9d8d4e38670ca24774c", - "sha256:6e81d7a3e58882450ec4186ca59a3f20a5d4440f25b1cff6f0902ad890e6748a", - "sha256:702855feff378050ae4f741045e19a32d57d19f3e0676d589df0575008ea5004", - "sha256:78b260de9790fd81e69401c2dc8b17da47c8038176a79092a89cb2b7d945d060", - "sha256:7bb65125fcbef8d989fa1dd0e8a060999497629ca5b0efbca209588a73356232", - "sha256:7dea0889685db8550f839fa202744652e87c60015029ce3f60e006f8c4462c93", - "sha256:8284cf8c0dd272a247bc154eb6c95548722dce90d098c17a883ed36e67cdb129", - "sha256:877abb17e6339d96bf08e7a622d05095e72b71f8afd8a9fefc82cf30ed944163", - "sha256:8929543a7192c13d177b770008bc4e8119f2e1f881d563fc6b6305d2d0ebe9de", - "sha256:8ae539519c4c040c5ffd0632784e21b2f03fc1340752af711f33e5be83a9d6c6", - "sha256:8f59d57baca39b32db42b83b2a7ba6f47ad9c394ec2076b084c3f029b7afca23", - "sha256:9054a0754de38d9dbd01a46621636689124d666bad1936d76c0341f7d71bf569", - "sha256:953510dfb7b12ab69d20135a0662397f077c59b1e6379a768e97c59d852ee51d", - "sha256:95cae0efeb032af8458fc27d191f85d1717b1d4e49f7cb226cf526ff28179778", - "sha256:9bc572be474cafb617672c43fe989d6e48d3c83af02ce8de73fff1c6bb3c198d", - "sha256:9c56863d44bd1c4fe2abb8a4d6f5371d197f1ac0ebdee542f07f35895fc07f36", - "sha256:9e0b2df163b8ed01d515807af24f63de04bebcecbd6c3bfeff88385789fdf75a", - "sha256:a09ece4a69cf399510c8ab25e0950d9cf2b42f7b3cb0374f95d2e2ff594478a6", - "sha256:a1ac0ae2b8bd743b88ed0502544847c3053d7171a3cff9228af618a068ed9c34", - "sha256:a318d68e92e80af8b00fa99609796fdbcdfef3629c77c6283566c6f02c6d6704", - "sha256:a4acd025ecc06185ba2b801f2de85546e0b8ac787cf9d3b06e7e2a69f925b106", - "sha256:a6d3adcf24b624a7b778533480e32434a39ad8fa30c315208f6d3e5542aeb6e9", - "sha256:a78d169acd38300060b28d600344a803628c3fd585c912cacc9ea8790fe96862", - "sha256:a95324a9de9650a729239daea117df21f4b9868ce32e63f8b650ebe6cef5595b", - "sha256:abd5fd0db5f4dc9289408aaf34908072f805ff7792632250dcb36dc591d24255", - "sha256:b06079abebbc0e89e6163b8e8f0e16270124c154dc6e4a47b413dd538859af16", - "sha256:b43c03669dc4618ec25270b06ecd3ee4fa94c7f9b3c14bae6571ca00ef98b0d3", - "sha256:b48f312cca9621272ae49008c7f613337c53fadca647d6384cc129d2996d1133", - "sha256:b5d7b556859dd85f3a541db6a4e0167b86e7273e1cdc973e5b175166bb634fdb", - "sha256:b9f222de8cded79c49bf184bdbc06630d4c58eec9459b939b4a690c82ed05657", - "sha256:c3c02d12f837d9683e5ab2f3d9844dc57655b92c74e286c262e0fc54213c216d", - "sha256:c44fee9975f04b33331cb8eb272827111efc8930cfd582e0320613263ca849ca", - "sha256:cf4b19715bccd7ee27b6b120e7e9dd56037b9c0681dcc1adc9ba9db3d417fa36", - "sha256:d0c212c49b6c10e6951362f7c6df3329f04c2b1c28499563d4035d964ab8e08c", - "sha256:d3296782ca4eab572a1a4eca686d8bfb00226300dcefdf43faa25b5242ab8a3e", - "sha256:d85f5e9a5f8b73e2350097c3756ef7e785f55bd71205defa0bfdaf96c31616ff", - "sha256:da511e6ad4f7323ee5702e6633085fb76c2f893aaf8ce4c51a0ba4fc07580ea7", - "sha256:e05882b70b87a18d937ca6768ff33cc3f72847cbc4de4491c8e73880766718e5", - "sha256:e61c0abb4c85b095a784ef23fdd4aede7a2628478e7baba7c5e3deba61070a02", - "sha256:e6a08c0be454c3b3beb105c0596ebdc2371fab6bb90c0c0297f4e58fd7e1012c", - "sha256:e9a6e0eb86070e8ccaedfbd9d38fec54864f3125ab95419970575b42af7541df", - "sha256:ed37bd3c3b063412f7620464a9ac1314d33100329f39799255fb8d3027da50d3", - "sha256:f1adfc8ac319e1a348af294106bc6a8458a0f1633cc62a1446aebc30c5fa186a", - "sha256:f5796e664fe802da4f57a168c85359a8fbf3eab5e55cd4e4569fbacecc903959", - "sha256:fc5a77d0c516700ebad189b587de289a20a78324bc54baee03dd486f0855d234", - "sha256:fd21f6ae3f08b41004dfb433fa895d858f3f5979e7762d052b12aef444e29afc" - ], - "markers": "python_version >= '3.8'", - "version": "==7.6.1" + "sha256:04f2189716e85ec9192df307f7c255f90e78b6e9863a03223c3b998d24a3c6c6", + "sha256:0c6c0f4d53ef603397fc894a895b960ecd7d44c727df42a8d500031716d4e8d2", + "sha256:0ca37993206402c6c35dc717f90d4c8f53568a8b80f0bf1a1b2b334f4d488fba", + "sha256:12f9515d875859faedb4144fd38694a761cd2a61ef9603bf887b13956d0bbfbb", + "sha256:1990b1f4e2c402beb317840030bb9f1b6a363f86e14e21b4212e618acdfce7f6", + "sha256:2341a78ae3a5ed454d524206a3fcb3cec408c2a0c7c2752cd78b606a2ff15af4", + "sha256:23bb63ae3f4c645d2d82fa22697364b0046fbafb6261b258a58587441c5f7bd0", + "sha256:27bd5f18d8f2879e45724b0ce74f61811639a846ff0e5c0395b7818fae87aec6", + "sha256:2dc7d6b380ca76f5e817ac9eef0c3686e7834c8346bef30b041a4ad286449990", + "sha256:331b200ad03dbaa44151d74daeb7da2cf382db424ab923574f6ecca7d3b30de3", + "sha256:365defc257c687ce3e7d275f39738dcd230777424117a6c76043459db131dd43", + "sha256:37be7b5ea3ff5b7c4a9db16074dc94523b5f10dd1f3b362a827af66a55198175", + "sha256:3c2e6fa98032fec8282f6b27e3f3986c6e05702828380618776ad794e938f53a", + "sha256:40e8b1983080439d4802d80b951f4a93d991ef3261f69e81095a66f86cf3c3c6", + "sha256:43517e1f6b19f610a93d8227e47790722c8bf7422e46b365e0469fc3d3563d97", + "sha256:43b32a06c47539fe275106b376658638b418c7cfdfff0e0259fbf877e845f14b", + "sha256:43d6a66e33b1455b98fc7312b124296dad97a2e191c80320587234a77b1b736e", + "sha256:4c59d6a4a4633fad297f943c03d0d2569867bd5372eb5684befdff8df8522e39", + "sha256:52ac29cc72ee7e25ace7807249638f94c9b6a862c56b1df015d2b2e388e51dbd", + "sha256:54356a76b67cf8a3085818026bb556545ebb8353951923b88292556dfa9f812d", + "sha256:583049c63106c0555e3ae3931edab5669668bbef84c15861421b94e121878d3f", + "sha256:6d99198203f0b9cb0b5d1c0393859555bc26b548223a769baf7e321a627ed4fc", + "sha256:6da42bbcec130b188169107ecb6ee7bd7b4c849d24c9370a0c884cf728d8e976", + "sha256:6e484e479860e00da1f005cd19d1c5d4a813324e5951319ac3f3eefb497cc549", + "sha256:70a6756ce66cd6fe8486c775b30889f0dc4cb20c157aa8c35b45fd7868255c5c", + "sha256:70d24936ca6c15a3bbc91ee9c7fc661132c6f4c9d42a23b31b6686c05073bde5", + "sha256:71967c35828c9ff94e8c7d405469a1fb68257f686bca7c1ed85ed34e7c2529c4", + "sha256:79644f68a6ff23b251cae1c82b01a0b51bc40c8468ca9585c6c4b1aeee570e0b", + "sha256:87cd2e29067ea397a47e352efb13f976eb1b03e18c999270bb50589323294c6e", + "sha256:8d4c6ea0f498c7c79111033a290d060c517853a7bcb2f46516f591dab628ddd3", + "sha256:9134032f5aa445ae591c2ba6991d10136a1f533b1d2fa8f8c21126468c5025c6", + "sha256:921fbe13492caf6a69528f09d5d7c7d518c8d0e7b9f6701b7719715f29a71e6e", + "sha256:99670790f21a96665a35849990b1df447993880bb6463a0a1d757897f30da929", + "sha256:9975442f2e7a5cfcf87299c26b5a45266ab0696348420049b9b94b2ad3d40234", + "sha256:99ded130555c021d99729fabd4ddb91a6f4cc0707df4b1daf912c7850c373b13", + "sha256:a3328c3e64ea4ab12b85999eb0779e6139295bbf5485f69d42cf794309e3d007", + "sha256:a4fb91d5f72b7e06a14ff4ae5be625a81cd7e5f869d7a54578fc271d08d58ae3", + "sha256:aa23ce39661a3e90eea5f99ec59b763b7d655c2cada10729ed920a38bfc2b167", + "sha256:aac7501ae73d4a02f4b7ac8fcb9dc55342ca98ffb9ed9f2dfb8a25d53eda0e4d", + "sha256:ab84a8b698ad5a6c365b08061920138e7a7dd9a04b6feb09ba1bfae68346ce6d", + "sha256:b4adeb878a374126f1e5cf03b87f66279f479e01af0e9a654cf6d1509af46c40", + "sha256:b9853509b4bf57ba7b1f99b9d866c422c9c5248799ab20e652bbb8a184a38181", + "sha256:bb7d5fe92bd0dc235f63ebe9f8c6e0884f7360f88f3411bfed1350c872ef2054", + "sha256:bca4c8abc50d38f9773c1ec80d43f3768df2e8576807d1656016b9d3eeaa96fd", + "sha256:c222958f59b0ae091f4535851cbb24eb57fc0baea07ba675af718fb5302dddb2", + "sha256:c30e42ea11badb147f0d2e387115b15e2bd8205a5ad70d6ad79cf37f6ac08c91", + "sha256:c3a79f56dee9136084cf84a6c7c4341427ef36e05ae6415bf7d787c96ff5eaa3", + "sha256:c51ef82302386d686feea1c44dbeef744585da16fcf97deea2a8d6c1556f519b", + "sha256:c77326300b839c44c3e5a8fe26c15b7e87b2f32dfd2fc9fee1d13604347c9b38", + "sha256:d33a785ea8354c480515e781554d3be582a86297e41ccbea627a5c632647f2cd", + "sha256:d546cfa78844b8b9c1c0533de1851569a13f87449897bbc95d698d1d3cb2a30f", + "sha256:da29ceabe3025a1e5a5aeeb331c5b1af686daab4ff0fb4f83df18b1180ea83e2", + "sha256:df8c05a0f574d480947cba11b947dc41b1265d721c3777881da2fb8d3a1ddfba", + "sha256:e266af4da2c1a4cbc6135a570c64577fd3e6eb204607eaff99d8e9b710003c6f", + "sha256:e279f3db904e3b55f520f11f983cc8dc8a4ce9b65f11692d4718ed021ec58b83", + "sha256:ea52bd218d4ba260399a8ae4bb6b577d82adfc4518b93566ce1fddd4a49d1dce", + "sha256:ebec65f5068e7df2d49466aab9128510c4867e532e07cb6960075b27658dca38", + "sha256:ec1e3b40b82236d100d259854840555469fad4db64f669ab817279eb95cd535c", + "sha256:ee77c7bef0724165e795b6b7bf9c4c22a9b8468a6bdb9c6b4281293c6b22a90f", + "sha256:f263b18692f8ed52c8de7f40a0751e79015983dbd77b16906e5b310a39d3ca21", + "sha256:f7b26757b22faf88fcf232f5f0e62f6e0fd9e22a8a5d0d5016888cdfe1f6c1c4", + "sha256:f7ddb920106bbbbcaf2a274d56f46956bf56ecbde210d88061824a95bdd94e92" + ], + "markers": "python_version >= '3.9'", + "version": "==7.6.3" }, "decorator": { "hashes": [ "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330", "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186" ], - "markers": "python_version < '3.11' and python_version >= '3.7'", + "markers": "python_version >= '3.11'", "version": "==5.1.1" }, "distlib": { "hashes": [ - "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784", - "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64" + "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87", + "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403" ], - "version": "==0.3.8" + "version": "==0.3.9" }, "etelemetry": { "hashes": [ @@ -2834,14 +2970,6 @@ "markers": "python_version >= '3.7'", "version": "==0.3.1" }, - "exceptiongroup": { - "hashes": [ - "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", - "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc" - ], - "markers": "python_version < '3.11'", - "version": "==1.2.2" - }, "executing": { "hashes": [ "sha256:8d63781349375b5ebccc3142f4b30350c0cd9c79f921cde38be2be4637e98eaf", @@ -2852,58 +2980,64 @@ }, "faker": { "hashes": [ - "sha256:4294d169255a045990720d6f3fa4134b764a4cdf46ef0d3c7553d2506f1adaa1", - "sha256:e59c01d1e8b8e20a83255ab8232c143cb2af3b4f5ab6a3f5ce495f385ad8ab4c" + "sha256:6fd328db7195e70cdee479ee687fef6623c9b57b8023c582adbe88a01dc54297", + "sha256:b6c2d61861dcf1084b8e10959418fe3380a1a3dcd2796a73d43f738a42aabb4c" ], "markers": "python_version >= '3.8'", - "version": "==28.4.1" + "version": "==30.4.0" }, "filelock": { "hashes": [ - "sha256:81de9eb8453c769b63369f87f11131a7ab04e367f8d97ad39dc230daa07e3bec", - "sha256:f6ed4c963184f4c84dd5557ce8fece759a3724b37b80c6c4f20a2f63a4dc6609" + "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0", + "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435" ], "markers": "python_version >= '3.8'", - "version": "==3.16.0" + "version": "==3.16.1" }, "frozendict": { "hashes": [ - "sha256:07c3a5dee8bbb84cba770e273cdbf2c87c8e035903af8f781292d72583416801", - "sha256:12a342e439aef28ccec533f0253ea53d75fe9102bd6ea928ff530e76eac38906", - "sha256:1697793b5f62b416c0fc1d94638ec91ed3aa4ab277f6affa3a95216ecb3af170", - "sha256:199a4d32194f3afed6258de7e317054155bc9519252b568d9cfffde7e4d834e5", - "sha256:259528ba6b56fa051bc996f1c4d8b57e30d6dd3bc2f27441891b04babc4b5e73", - "sha256:2b70b431e3a72d410a2cdf1497b3aba2f553635e0c0f657ce311d841bf8273b6", - "sha256:2bd009cf4fc47972838a91e9b83654dc9a095dc4f2bb3a37c3f3124c8a364543", - "sha256:2d8536e068d6bf281f23fa835ac07747fb0f8851879dd189e9709f9567408b4d", - "sha256:3148062675536724502c6344d7c485dd4667fdf7980ca9bd05e338ccc0c4471e", - "sha256:3f7c031b26e4ee6a3f786ceb5e3abf1181c4ade92dce1f847da26ea2c96008c7", - "sha256:4297d694eb600efa429769125a6f910ec02b85606f22f178bafbee309e7d3ec7", - "sha256:4a59578d47b3949437519b5c39a016a6116b9e787bb19289e333faae81462e59", - "sha256:4ae8d05c8d0b6134bfb6bfb369d5fa0c4df21eabb5ca7f645af95fdc6689678e", - "sha256:5d58d9a8d9e49662c6dafbea5e641f97decdb3d6ccd76e55e79818415362ba25", - "sha256:63aa49f1919af7d45fb8fd5dec4c0859bc09f46880bd6297c79bb2db2969b63d", - "sha256:6874fec816b37b6eb5795b00e0574cba261bf59723e2de607a195d5edaff0786", - "sha256:6eb716e6a6d693c03b1d53280a1947716129f5ef9bcdd061db5c17dea44b80fe", - "sha256:705efca8d74d3facbb6ace80ab3afdd28eb8a237bfb4063ed89996b024bc443d", - "sha256:78c94991944dd33c5376f720228e5b252ee67faf3bac50ef381adc9e51e90d9d", - "sha256:7f79c26dff10ce11dad3b3627c89bb2e87b9dd5958c2b24325f16a23019b8b94", - "sha256:7fee9420475bb6ff357000092aa9990c2f6182b2bab15764330f4ad7de2eae49", - "sha256:812ab17522ba13637826e65454115a914c2da538356e85f43ecea069813e4b33", - "sha256:85375ec6e979e6373bffb4f54576a68bf7497c350861d20686ccae38aab69c0a", - "sha256:87ebcde21565a14fe039672c25550060d6f6d88cf1f339beac094c3b10004eb0", - "sha256:93a7b19afb429cbf99d56faf436b45ef2fa8fe9aca89c49eb1610c3bd85f1760", - "sha256:b3b967d5065872e27b06f785a80c0ed0a45d1f7c9b85223da05358e734d858ca", - "sha256:c6bf9260018d653f3cab9bd147bd8592bf98a5c6e338be0491ced3c196c034a3", - "sha256:c8f92425686323a950337da4b75b4c17a3327b831df8c881df24038d560640d4", - "sha256:d13b4310db337f4d2103867c5a05090b22bc4d50ca842093779ef541ea9c9eea", - "sha256:d9647563e76adb05b7cde2172403123380871360a114f546b4ae1704510801e5", - "sha256:dc2228874eacae390e63fd4f2bb513b3144066a977dc192163c9f6c7f6de6474", - "sha256:e1b941132d79ce72d562a13341d38fc217bc1ee24d8c35a20d754e79ff99e038", - "sha256:fefeb700bc7eb8b4c2dc48704e4221860d254c8989fb53488540bc44e44a1ac2" + "sha256:02331541611f3897f260900a1815b63389654951126e6e65545e529b63c08361", + "sha256:0aaa11e7c472150efe65adbcd6c17ac0f586896096ab3963775e1c5c58ac0098", + "sha256:18d50a2598350b89189da9150058191f55057581e40533e470db46c942373acf", + "sha256:1b4a3f8f6dd51bee74a50995c39b5a606b612847862203dd5483b9cd91b0d36a", + "sha256:1f42e6b75254ea2afe428ad6d095b62f95a7ae6d4f8272f0bd44a25dddd20f67", + "sha256:2d69418479bfb834ba75b0e764f058af46ceee3d655deb6a0dd0c0c1a5e82f09", + "sha256:323f1b674a2cc18f86ab81698e22aba8145d7a755e0ac2cccf142ee2db58620d", + "sha256:377a65be0a700188fc21e669c07de60f4f6d35fae8071c292b7df04776a1c27b", + "sha256:49344abe90fb75f0f9fdefe6d4ef6d4894e640fadab71f11009d52ad97f370b9", + "sha256:49ffaf09241bc1417daa19362a2241a4aa435f758fd4375c39ce9790443a39cd", + "sha256:622301b1c29c4f9bba633667d592a3a2b093cb408ba3ce578b8901ace3931ef3", + "sha256:665fad3f0f815aa41294e561d98dbedba4b483b3968e7e8cab7d728d64b96e33", + "sha256:669237c571856be575eca28a69e92a3d18f8490511eff184937283dc6093bd67", + "sha256:7088102345d1606450bd1801a61139bbaa2cb0d805b9b692f8d81918ea835da6", + "sha256:7134a2bb95d4a16556bb5f2b9736dceb6ea848fa5b6f3f6c2d6dba93b44b4757", + "sha256:7291abacf51798d5ffe632771a69c14fb423ab98d63c4ccd1aa382619afe2f89", + "sha256:74b6b26c15dddfefddeb89813e455b00ebf78d0a3662b89506b4d55c6445a9f4", + "sha256:7730f8ebe791d147a1586cbf6a42629351d4597773317002181b66a2da0d509e", + "sha256:807862e14b0e9665042458fde692c4431d660c4219b9bb240817f5b918182222", + "sha256:94321e646cc39bebc66954a31edd1847d3a2a3483cf52ff051cd0996e7db07db", + "sha256:9647c74efe3d845faa666d4853cfeabbaee403b53270cabfc635b321f770e6b8", + "sha256:9a8a43036754a941601635ea9c788ebd7a7efbed2becba01b54a887b41b175b9", + "sha256:a4e3737cb99ed03200cd303bdcd5514c9f34b29ee48f405c1184141bd68611c9", + "sha256:a76cee5c4be2a5d1ff063188232fffcce05dde6fd5edd6afe7b75b247526490e", + "sha256:b8f2829048f29fe115da4a60409be2130e69402e29029339663fac39c90e6e2b", + "sha256:ba5ef7328706db857a2bdb2c2a17b4cd37c32a19c017cff1bb7eeebc86b0f411", + "sha256:c131f10c4d3906866454c4e89b87a7e0027d533cce8f4652aa5255112c4d6677", + "sha256:c3a05c0a50cab96b4bb0ea25aa752efbfceed5ccb24c007612bc63e51299336f", + "sha256:c9905dcf7aa659e6a11b8051114c9fa76dfde3a6e50e6dc129d5aece75b449a2", + "sha256:ce1e9217b85eec6ba9560d520d5089c82dbb15f977906eb345d81459723dd7e3", + "sha256:d065db6a44db2e2375c23eac816f1a022feb2fa98cbb50df44a9e83700accbea", + "sha256:da6a10164c8a50b34b9ab508a9420df38f4edf286b9ca7b7df8a91767baecb34", + "sha256:df7cd16470fbd26fc4969a208efadc46319334eb97def1ddf48919b351192b8e", + "sha256:e72fb86e48811957d66ffb3e95580af7b1af1e6fbd760ad63d7bd79b2c9a07f8", + "sha256:eabd21d8e5db0c58b60d26b4bb9839cac13132e88277e1376970172a85ee04b3", + "sha256:eddabeb769fab1e122d3a6872982c78179b5bcc909fdc769f3cf1964f55a6d20", + "sha256:f4c789fd70879ccb6289a603cdebdc4953e7e5dea047d30c1b180529b28257b5", + "sha256:f5b94d5b07c00986f9e37a38dd83c13f5fe3bf3f1ccc8e88edea8fe15d6cd88c", + "sha256:fc67cbb3c96af7a798fab53d52589752c1673027e516b702ab355510ddf6bdff" ], "markers": "python_version >= '3.6'", - "version": "==2.4.4" + "version": "==2.4.6" }, "gevent": { "hashes": [ @@ -2955,99 +3089,104 @@ }, "greenlet": { "hashes": [ - "sha256:01059afb9b178606b4b6e92c3e710ea1635597c3537e44da69f4531e111dd5e9", - "sha256:037d9ac99540ace9424cb9ea89f0accfaff4316f149520b4ae293eebc5bded17", - "sha256:0e49a65d25d7350cca2da15aac31b6f67a43d867448babf997fe83c7505f57bc", - "sha256:13ff8c8e54a10472ce3b2a2da007f915175192f18e6495bad50486e87c7f6637", - "sha256:1544b8dd090b494c55e60c4ff46e238be44fdc472d2589e943c241e0169bcea2", - "sha256:184258372ae9e1e9bddce6f187967f2e08ecd16906557c4320e3ba88a93438c3", - "sha256:1ddc7bcedeb47187be74208bc652d63d6b20cb24f4e596bd356092d8000da6d6", - "sha256:221169d31cada333a0c7fd087b957c8f431c1dba202c3a58cf5a3583ed973e9b", - "sha256:243a223c96a4246f8a30ea470c440fe9db1f5e444941ee3c3cd79df119b8eebf", - "sha256:24fc216ec7c8be9becba8b64a98a78f9cd057fd2dc75ae952ca94ed8a893bf27", - "sha256:2651dfb006f391bcb240635079a68a261b227a10a08af6349cba834a2141efa1", - "sha256:26811df4dc81271033a7836bc20d12cd30938e6bd2e9437f56fa03da81b0f8fc", - "sha256:26d9c1c4f1748ccac0bae1dbb465fb1a795a75aba8af8ca871503019f4285e2a", - "sha256:28fe80a3eb673b2d5cc3b12eea468a5e5f4603c26aa34d88bf61bba82ceb2f9b", - "sha256:2cd8518eade968bc52262d8c46727cfc0826ff4d552cf0430b8d65aaf50bb91d", - "sha256:2d004db911ed7b6218ec5c5bfe4cf70ae8aa2223dffbb5b3c69e342bb253cb28", - "sha256:3d07c28b85b350564bdff9f51c1c5007dfb2f389385d1bc23288de51134ca303", - "sha256:3e7e6ef1737a819819b1163116ad4b48d06cfdd40352d813bb14436024fcda99", - "sha256:44151d7b81b9391ed759a2f2865bbe623ef00d648fed59363be2bbbd5154656f", - "sha256:44cd313629ded43bb3b98737bba2f3e2c2c8679b55ea29ed73daea6b755fe8e7", - "sha256:4a3dae7492d16e85ea6045fd11cb8e782b63eac8c8d520c3a92c02ac4573b0a6", - "sha256:4b5ea3664eed571779403858d7cd0a9b0ebf50d57d2cdeafc7748e09ef8cd81a", - "sha256:4c3446937be153718250fe421da548f973124189f18fe4575a0510b5c928f0cc", - "sha256:5415b9494ff6240b09af06b91a375731febe0090218e2898d2b85f9b92abcda0", - "sha256:5fd6e94593f6f9714dbad1aaba734b5ec04593374fa6638df61592055868f8b8", - "sha256:619935a44f414274a2c08c9e74611965650b730eb4efe4b2270f91df5e4adf9a", - "sha256:655b21ffd37a96b1e78cc48bf254f5ea4b5b85efaf9e9e2a526b3c9309d660ca", - "sha256:665b21e95bc0fce5cab03b2e1d90ba9c66c510f1bb5fdc864f3a377d0f553f6b", - "sha256:6a4bf607f690f7987ab3291406e012cd8591a4f77aa54f29b890f9c331e84989", - "sha256:6cea1cca3be76c9483282dc7760ea1cc08a6ecec1f0b6ca0a94ea0d17432da19", - "sha256:713d450cf8e61854de9420fb7eea8ad228df4e27e7d4ed465de98c955d2b3fa6", - "sha256:726377bd60081172685c0ff46afbc600d064f01053190e4450857483c4d44484", - "sha256:76b3e3976d2a452cba7aa9e453498ac72240d43030fdc6d538a72b87eaff52fd", - "sha256:76dc19e660baea5c38e949455c1181bc018893f25372d10ffe24b3ed7341fb25", - "sha256:76e5064fd8e94c3f74d9fd69b02d99e3cdb8fc286ed49a1f10b256e59d0d3a0b", - "sha256:7f346d24d74c00b6730440f5eb8ec3fe5774ca8d1c9574e8e57c8671bb51b910", - "sha256:81eeec4403a7d7684b5812a8aaa626fa23b7d0848edb3a28d2eb3220daddcbd0", - "sha256:90b5bbf05fe3d3ef697103850c2ce3374558f6fe40fd57c9fac1bf14903f50a5", - "sha256:9730929375021ec90f6447bff4f7f5508faef1c02f399a1953870cdb78e0c345", - "sha256:9eb4a1d7399b9f3c7ac68ae6baa6be5f9195d1d08c9ddc45ad559aa6b556bce6", - "sha256:a0409bc18a9f85321399c29baf93545152d74a49d92f2f55302f122007cfda00", - "sha256:a22f4e26400f7f48faef2d69c20dc055a1f3043d330923f9abe08ea0aecc44df", - "sha256:a53dfe8f82b715319e9953330fa5c8708b610d48b5c59f1316337302af5c0811", - "sha256:a771dc64fa44ebe58d65768d869fcfb9060169d203446c1d446e844b62bdfdca", - "sha256:a814dc3100e8a046ff48faeaa909e80cdb358411a3d6dd5293158425c684eda8", - "sha256:a8870983af660798dc1b529e1fd6f1cefd94e45135a32e58bd70edd694540f33", - "sha256:ac0adfdb3a21dc2a24ed728b61e72440d297d0fd3a577389df566651fcd08f97", - "sha256:b395121e9bbe8d02a750886f108d540abe66075e61e22f7353d9acb0b81be0f0", - "sha256:b9505a0c8579899057cbefd4ec34d865ab99852baf1ff33a9481eb3924e2da0b", - "sha256:c0a5b1c22c82831f56f2f7ad9bbe4948879762fe0d59833a4a71f16e5fa0f682", - "sha256:c3967dcc1cd2ea61b08b0b276659242cbce5caca39e7cbc02408222fb9e6ff39", - "sha256:c6f4c2027689093775fd58ca2388d58789009116844432d920e9147f91acbe64", - "sha256:c9d86401550b09a55410f32ceb5fe7efcd998bd2dad9e82521713cb148a4a15f", - "sha256:cd468ec62257bb4544989402b19d795d2305eccb06cde5da0eb739b63dc04665", - "sha256:cfcfb73aed40f550a57ea904629bdaf2e562c68fa1164fa4588e752af6efdc3f", - "sha256:d0dd943282231480aad5f50f89bdf26690c995e8ff555f26d8a5b9887b559bcc", - "sha256:d3c59a06c2c28a81a026ff11fbf012081ea34fb9b7052f2ed0366e14896f0a1d", - "sha256:d45b75b0f3fd8d99f62eb7908cfa6d727b7ed190737dec7fe46d993da550b81a", - "sha256:d46d5069e2eeda111d6f71970e341f4bd9aeeee92074e649ae263b834286ecc0", - "sha256:d58ec349e0c2c0bc6669bf2cd4982d2f93bf067860d23a0ea1fe677b0f0b1e09", - "sha256:db1b3ccb93488328c74e97ff888604a8b95ae4f35f4f56677ca57a4fc3a4220b", - "sha256:dd65695a8df1233309b701dec2539cc4b11e97d4fcc0f4185b4a12ce54db0491", - "sha256:f9482c2ed414781c0af0b35d9d575226da6b728bd1a720668fa05837184965b7", - "sha256:f9671e7282d8c6fcabc32c0fb8d7c0ea8894ae85cee89c9aadc2d7129e1a9954", - "sha256:fad7a051e07f64e297e6e8399b4d6a3bdcad3d7297409e9a06ef8cbccff4f501", - "sha256:ffb08f2a1e59d38c7b8b9ac8083c9c8b9875f0955b1e9b9b9a965607a51f8e54" - ], - "markers": "python_version >= '3.7'", - "version": "==3.1.0" + "sha256:0153404a4bb921f0ff1abeb5ce8a5131da56b953eda6e14b88dc6bbc04d2049e", + "sha256:03a088b9de532cbfe2ba2034b2b85e82df37874681e8c470d6fb2f8c04d7e4b7", + "sha256:04b013dc07c96f83134b1e99888e7a79979f1a247e2a9f59697fa14b5862ed01", + "sha256:05175c27cb459dcfc05d026c4232f9de8913ed006d42713cb8a5137bd49375f1", + "sha256:09fc016b73c94e98e29af67ab7b9a879c307c6731a2c9da0db5a7d9b7edd1159", + "sha256:0bbae94a29c9e5c7e4a2b7f0aae5c17e8e90acbfd3bf6270eeba60c39fce3563", + "sha256:0fde093fb93f35ca72a556cf72c92ea3ebfda3d79fc35bb19fbe685853869a83", + "sha256:1443279c19fca463fc33e65ef2a935a5b09bb90f978beab37729e1c3c6c25fe9", + "sha256:1776fd7f989fc6b8d8c8cb8da1f6b82c5814957264d1f6cf818d475ec2bf6395", + "sha256:1d3755bcb2e02de341c55b4fca7a745a24a9e7212ac953f6b3a48d117d7257aa", + "sha256:23f20bb60ae298d7d8656c6ec6db134bca379ecefadb0b19ce6f19d1f232a942", + "sha256:275f72decf9932639c1c6dd1013a1bc266438eb32710016a1c742df5da6e60a1", + "sha256:2846930c65b47d70b9d178e89c7e1a69c95c1f68ea5aa0a58646b7a96df12441", + "sha256:3319aa75e0e0639bc15ff54ca327e8dc7a6fe404003496e3c6925cd3142e0e22", + "sha256:346bed03fe47414091be4ad44786d1bd8bef0c3fcad6ed3dee074a032ab408a9", + "sha256:36b89d13c49216cadb828db8dfa6ce86bbbc476a82d3a6c397f0efae0525bdd0", + "sha256:37b9de5a96111fc15418819ab4c4432e4f3c2ede61e660b1e33971eba26ef9ba", + "sha256:396979749bd95f018296af156201d6211240e7a23090f50a8d5d18c370084dc3", + "sha256:3b2813dc3de8c1ee3f924e4d4227999285fd335d1bcc0d2be6dc3f1f6a318ec1", + "sha256:411f015496fec93c1c8cd4e5238da364e1da7a124bcb293f085bf2860c32c6f6", + "sha256:47da355d8687fd65240c364c90a31569a133b7b60de111c255ef5b606f2ae291", + "sha256:48ca08c771c268a768087b408658e216133aecd835c0ded47ce955381105ba39", + "sha256:4afe7ea89de619adc868e087b4d2359282058479d7cfb94970adf4b55284574d", + "sha256:4ce3ac6cdb6adf7946475d7ef31777c26d94bccc377e070a7986bd2d5c515467", + "sha256:4ead44c85f8ab905852d3de8d86f6f8baf77109f9da589cb4fa142bd3b57b475", + "sha256:54558ea205654b50c438029505def3834e80f0869a70fb15b871c29b4575ddef", + "sha256:5e06afd14cbaf9e00899fae69b24a32f2196c19de08fcb9f4779dd4f004e5e7c", + "sha256:62ee94988d6b4722ce0028644418d93a52429e977d742ca2ccbe1c4f4a792511", + "sha256:63e4844797b975b9af3a3fb8f7866ff08775f5426925e1e0bbcfe7932059a12c", + "sha256:6510bf84a6b643dabba74d3049ead221257603a253d0a9873f55f6a59a65f822", + "sha256:667a9706c970cb552ede35aee17339a18e8f2a87a51fba2ed39ceeeb1004798a", + "sha256:6ef9ea3f137e5711f0dbe5f9263e8c009b7069d8a1acea822bd5e9dae0ae49c8", + "sha256:7017b2be767b9d43cc31416aba48aab0d2309ee31b4dbf10a1d38fb7972bdf9d", + "sha256:7124e16b4c55d417577c2077be379514321916d5790fa287c9ed6f23bd2ffd01", + "sha256:73aaad12ac0ff500f62cebed98d8789198ea0e6f233421059fa68a5aa7220145", + "sha256:77c386de38a60d1dfb8e55b8c1101d68c79dfdd25c7095d51fec2dd800892b80", + "sha256:7876452af029456b3f3549b696bb36a06db7c90747740c5302f74a9e9fa14b13", + "sha256:7939aa3ca7d2a1593596e7ac6d59391ff30281ef280d8632fa03d81f7c5f955e", + "sha256:8320f64b777d00dd7ccdade271eaf0cad6636343293a25074cc5566160e4de7b", + "sha256:85f3ff71e2e60bd4b4932a043fbbe0f499e263c628390b285cb599154a3b03b1", + "sha256:8b8b36671f10ba80e159378df9c4f15c14098c4fd73a36b9ad715f057272fbef", + "sha256:93147c513fac16385d1036b7e5b102c7fbbdb163d556b791f0f11eada7ba65dc", + "sha256:935e943ec47c4afab8965954bf49bfa639c05d4ccf9ef6e924188f762145c0ff", + "sha256:94b6150a85e1b33b40b1464a3f9988dcc5251d6ed06842abff82e42632fac120", + "sha256:94ebba31df2aa506d7b14866fed00ac141a867e63143fe5bca82a8e503b36437", + "sha256:95ffcf719966dd7c453f908e208e14cde192e09fde6c7186c8f1896ef778d8cd", + "sha256:98884ecf2ffb7d7fe6bd517e8eb99d31ff7855a840fa6d0d63cd07c037f6a981", + "sha256:99cfaa2110534e2cf3ba31a7abcac9d328d1d9f1b95beede58294a60348fba36", + "sha256:9e8f8c9cb53cdac7ba9793c276acd90168f416b9ce36799b9b885790f8ad6c0a", + "sha256:a0dfc6c143b519113354e780a50381508139b07d2177cb6ad6a08278ec655798", + "sha256:b2795058c23988728eec1f36a4e5e4ebad22f8320c85f3587b539b9ac84128d7", + "sha256:b42703b1cf69f2aa1df7d1030b9d77d3e584a70755674d60e710f0af570f3761", + "sha256:b7cede291382a78f7bb5f04a529cb18e068dd29e0fb27376074b6d0317bf4dd0", + "sha256:b8a678974d1f3aa55f6cc34dc480169d58f2e6d8958895d68845fa4ab566509e", + "sha256:b8da394b34370874b4572676f36acabac172602abf054cbc4ac910219f3340af", + "sha256:c3a701fe5a9695b238503ce5bbe8218e03c3bcccf7e204e455e7462d770268aa", + "sha256:c4aab7f6381f38a4b42f269057aee279ab0fc7bf2e929e3d4abfae97b682a12c", + "sha256:ca9d0ff5ad43e785350894d97e13633a66e2b50000e8a183a50a88d834752d42", + "sha256:d0028e725ee18175c6e422797c407874da24381ce0690d6b9396c204c7f7276e", + "sha256:d21e10da6ec19b457b82636209cbe2331ff4306b54d06fa04b7c138ba18c8a81", + "sha256:d5e975ca70269d66d17dd995dafc06f1b06e8cb1ec1e9ed54c1d1e4a7c4cf26e", + "sha256:da7a9bff22ce038e19bf62c4dd1ec8391062878710ded0a845bcf47cc0200617", + "sha256:db32b5348615a04b82240cc67983cb315309e88d444a288934ee6ceaebcad6cc", + "sha256:dcc62f31eae24de7f8dce72134c8651c58000d3b1868e01392baea7c32c247de", + "sha256:dfc59d69fc48664bc693842bd57acfdd490acafda1ab52c7836e3fc75c90a111", + "sha256:e347b3bfcf985a05e8c0b7d462ba6f15b1ee1c909e2dcad795e49e91b152c383", + "sha256:e4d333e558953648ca09d64f13e6d8f0523fa705f51cae3f03b5983489958c70", + "sha256:ed10eac5830befbdd0c32f83e8aa6288361597550ba669b04c48f0f9a2c843c6", + "sha256:efc0f674aa41b92da8c49e0346318c6075d734994c3c4e4430b1c3f853e498e4", + "sha256:f1695e76146579f8c06c1509c7ce4dfe0706f49c6831a817ac04eebb2fd02011", + "sha256:f1d4aeb8891338e60d1ab6127af1fe45def5259def8094b9c7e34690c8858803", + "sha256:f406b22b7c9a9b4f8aa9d2ab13d6ae0ac3e85c9a809bd590ad53fed2bf70dc79", + "sha256:f6ff3b14f2df4c41660a7dec01045a045653998784bf8cfcb5a525bdffffbc8f" + ], + "version": "==3.1.1" }, "html5lib": { "hashes": [ "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d", "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==1.1" }, "identify": { "hashes": [ - "sha256:cb171c685bdc31bcc4c1734698736a7d5b6c8bf2e0c15117f4d469c8640ae5cf", - "sha256:e79ae4406387a9d300332b5fd366d8994f1525e8414984e1a59e058b2eda2dd0" + "sha256:53863bcac7caf8d2ed85bd20312ea5dcfc22226800f6d6881f232d861db5a8f0", + "sha256:91478c5fb7c3aac5ff7bf9b4344f803843dc586832d5f110d672b19aa1984c98" ], "markers": "python_version >= '3.8'", - "version": "==2.6.0" + "version": "==2.6.1" }, "idna": { "hashes": [ - "sha256:050b4e5baadcd44d760cedbd2b8e639f2ff89bbc7a5730fcc662954303377aac", - "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603" + "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", + "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3" ], "markers": "python_version >= '3.6'", - "version": "==3.8" + "version": "==3.10" }, "importlib-metadata": { "hashes": [ @@ -3076,18 +3215,19 @@ }, "ipython": { "hashes": [ - "sha256:0b99a2dc9f15fd68692e898e5568725c6d49c527d36a9fb5960ffbdeaa82ff7e", - "sha256:f68b3cb8bde357a5d7adc9598d57e22a45dfbea19eb6b98286fa3b288c9cd55c" + "sha256:0d0d15ca1e01faeb868ef56bc7ee5a0de5bd66885735682e8a322ae289a13d1a", + "sha256:530ef1e7bb693724d3cdc37287c80b07ad9b25986c007a53aa1857272dac3f35" ], - "markers": "python_version < '3.11' and python_version >= '3.7'", - "version": "==8.27.0" + "markers": "python_version >= '3.11'", + "version": "==8.28.0" }, "isodate": { "hashes": [ - "sha256:0751eece944162659049d35f4f549ed815792b38793f07cf73381c1c87cbed96", - "sha256:48c5881de7e8b0a0d648cb024c8062dc84e7b840ed81e864c7614fd3c127bde9" + "sha256:28009937d8031054830160fce6d409ed342816b543597cece116d966c6d99e15", + "sha256:4cd1aa0f43ca76f4a6c6c0292a85f40b35ec2e43e315b59f06e6d32171a953e6" ], - "version": "==0.6.1" + "markers": "python_version >= '3.7'", + "version": "==0.7.2" }, "jedi": { "hashes": [ @@ -3341,11 +3481,11 @@ }, "platformdirs": { "hashes": [ - "sha256:9e5e27a08aa095dd127b9f2e764d74254f482fef22b0970773bfba79d091ab8c", - "sha256:eb1c8582560b34ed4ba105009a4badf7f6f85768b30126f351328507b2beb617" + "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907", + "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb" ], "markers": "python_version >= '3.8'", - "version": "==4.3.2" + "version": "==4.3.6" }, "pluggy": { "hashes": [ @@ -3369,16 +3509,16 @@ "sha256:7e23ca1e68bbfd06ba8de98bf553bf3493264c96d5e8a615c0471025deeba722", "sha256:aa17083feb6c71da11a68b2c213b04675c4af4ce9c541762632ca3f2cb3546dd" ], - "markers": "python_version < '3.12' and python_version >= '3.8'", + "markers": "python_version >= '3.8' and python_version < '3.12'", "version": "==3.11.0" }, "prompt-toolkit": { "hashes": [ - "sha256:0d7bfa67001d5e39d02c224b663abc33687405033a8c422d0d675a5a13361d10", - "sha256:1e1b29cb58080b1e69f207c893a1a7bf16d127a5c30c9d17a25a5d77792e5360" + "sha256:d6623ab0477a80df74e646bdbc93621143f5caf104206aa29294d53de1a03d90", + "sha256:f49a827f90062e411f1ce1f854f2aedb3c23353244f8108b89283587397ac10e" ], "markers": "python_full_version >= '3.7.0'", - "version": "==3.0.47" + "version": "==3.0.48" }, "ptyprocess": { "hashes": [ @@ -3482,19 +3622,19 @@ }, "pyparsing": { "hashes": [ - "sha256:a6a7ee4235a3f944aa1fa2249307708f893fe5717dc603503c6c7969c070fb7c", - "sha256:f86ec8d1a83f11977c9a6ea7598e8c27fc5cddfa5b07ea2241edbbde1d7bc032" + "sha256:93d9577b88da0bbea8cc8334ee8b918ed014968fd2ec383e868fb8afb1ccef84", + "sha256:cbf74e27246d595d9a74b186b810f6fbb86726dbf3b9532efb343f6d7294fe9c" ], - "markers": "python_version >= '3.1'", - "version": "==3.1.4" + "markers": "python_version > '3.0'", + "version": "==3.2.0" }, "pyshacl": { "hashes": [ - "sha256:48d44f317cd9aad8e3fdb5df8aa5706fa92dc6b2746419698035e84a320fb89d", - "sha256:a4bef4296d56305a30e0a97509e541ebe4f2cc2d5da73536d0541233e28f2d22" + "sha256:4cdbaea15ec0b37a39e2a846898e79bfd32fe5d1f1b87c106e3e56ec473e3d63", + "sha256:875ccf8cd5d3c9f8ad3eec1837fb91b9ef5b876312a855f056f47d03b8bd1104" ], "markers": "python_full_version >= '3.8.1' and python_full_version < '4.0.0'", - "version": "==0.26.0" + "version": "==0.27.0" }, "pytest": { "hashes": [ @@ -3525,12 +3665,12 @@ }, "pytest-env": { "hashes": [ - "sha256:86653658da8f11c6844975db955746c458a9c09f1e64957603161e2ff93f5133", - "sha256:a4212056d4d440febef311a98fdca56c31256d58fb453d103cba4e8a532b721d" + "sha256:91209840aa0e43385073ac464a554ad2947cc2fd663a9debf88d03b01e0cc1cf", + "sha256:ce90cf8772878515c24b31cd97c7fa1f4481cd68d588419fd45f10ecaee6bc30" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==1.1.4" + "version": "==1.1.5" }, "pytest-lazy-fixtures": { "hashes": [ @@ -3555,7 +3695,7 @@ "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", "version": "==2.9.0.post0" }, "pyyaml": { @@ -3617,6 +3757,9 @@ "version": "==6.0.2" }, "rdflib": { + "extras": [ + "html" + ], "hashes": [ "sha256:0438920912a642c866a513de6fe8a0001bd86ef975057d6962c79ce4771687cd", "sha256:9995eb8569428059b8c1affd26b25eac510d64f5043d9ce8c84e0d0036e995ae" @@ -3650,43 +3793,43 @@ }, "ruff": { "hashes": [ - "sha256:0308610470fcc82969082fc83c76c0d362f562e2f0cdab0586516f03a4e06ec6", - "sha256:0b52387d3289ccd227b62102c24714ed75fbba0b16ecc69a923a37e3b5e0aaaa", - "sha256:0ea086601b22dc5e7693a78f3fcfc460cceabfdf3bdc36dc898792aba48fbad6", - "sha256:34d5efad480193c046c86608dbba2bccdc1c5fd11950fb271f8086e0c763a5d1", - "sha256:50e30b437cebef547bd5c3edf9ce81343e5dd7c737cb36ccb4fe83573f3d392e", - "sha256:549daccee5227282289390b0222d0fbee0275d1db6d514550d65420053021a58", - "sha256:66dbfea86b663baab8fcae56c59f190caba9398df1488164e2df53e216248baa", - "sha256:7862f42fc1a4aca1ea3ffe8a11f67819d183a5693b228f0bb3a531f5e40336fc", - "sha256:803b96dea21795a6c9d5bfa9e96127cc9c31a1987802ca68f35e5c95aed3fc0d", - "sha256:932063a03bac394866683e15710c25b8690ccdca1cf192b9a98260332ca93408", - "sha256:ac3b5bfbee99973f80aa1b7cbd1c9cbce200883bdd067300c22a6cc1c7fba212", - "sha256:ac4b75e898ed189b3708c9ab3fc70b79a433219e1e87193b4f2b77251d058d14", - "sha256:bedff9e4f004dad5f7f76a9d39c4ca98af526c9b1695068198b3bda8c085ef60", - "sha256:c44536df7b93a587de690e124b89bd47306fddd59398a0fb12afd6133c7b3818", - "sha256:c4b153fc152af51855458e79e835fb6b933032921756cec9af7d0ba2aa01a258", - "sha256:d02a4127a86de23002e694d7ff19f905c51e338c72d8e09b56bfb60e1681724f", - "sha256:eebe4ff1967c838a1a9618a5a59a3b0a00406f8d7eefee97c70411fefc353617", - "sha256:f0f8968feea5ce3777c0d8365653d5e91c40c31a81d95824ba61d871a11b8523" + "sha256:007dee844738c3d2e6c24ab5bc7d43c99ba3e1943bd2d95d598582e9c1b27750", + "sha256:1085c455d1b3fdb8021ad534379c60353b81ba079712bce7a900e834859182fa", + "sha256:27b87e1801e786cd6ede4ada3faa5e254ce774de835e6723fd94551464c56b8c", + "sha256:5fd0d4b7b1457c49e435ee1e437900ced9b35cb8dc5178921dfb7d98d65a08d0", + "sha256:677e03c00f37c66cea033274295a983c7c546edea5043d0c798833adf4cf4c6f", + "sha256:6cfb227b932ba8ef6e56c9f875d987973cd5e35bc5d05f5abf045af78ad8e098", + "sha256:6ef0411eccfc3909269fed47c61ffebdcb84a04504bafa6b6df9b85c27e813b0", + "sha256:6f5a2f17c7d32991169195d52a04c95b256378bbf0de8cb98478351eb70d526f", + "sha256:70edf6a93b19481affd287d696d9e311388d808671bc209fb8907b46a8c3af44", + "sha256:77944bca110ff0a43b768f05a529fecd0706aac7bcce36d7f1eeb4cbfca5f0f2", + "sha256:792213f7be25316f9b46b854df80a77e0da87ec66691e8f012f887b4a671ab5a", + "sha256:8d3bb2e3fbb9875172119021a13eed38849e762499e3cfde9588e4b4d70968dc", + "sha256:9f1476236b3eacfacfc0f66aa9e6cd39f2a624cb73ea99189556015f27c0bdeb", + "sha256:a5bf44b1aa0adaf6d9d20f86162b34f7c593bfedabc51239953e446aefc8ce18", + "sha256:cd48f945da2a6334f1793d7f701725a76ba93bf3d73c36f6b21fb04d5338dcf5", + "sha256:ce60058d3cdd8490e5e5471ef086b3f1e90ab872b548814e35930e21d848c9ce", + "sha256:ec0517dc0f37cad14a5319ba7bba6e7e339d03fbf967a6d69b0907d61be7a263", + "sha256:f8034b19b993e9601f2ddf2c517451e17a6ab5cdb1c13fdff50c1442a7171d87" ], "index": "pypi", "markers": "python_version >= '3.7'", - "version": "==0.6.4" + "version": "==0.6.8" }, "setuptools": { "hashes": [ - "sha256:5f4c08aa4d3ebcb57a50c33b1b07e94315d7fc7230f7115e47fc99776c8ce308", - "sha256:95b40ed940a1c67eb70fc099094bd6e99c6ee7c23aa2306f4d2697ba7916f9c6" + "sha256:35ab7fd3bcd95e6b7fd704e4a1539513edad446c097797f2985e0e4b960772f2", + "sha256:d59a21b17a275fb872a9c3dae73963160ae079f1049ed956880cd7c09b120538" ], "markers": "python_version >= '3.8'", - "version": "==74.1.2" + "version": "==75.1.0" }, "six": { "hashes": [ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", "version": "==1.16.0" }, "stack-data": { @@ -3696,14 +3839,6 @@ ], "version": "==0.6.3" }, - "tomli": { - "hashes": [ - "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", - "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f" - ], - "markers": "python_version < '3.11'", - "version": "==2.0.1" - }, "traitlets": { "hashes": [ "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7", @@ -3730,23 +3865,6 @@ "markers": "python_version >= '3.8'", "version": "==5.5.0.20240820" }, - "types-passlib": { - "hashes": [ - "sha256:8fc8df71623845032293d5cf7f8091f0adfeba02d387a2888684b8413f14b3d0", - "sha256:c4d299083497b66e12258c7b77c08952574213fdf7009da3135d8181a6a25f23" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==1.7.7.20240819" - }, - "types-pyasn1": { - "hashes": [ - "sha256:2cee8bfddf06d88e25ea122f7fb3b9d127a9f4a532e4d1415ef99ee0c2f902ea", - "sha256:40873dbd960e8ddb4bebda5195d3aa5e9f9c7c19d461af2f6c8540aa97e8055d" - ], - "markers": "python_version >= '3.8'", - "version": "==0.6.0.20240824" - }, "types-python-dateutil": { "hashes": [ "sha256:27c8cc2d058ccb14946eebcaaa503088f4f6dbc4fb6093d3d456a49aef2753f6", @@ -3756,32 +3874,23 @@ "markers": "python_version >= '3.8'", "version": "==2.9.0.20240906" }, - "types-python-jose": { - "hashes": [ - "sha256:b18cf8c5080bbfe1ef7c3b707986435d9efca3e90889acb6a06f65e06bc3405a", - "sha256:b515a6c0c61f5e2a53bc93e3a2b024cbd42563e2e19cbde9fd1c2cc2cfe77ccc" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==3.3.4.20240106" - }, "types-pytz": { "hashes": [ - "sha256:6810c8a1f68f21fdf0f4f374a432487c77645a0ac0b31de4bf4690cf21ad3981", - "sha256:8335d443310e2db7b74e007414e74c4f53b67452c0cb0d228ca359ccfba59659" + "sha256:4433b5df4a6fc587bbed41716d86a5ba5d832b4378e506f40d34bc9c81df2c24", + "sha256:a1eebf57ebc6e127a99d2fa2ba0a88d2b173784ef9b3defcc2004ab6855a44df" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==2024.1.0.20240417" + "version": "==2024.2.0.20240913" }, "types-requests": { "hashes": [ - "sha256:90c079ff05e549f6bf50e02e910210b98b8ff1ebdd18e19c873cd237737c1358", - "sha256:f754283e152c752e46e70942fa2a146b5bc70393522257bb85bd1ef7e019dcc3" + "sha256:2850e178db3919d9bf809e434eef65ba49d0e7e33ac92d588f4a5e295fffd405", + "sha256:59c2f673eb55f32a99b2894faf6020e1a9f4a402ad0f192bfee0b64469054310" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==2.32.0.20240712" + "version": "==2.32.0.20240914" }, "typing-extensions": { "hashes": [ @@ -3801,33 +3910,33 @@ }, "urllib3": { "hashes": [ - "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472", - "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168" + "sha256:0ed14ccfbf1c30a9072c7ca157e4319b70d65f623e91e7b32fadb2853431016e", + "sha256:40c2dc0c681e47eb8f90e7e27bf6ff7df2e677421fd46756da1161c39ca70d32" ], - "markers": "python_version >= '3.8'", - "version": "==2.2.2" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==1.26.20" }, "urwid": { "hashes": [ - "sha256:71b3171cabaa0092902f556768756bd2f2ebb24c0da287ee08f081d235340cb7", - "sha256:9ecc57330d88c8d9663ffd7092a681674c03ff794b6330ccfef479af7aa9671b" + "sha256:93ad239939e44c385e64aa00027878b9e5c486d59e855ec8ab5b1e1adcdb32a2", + "sha256:de14896c6df9eb759ed1fd93e0384a5279e51e0dde8f621e4083f7a8368c0797" ], "markers": "python_version >= '3.8'", - "version": "==2.6.15" + "version": "==2.6.16" }, "urwid-readline": { "hashes": [ - "sha256:8fabd2e501c124a30d38cfb10610b32f119a615ec0b310ae5591c583fb00bd09" + "sha256:9301444b86d58f7d26388506b704f142cefd193888488b4070d3a0fdfcfc0f84" ], - "version": "==0.14" + "version": "==0.15.1" }, "virtualenv": { "hashes": [ - "sha256:48f2695d9809277003f30776d155615ffc11328e6a0a8c1f0ec80188d7874a55", - "sha256:c17f4e0f3e6036e9f26700446f85c76ab11df65ff6d8a9cbfad9f71aabfcf23c" + "sha256:280aede09a2a5c317e409a00102e7077c6432c5a38f0ef938e643805a7ad2c48", + "sha256:7345cc5b25405607a624d8418154577459c3e0277f5466dd79c49d5e492995f2" ], "markers": "python_version >= '3.7'", - "version": "==20.26.4" + "version": "==20.26.6" }, "wcwidth": { "hashes": [ @@ -3845,11 +3954,11 @@ }, "zipp": { "hashes": [ - "sha256:9960cd8967c8f85a56f920d5d507274e74f9ff813a0ab8889a5b5be2daf44064", - "sha256:c22b14cc4763c5a5b04134207736c107db42e9d3ef2d9779d465f5f1bcba572b" + "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350", + "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29" ], "markers": "python_version >= '3.8'", - "version": "==3.20.1" + "version": "==3.20.2" }, "zope.event": { "hashes": [ @@ -3861,43 +3970,46 @@ }, "zope.interface": { "hashes": [ - "sha256:01e6e58078ad2799130c14a1d34ec89044ada0e1495329d72ee0407b9ae5100d", - "sha256:064ade95cb54c840647205987c7b557f75d2b2f7d1a84bfab4cf81822ef6e7d1", - "sha256:11fa1382c3efb34abf16becff8cb214b0b2e3144057c90611621f2d186b7e1b7", - "sha256:1bee1b722077d08721005e8da493ef3adf0b7908e0cd85cc7dc836ac117d6f32", - "sha256:1eeeb92cb7d95c45e726e3c1afe7707919370addae7ed14f614e22217a536958", - "sha256:21a207c6b2c58def5011768140861a73f5240f4f39800625072ba84e76c9da0b", - "sha256:2545d6d7aac425d528cd9bf0d9e55fcd47ab7fd15f41a64b1c4bf4c6b24946dc", - "sha256:2c4316a30e216f51acbd9fb318aa5af2e362b716596d82cbb92f9101c8f8d2e7", - "sha256:35062d93bc49bd9b191331c897a96155ffdad10744ab812485b6bad5b588d7e4", - "sha256:382d31d1e68877061daaa6499468e9eb38eb7625d4369b1615ac08d3860fe896", - "sha256:3aa8fcbb0d3c2be1bfd013a0f0acd636f6ed570c287743ae2bbd467ee967154d", - "sha256:3d4b91821305c8d8f6e6207639abcbdaf186db682e521af7855d0bea3047c8ca", - "sha256:3de1d553ce72868b77a7e9d598c9bff6d3816ad2b4cc81c04f9d8914603814f3", - "sha256:3fcdc76d0cde1c09c37b7c6b0f8beba2d857d8417b055d4f47df9c34ec518bdd", - "sha256:5112c530fa8aa2108a3196b9c2f078f5738c1c37cfc716970edc0df0414acda8", - "sha256:53d678bb1c3b784edbfb0adeebfeea6bf479f54da082854406a8f295d36f8386", - "sha256:6195c3c03fef9f87c0dbee0b3b6451df6e056322463cf35bca9a088e564a3c58", - "sha256:6d04b11ea47c9c369d66340dbe51e9031df2a0de97d68f442305ed7625ad6493", - "sha256:6dd647fcd765030638577fe6984284e0ebba1a1008244c8a38824be096e37fe3", - "sha256:799ef7a444aebbad5a145c3b34bff012b54453cddbde3332d47ca07225792ea4", - "sha256:7d92920416f31786bc1b2f34cc4fc4263a35a407425319572cbf96b51e835cd3", - "sha256:7e0c151a6c204f3830237c59ee4770cc346868a7a1af6925e5e38650141a7f05", - "sha256:84f8794bd59ca7d09d8fce43ae1b571be22f52748169d01a13d3ece8394d8b5b", - "sha256:95e5913ec718010dc0e7c215d79a9683b4990e7026828eedfda5268e74e73e11", - "sha256:9b9369671a20b8d039b8e5a1a33abd12e089e319a3383b4cc0bf5c67bd05fe7b", - "sha256:ab985c566a99cc5f73bc2741d93f1ed24a2cc9da3890144d37b9582965aff996", - "sha256:af94e429f9d57b36e71ef4e6865182090648aada0cb2d397ae2b3f7fc478493a", - "sha256:c96b3e6b0d4f6ddfec4e947130ec30bd2c7b19db6aa633777e46c8eecf1d6afd", - "sha256:cd2690d4b08ec9eaf47a85914fe513062b20da78d10d6d789a792c0b20307fb1", - "sha256:d3b7ce6d46fb0e60897d62d1ff370790ce50a57d40a651db91a3dde74f73b738", - "sha256:d976fa7b5faf5396eb18ce6c132c98e05504b52b60784e3401f4ef0b2e66709b", - "sha256:db6237e8fa91ea4f34d7e2d16d74741187e9105a63bbb5686c61fea04cdbacca", - "sha256:ecd32f30f40bfd8511b17666895831a51b532e93fc106bfa97f366589d3e4e0e", - "sha256:f418c88f09c3ba159b95a9d1cfcdbe58f208443abb1f3109f4b9b12fd60b187c" - ], - "markers": "python_version >= '3.8'", - "version": "==7.0.3" + "sha256:07add15de0cc7e69917f7d286b64d54125c950aeb43efed7a5ea7172f000fbc1", + "sha256:0ac20581fc6cd7c754f6dff0ae06fedb060fa0e9ea6309d8be8b2701d9ea51c4", + "sha256:124149e2d42067b9c6597f4dafdc7a0983d0163868f897b7bb5dc850b14f9a87", + "sha256:27cfb5205d68b12682b6e55ab8424662d96e8ead19550aad0796b08dd2c9a45e", + "sha256:2a29ac607e970b5576547f0e3589ec156e04de17af42839eedcf478450687317", + "sha256:2b6a4924f5bad9fe21d99f66a07da60d75696a136162427951ec3cb223a5570d", + "sha256:2bd9e9f366a5df08ebbdc159f8224904c1c5ce63893984abb76954e6fbe4381a", + "sha256:3bcff5c09d0215f42ba64b49205a278e44413d9bf9fa688fd9e42bfe472b5f4f", + "sha256:3f005869a1a05e368965adb2075f97f8ee9a26c61898a9e52a9764d93774f237", + "sha256:4a00ead2e24c76436e1b457a5132d87f83858330f6c923640b7ef82d668525d1", + "sha256:4af4a12b459a273b0b34679a5c3dc5e34c1847c3dd14a628aa0668e19e638ea2", + "sha256:5501e772aff595e3c54266bc1bfc5858e8f38974ce413a8f1044aae0f32a83a3", + "sha256:5e28ea0bc4b084fc93a483877653a033062435317082cdc6388dec3438309faf", + "sha256:5e956b1fd7f3448dd5e00f273072e73e50dfafcb35e4227e6d5af208075593c9", + "sha256:5fcf379b875c610b5a41bc8a891841533f98de0520287d7f85e25386cd10d3e9", + "sha256:6159e767d224d8f18deff634a1d3722e68d27488c357f62ebeb5f3e2f5288b1f", + "sha256:661d5df403cd3c5b8699ac480fa7f58047a3253b029db690efa0c3cf209993ef", + "sha256:711eebc77f2092c6a8b304bad0b81a6ce3cf5490b25574e7309fbc07d881e3af", + "sha256:80a3c00b35f6170be5454b45abe2719ea65919a2f09e8a6e7b1362312a872cd3", + "sha256:848b6fa92d7c8143646e64124ed46818a0049a24ecc517958c520081fd147685", + "sha256:91b6c30689cfd87c8f264acb2fc16ad6b3c72caba2aec1bf189314cf1a84ca33", + "sha256:9733a9a0f94ef53d7aa64661811b20875b5bc6039034c6e42fb9732170130573", + "sha256:9940d5bc441f887c5f375ec62bcf7e7e495a2d5b1da97de1184a88fb567f06af", + "sha256:9e3e48f3dea21c147e1b10c132016cb79af1159facca9736d231694ef5a740a8", + "sha256:a14c9decf0eb61e0892631271d500c1e306c7b6901c998c7035e194d9150fdd1", + "sha256:a735f82d2e3ed47ca01a20dfc4c779b966b16352650a8036ab3955aad151ed8a", + "sha256:a99240b1d02dc469f6afbe7da1bf617645e60290c272968f4e53feec18d7dce8", + "sha256:b7b25db127db3e6b597c5f74af60309c4ad65acd826f89609662f0dc33a54728", + "sha256:b936d61dbe29572fd2cfe13e30b925e5383bed1aba867692670f5a2a2eb7b4e9", + "sha256:bec001798ab62c3fc5447162bf48496ae9fba02edc295a9e10a0b0c639a6452e", + "sha256:cc8a318162123eddbdf22fcc7b751288ce52e4ad096d3766ff1799244352449d", + "sha256:d0a45b5af9f72c805ee668d1479480ca85169312211bed6ed18c343e39307d5f", + "sha256:e53c291debef523b09e1fe3dffe5f35dde164f1c603d77f770b88a1da34b7ed6", + "sha256:ec1ef1fdb6f014d5886b97e52b16d0f852364f447d2ab0f0c6027765777b6667", + "sha256:ec59fe53db7d32abb96c6d4efeed84aab4a7c38c62d7a901a9b20c09dd936e7a", + "sha256:f245d039f72e6f802902375755846f5de1ee1e14c3e8736c078565599bcab621", + "sha256:ff115ef91c0eeac69cd92daeba36a9d8e14daee445b504eeea2b1c0b55821984" + ], + "markers": "python_version >= '3.8'", + "version": "==7.1.0" } } } diff --git a/README.md b/README.md index e7a73cf36b0..2096d053558 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ See MindLogger's [Knowledge Base article](https://mindlogger.atlassian.net/servi ## Technologies -- ✅ [Python3.10+](https://www.python.org/downloads/release/python-3108/) +- ✅ [Python3.11+](https://www.python.org/downloads/release/python-31110/) - ✅ [Pipenv](https://pipenv.pypa.io/en/latest/) - ✅ [FastAPI](https://fastapi.tiangolo.com) - ✅ [Postgresql](https://www.postgresql.org/docs/14/index.html) @@ -61,7 +61,7 @@ And ### Prerequisites -- Python 3.10 +- Python 3.11 - [Docker](https://docs.docker.com/get-docker/) #### Recommended Extras @@ -71,7 +71,7 @@ Installing [pyenv](https://github.com/pyenv/pyenv) is recommended to automatical Alternatively, on macOS you can use a tool like [Homebrew](https://brew.sh/) to install multiple versions and specify when creating the virtual environment: ```bash -pipenv --python /opt/homebrew/bin/python3.10 +pipenv --python /opt/homebrew/bin/python3.11 ``` ### Environment Variables @@ -189,14 +189,15 @@ Create your virtual environment: pipenv shell ``` -If `pyenv` is installed Python 3.10 should automatically be installed in the virtual environment, you can check the correct version of Python is active by running: +If `pyenv` is installed Python 3.11 should automatically be installed in the virtual environment, you can check the +correct version of Python is active by running: ```bash python --version ``` -If the active version is **not** 3.10, you can manually specify a version while creating your virtual environment: +If the active version is **not** 3.11, you can manually specify a version while creating your virtual environment: ```bash -pipenv --python /opt/homebrew/bin/python3.10 +pipenv --python /opt/homebrew/bin/python3.11 ``` Install all dependencies diff --git a/compose/fastapi/Dockerfile b/compose/fastapi/Dockerfile index 5d4aae974ff..bb6fd504ebd 100644 --- a/compose/fastapi/Dockerfile +++ b/compose/fastapi/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.10-slim-bookworm AS base +FROM python:3.11-slim-bookworm AS base ENV PYTHONUNBUFFERED=1 ENV PYTHONPATH="src/" @@ -6,7 +6,7 @@ ENV PYTHONPATH="src/" WORKDIR /app/ RUN apt-get -y update && apt-get -y upgrade \ - && apt-get install --no-install-recommends -y build-essential=12.9 curl=7.88* libffi-dev \ + && apt-get install --no-install-recommends -y build-essential curl libffi-dev \ && rm -rf /var/lib/apt/lists/ # Add local non-root user to avoid issue with files @@ -67,8 +67,8 @@ FROM base AS worker USER root RUN apt-get update -y && apt-get install -y --no-install-recommends \ - ffmpeg=7:5.1* \ - imagemagick=8:6.9* \ + ffmpeg \ + imagemagick \ && rm -rf /var/lib/apt/lists/ USER code diff --git a/pyproject.toml b/pyproject.toml index 1b4b90b3bac..3c4d0280256 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -71,7 +71,7 @@ omit = [ [tool.mypy] plugins = ["pydantic.mypy"] ignore_missing_imports = true -python_version = '3.10' +python_version = '3.11' mypy_path = 'src' files = ['*.py'] warn_redundant_casts = true diff --git a/src/apps/activities/domain/activity_item_base.py b/src/apps/activities/domain/activity_item_base.py index a6c1c1428ea..a8d49043287 100644 --- a/src/apps/activities/domain/activity_item_base.py +++ b/src/apps/activities/domain/activity_item_base.py @@ -8,7 +8,6 @@ AlertFlagMissingSliderItemError, DataMatrixRequiredError, HiddenWhenConditionalLogicSetError, - IncorrectConditionLogicItemTypeError, IncorrectConfigError, IncorrectNameCharactersError, IncorrectResponseValueError, @@ -154,34 +153,6 @@ def validate_score_required(cls, values): return values - @validator("conditional_logic") - def validate_conditional_logic(cls, value, values): - response_type = values.get("response_type") - if value is not None and response_type not in [ - ResponseType.SINGLESELECT, - ResponseType.MULTISELECT, - ResponseType.SINGLESELECTROWS, - ResponseType.MULTISELECTROWS, - ResponseType.SLIDER, - ResponseType.SLIDERROWS, - ResponseType.TEXT, - ResponseType.PARAGRAPHTEXT, - ResponseType.TIME, - ResponseType.TIMERANGE, - ResponseType.DATE, - ResponseType.NUMBERSELECT, - ResponseType.DRAWING, - ResponseType.PHOTO, - ResponseType.VIDEO, - ResponseType.GEOLOCATION, - ResponseType.AUDIO, - ResponseType.MESSAGE, - ResponseType.AUDIOPLAYER, - ]: - raise IncorrectConditionLogicItemTypeError() - - return value - @root_validator(skip_on_failure=True) def validate_is_hidden(cls, values): # cannot hide if conditional logic is set diff --git a/src/apps/activities/domain/conditional_logic.py b/src/apps/activities/domain/conditional_logic.py index 2bbe4fb3073..fb8baccb26d 100644 --- a/src/apps/activities/domain/conditional_logic.py +++ b/src/apps/activities/domain/conditional_logic.py @@ -1,4 +1,4 @@ -from enum import Enum +from enum import StrEnum from pydantic import Field @@ -6,7 +6,7 @@ from apps.shared.domain import PublicModel -class Match(str, Enum): +class Match(StrEnum): ANY = "any" ALL = "all" diff --git a/src/apps/activities/domain/conditions.py b/src/apps/activities/domain/conditions.py index 9c7452fa1d5..dce8053b60e 100644 --- a/src/apps/activities/domain/conditions.py +++ b/src/apps/activities/domain/conditions.py @@ -1,11 +1,14 @@ -from enum import Enum +import datetime +from enum import StrEnum +from typing import Any, Dict, Optional -from pydantic import Field, validator +from pydantic import Field, root_validator, validator -from apps.shared.domain import PublicModel +from apps.activities.errors import IncorrectMaxTimeRange, IncorrectMinTimeRange, IncorrectTimeRange +from apps.shared.domain import PublicModel, PublicModelNoExtra -class ConditionType(str, Enum): +class ConditionType(StrEnum): INCLUDES_OPTION = "INCLUDES_OPTION" NOT_INCLUDES_OPTION = "NOT_INCLUDES_OPTION" EQUAL_TO_OPTION = "EQUAL_TO_OPTION" @@ -19,17 +22,63 @@ class ConditionType(str, Enum): EQUAL_TO_SCORE = "EQUAL_TO_SCORE" -class MultiSelectConditionType(str, Enum): +class DateConditionType(StrEnum): + GREATER_THAN_DATE = "GREATER_THAN_DATE" + LESS_THAN_DATE = "LESS_THAN_DATE" + EQUAL_TO_DATE = "EQUAL_TO_DATE" + NOT_EQUAL_TO_DATE = "NOT_EQUAL_TO_DATE" + BETWEEN_DATES = "BETWEEN_DATES" + OUTSIDE_OF_DATES = "OUTSIDE_OF_DATES" + + +class TimeRangeConditionType(StrEnum): + GREATER_THAN_TIME_RANGE = "GREATER_THAN_TIME_RANGE" + LESS_THAN_TIMES_RANGE = "LESS_THAN_TIME_RANGE" + BETWEEN_TIMES_RANGE = "BETWEEN_TIMES_RANGE" + EQUAL_TO_TIMES_RANGE = "EQUAL_TO_TIME_RANGE" + NOT_EQUAL_TO_TIMES_RANGE = "NOT_EQUAL_TO_TIME_RANGE" + OUTSIDE_OF_TIMES_RANGE = "OUTSIDE_OF_TIMES_RANGE" + + +class TimeConditionType(StrEnum): + GREATER_THAN_TIME = "GREATER_THAN_TIME" + LESS_THAN_TIME = "LESS_THAN_TIME" + BETWEEN_TIMES = "BETWEEN_TIMES" + EQUAL_TO_TIME = "EQUAL_TO_TIME" + NOT_EQUAL_TO_TIMES = "NOT_EQUAL_TO_TIME" + OUTSIDE_OF_TIMES = "OUTSIDE_OF_TIMES" + + +class MultiSelectConditionType(StrEnum): INCLUDES_OPTION = "INCLUDES_OPTION" NOT_INCLUDES_OPTION = "NOT_INCLUDES_OPTION" -class SingleSelectConditionType(str, Enum): +class MultiSelectionsPerRowConditionType(StrEnum): + INCLUDES_ROW_OPTION = "INCLUDES_ROW_OPTION" + NOT_INCLUDES_ROW_OPTION = "NOT_INCLUDES_ROW_OPTION" + + +class SingleSelectionPerRowConditionType(StrEnum): + EQUAL_TO_ROW_OPTION = "EQUAL_TO_ROW_OPTION" + NOT_EQUAL_TO_ROW_OPTION = "NOT_EQUAL_TO_ROW_OPTION" + + +class SingleSelectConditionType(StrEnum): EQUAL_TO_OPTION = "EQUAL_TO_OPTION" NOT_EQUAL_TO_OPTION = "NOT_EQUAL_TO_OPTION" -class SliderConditionType(str, Enum): +class SliderRowConditionType(StrEnum): + GREATER_THAN_SLIDER_ROWS = "GREATER_THAN_SLIDER_ROWS" + LESS_THAN_SLIDER_ROWS = "LESS_THAN_SLIDER_ROWS" + EQUAL_TO_SLIDER_ROWS = "EQUAL_TO_SLIDER_ROWS" + NOT_EQUAL_TO_SLIDER_ROWS = "NOT_EQUAL_TO_SLIDER_ROWS" + BETWEEN_SLIDER_ROWS = "BETWEEN_SLIDER_ROWS" + OUTSIDE_OF_SLIDER_ROWS = "OUTSIDE_OF_SLIDER_ROWS" + + +class SliderConditionType(StrEnum): GREATER_THAN = "GREATER_THAN" LESS_THAN = "LESS_THAN" EQUAL = "EQUAL" @@ -38,11 +87,32 @@ class SliderConditionType(str, Enum): OUTSIDE_OF = "OUTSIDE_OF" -class OptionPayload(PublicModel): +class TimePayloadType(StrEnum): + START_TIME = "startTime" + END_TIME = "endTime" + + +OPTION_BASED_CONDITIONS = [ + MultiSelectConditionType.INCLUDES_OPTION, + MultiSelectConditionType.NOT_INCLUDES_OPTION, + SingleSelectConditionType.EQUAL_TO_OPTION, + SingleSelectConditionType.NOT_EQUAL_TO_OPTION, + SingleSelectionPerRowConditionType.EQUAL_TO_ROW_OPTION, + SingleSelectionPerRowConditionType.NOT_EQUAL_TO_ROW_OPTION, + MultiSelectionsPerRowConditionType.INCLUDES_ROW_OPTION, + MultiSelectionsPerRowConditionType.NOT_INCLUDES_ROW_OPTION, +] + + +class OptionPayload(PublicModelNoExtra): option_value: str -class ValuePayload(PublicModel): +class OptionIndexPayload(OptionPayload): + row_index: str + + +class ValuePayload(PublicModelNoExtra): value: float @validator("value") @@ -50,7 +120,170 @@ def validate_score(cls, value): return round(value, 2) -class MinMaxPayload(PublicModel): +class ValueIndexPayload(ValuePayload): + row_index: str + + +class SingleDatePayload(PublicModel): + date: datetime.date + + def dict(self, *args, **kwargs): + d = super().dict(*args, **kwargs) + d["date"] = self.date.isoformat() + return d + + +class DateRangePayload(PublicModel): + minDate: datetime.date + maxDate: datetime.date + + @root_validator(pre=True) + def validate_dates(cls, values): + min_date = values.get("minDate") + max_date = values.get("maxDate") + if min_date and max_date and min_date > max_date: + raise ValueError("minDate cannot be later than maxDate") + return values + + def dict(self, *args, **kwargs): + d = super().dict(*args, **kwargs) + d["minDate"] = self.minDate.isoformat() + d["maxDate"] = self.maxDate.isoformat() + return d + + +class TimePayload(PublicModel): + type: TimePayloadType | None = None + value: datetime.time + + def dict(self, *args, **kwargs): + d = super().dict(*args, **kwargs) + d["value"] = self.value.strftime("%H:%M") + return d + + +class SingleTimePayload(PublicModel): + time: Optional[datetime.time] = None + max_value: Optional[datetime.time] = None + min_value: Optional[datetime.time] = None + + @root_validator(pre=True) + def validate_time(cls, values: Dict[str, Any]) -> Dict[str, Any]: + time_value = values.get("time") + max_time_value = values.get("max_value") + min_time_value = values.get("min_value") + + if isinstance(time_value, dict): + values["time"] = cls._dict_to_time(time_value) + elif isinstance(time_value, str): + values["time"] = cls._string_to_time(time_value) + if max_time_value and min_time_value: + if isinstance(max_time_value, dict): + max_time_value = cls._dict_to_time(max_time_value) + elif isinstance(max_time_value, str): + max_time_value = cls._string_to_time(max_time_value) + + if isinstance(min_time_value, dict): + min_time_value = cls._dict_to_time(min_time_value) + elif isinstance(min_time_value, str): + min_time_value = cls._string_to_time(min_time_value) + + if max_time_value < min_time_value: + raise IncorrectTimeRange() + + if min_time_value is not None: + if max_time_value is None: + raise IncorrectMaxTimeRange() + if max_time_value is not None: + if min_time_value is None: + raise IncorrectMinTimeRange() + + return values + + def dict(self, *args, **kwargs) -> Dict[str, Any]: + d = super().dict(*args, **kwargs) + if self.time: + d["time"] = self.time.strftime("%H:%M") + return d + + @staticmethod + def _dict_to_time(time_dict: Dict[str, Any]) -> datetime.time: + if "hours" in time_dict and "minutes" in time_dict: + return datetime.time(hour=int(time_dict["hours"]), minute=int(time_dict["minutes"])) + raise ValueError("Invalid time dictionary structure") + + @staticmethod + def _string_to_time(time_string: str) -> datetime.time: + try: + return datetime.datetime.strptime(time_string, "%H:%M").time() + except ValueError: + raise ValueError("Invalid time string format. Expected 'HH:MM'.") + + @staticmethod + def _time_to_dict(time: datetime.time) -> Dict[str, int]: + return {"hours": time.hour, "minutes": time.minute} + + +class MinMaxTimePayload(PublicModel): + minTime: Optional[datetime.time] = None + maxTime: Optional[datetime.time] = None + + @root_validator(pre=True) + def validate_times(cls, values: Dict[str, Any]) -> Dict[str, Any]: + min_time_dict = values.get("minTime") + max_time_dict = values.get("maxTime") + + if isinstance(min_time_dict, dict): + values["minTime"] = cls._dict_to_time(min_time_dict) + if isinstance(max_time_dict, dict): + values["maxTime"] = cls._dict_to_time(max_time_dict) + + return values + + def dict(self, *args: Any, **kwargs: Any) -> Dict[str, Any]: + d = super().dict(*args, **kwargs) + if self.minTime: + d["minTime"] = self._time_to_dict(self.minTime) + if self.maxTime: + d["maxTime"] = self._time_to_dict(self.maxTime) + return {key: value for key, value in d.items() if value is not None} + + @staticmethod + def _dict_to_time(time_dict: Dict[str, int]) -> datetime.time: + if "hours" in time_dict and "minutes" in time_dict: + return datetime.time(hour=int(time_dict["hours"]), minute=int(time_dict["minutes"])) + raise ValueError("Invalid time dictionary structure") + + @staticmethod + def _time_to_dict(time: datetime.time) -> Dict[str, int]: + return {"hours": time.hour, "minutes": time.minute} + + def json_serialize(self) -> Dict[str, Any]: + data = self.dict() + if self.minTime: + data["minTime"] = self._time_to_dict(self.minTime) + if self.maxTime: + data["maxTime"] = self._time_to_dict(self.maxTime) + return data + + +class MinMaxSliderRowPayload(PublicModelNoExtra): + minValue: float + maxValue: float + rowIndex: str + + @validator("minValue", "maxValue") + def validate_score(cls, value): + return round(value, 2) + + def dict(self, *args, **kwargs): + d = super().dict(*args, **kwargs) + d["minValue"] = round(self.minValue, 2) + d["maxValue"] = round(self.maxValue, 2) + return d + + +class MinMaxPayload(PublicModelNoExtra): min_value: float max_value: float @@ -59,6 +292,10 @@ def validate_score(cls, value): return round(value, 2) +class MinMaxPayloadRow(MinMaxPayload): + row_index: str + + class ScoreConditionPayload(PublicModel): value: bool @@ -67,54 +304,308 @@ class BaseCondition(PublicModel): item_name: str -class IncludesOptionCondition(BaseCondition): +class _IncludesOptionCondition(BaseCondition): type: str = Field(ConditionType.INCLUDES_OPTION, const=True) - payload: OptionPayload -class NotIncludesOptionCondition(BaseCondition): +class _IncludesOptionPerRowCondition(BaseCondition): + type: str = Field(MultiSelectionsPerRowConditionType.INCLUDES_ROW_OPTION, const=True) + + +class _NotIncludesOptionPerRowCondition(BaseCondition): + type: str = Field(MultiSelectionsPerRowConditionType.NOT_INCLUDES_ROW_OPTION, const=True) + + +class _NotIncludesOptionCondition(BaseCondition): type: str = Field(ConditionType.NOT_INCLUDES_OPTION, const=True) - payload: OptionPayload -class EqualToOptionCondition(BaseCondition): +class _EqualToOptionCondition(BaseCondition): type: str = Field(ConditionType.EQUAL_TO_OPTION, const=True) - payload: OptionPayload -class NotEqualToOptionCondition(BaseCondition): +class _EqualToRowOptionCondition(BaseCondition): + type: str = Field(SingleSelectionPerRowConditionType.EQUAL_TO_ROW_OPTION, const=True) + + +class _NotEqualToRowOptionCondition(BaseCondition): + type: str = Field(SingleSelectionPerRowConditionType.NOT_EQUAL_TO_ROW_OPTION, const=True) + + +class _NotEqualToOptionCondition(BaseCondition): type: str = Field(ConditionType.NOT_EQUAL_TO_OPTION, const=True) - payload: OptionPayload -class GreaterThanCondition(BaseCondition): +class _GraterThanDateCondition(BaseCondition): + type: str = Field(DateConditionType.GREATER_THAN_DATE, const=True) + + +class _LessThanDateCondition(BaseCondition): + type: str = Field(DateConditionType.LESS_THAN_DATE, const=True) + + +class _GreaterThanSliderRowCondition(BaseCondition): + type: str = Field(SliderRowConditionType.GREATER_THAN_SLIDER_ROWS, const=True) + + +class _LessThanSliderRowCondition(BaseCondition): + type: str = Field(SliderRowConditionType.LESS_THAN_SLIDER_ROWS, const=True) + + +class _EqualToSliderRowCondition(BaseCondition): + type: str = Field(SliderRowConditionType.EQUAL_TO_SLIDER_ROWS, const=True) + + +class _NotEqualToSliderRowCondition(BaseCondition): + type: str = Field(SliderRowConditionType.NOT_EQUAL_TO_SLIDER_ROWS, const=True) + + +class _BetweenSliderRowCondition(BaseCondition): + type: str = Field(SliderRowConditionType.BETWEEN_SLIDER_ROWS, const=True) + + +class _OutsideOfSliderRowCondition(BaseCondition): + type: str = Field(SliderRowConditionType.OUTSIDE_OF_SLIDER_ROWS, const=True) + + +class _BetweenTimeRangeCondition(BaseCondition): + type: str = Field(TimeRangeConditionType.BETWEEN_TIMES_RANGE, const=True) + + +class _GreaterThanTimeRangeCondition(BaseCondition): + type: str = Field(TimeRangeConditionType.GREATER_THAN_TIME_RANGE, const=True) + + +class _EqualToTimeRangeCondition(BaseCondition): + type: str = Field(TimeRangeConditionType.EQUAL_TO_TIMES_RANGE, const=True) + + +class _EqualToTimeCondition(BaseCondition): + type: str = Field(TimeConditionType.EQUAL_TO_TIME, const=True) + + +class _NotEqualToTimeCondition(BaseCondition): + type: str = Field(TimeConditionType.NOT_EQUAL_TO_TIMES, const=True) + + +class _LessThanTimeRangeCondition(BaseCondition): + type: str = Field(TimeRangeConditionType.LESS_THAN_TIMES_RANGE, const=True) + + +class _LessThanTimeCondition(BaseCondition): + type: str = Field(TimeConditionType.LESS_THAN_TIME, const=True) + + +class _BetweenTimeCondition(BaseCondition): + type: str = Field(TimeConditionType.BETWEEN_TIMES, const=True) + + +class _NotEqualToTimeRangeCondition(BaseCondition): + type: str = Field(TimeRangeConditionType.NOT_EQUAL_TO_TIMES_RANGE, const=True) + + +class _OutsideOfTimeRangeCondition(BaseCondition): + type: str = Field(TimeRangeConditionType.OUTSIDE_OF_TIMES_RANGE, const=True) + + +class _GreaterThanTimeCondition(BaseCondition): + type: str = Field(TimeConditionType.GREATER_THAN_TIME, const=True) + + +class _OutsideOfTimeCondition(BaseCondition): + type: str = Field(TimeConditionType.OUTSIDE_OF_TIMES, const=True) + + +class _GreaterThanCondition(BaseCondition): type: str = Field(ConditionType.GREATER_THAN, const=True) - payload: ValuePayload -class LessThanCondition(BaseCondition): +class _LessThanCondition(BaseCondition): type: str = Field(ConditionType.LESS_THAN, const=True) - payload: ValuePayload -class EqualCondition(BaseCondition): +class _EqualCondition(BaseCondition): type: str = Field(ConditionType.EQUAL, const=True) - payload: ValuePayload -class NotEqualCondition(BaseCondition): +class _EqualToDateCondition(BaseCondition): + type: str = Field(DateConditionType.EQUAL_TO_DATE, const=True) + + +class _NotEqualToDateCondition(BaseCondition): + type: str = Field(DateConditionType.NOT_EQUAL_TO_DATE, const=True) + + +class _NotEqualCondition(BaseCondition): type: str = Field(ConditionType.NOT_EQUAL, const=True) - payload: ValuePayload -class BetweenCondition(BaseCondition): +class _BetweenCondition(BaseCondition): type: str = Field(ConditionType.BETWEEN, const=True) - payload: MinMaxPayload -class OutsideOfCondition(BaseCondition): +class _BetweenDatesCondition(BaseCondition): + type: str = Field(DateConditionType.BETWEEN_DATES, const=True) + + +class _OutsideOfDatesCondition(BaseCondition): + type: str = Field(DateConditionType.OUTSIDE_OF_DATES, const=True) + + +class _OutsideOfCondition(BaseCondition): type: str = Field(ConditionType.OUTSIDE_OF, const=True) - payload: MinMaxPayload + + +class IncludesOptionCondition(_IncludesOptionCondition): + payload: OptionPayload | OptionIndexPayload + + +class IncludesOptionPerRowCondition(_IncludesOptionPerRowCondition): + payload: OptionPayload | OptionIndexPayload + + +class NotIncludesOptionPerRowCondition(_NotIncludesOptionPerRowCondition): + payload: OptionPayload | OptionIndexPayload + + +class NotIncludesOptionCondition(_NotIncludesOptionCondition): + payload: OptionPayload | OptionIndexPayload + + +class EqualToOptionCondition(_EqualToOptionCondition): + payload: OptionPayload | OptionIndexPayload + + +class EqualToRowOptionCondition(_EqualToRowOptionCondition): + payload: OptionPayload | OptionIndexPayload + + +class NotEqualToRowOptionCondition(_NotEqualToRowOptionCondition): + payload: OptionPayload | OptionIndexPayload + + +class NotEqualToOptionCondition(_NotEqualToOptionCondition): + payload: OptionPayload | OptionIndexPayload + + +class GreaterThanDateCondition(_GraterThanDateCondition): + payload: SingleDatePayload + + +class GreaterThanSliderRowCondition(_GreaterThanSliderRowCondition): + payload: ValuePayload | ValueIndexPayload + + +class LessThanSliderRowCondition(_LessThanSliderRowCondition): + payload: ValuePayload | ValueIndexPayload + + +class EqualToSliderRowCondition(_EqualToSliderRowCondition): + payload: ValuePayload | ValueIndexPayload + + +class NotEqualToSliderRowCondition(_NotEqualToSliderRowCondition): + payload: ValuePayload | ValueIndexPayload + + +class BetweenSliderRowCondition(_BetweenSliderRowCondition): + payload: MinMaxSliderRowPayload | ValueIndexPayload + + +class OutsideOfSliderRowCondition(_OutsideOfSliderRowCondition): + payload: MinMaxSliderRowPayload | ValueIndexPayload + + +class LessThanDateCondition(_LessThanDateCondition): + payload: SingleDatePayload + + +class BetweenTimeRangeCondition(_BetweenTimeRangeCondition): + payload: MinMaxTimePayload + + +class GreaterThanTimeRangeCondition(_GreaterThanTimeRangeCondition): + payload: SingleTimePayload + + +class LessThanTimeRangeCondition(_LessThanTimeRangeCondition): + payload: SingleTimePayload + + +class EqualToTimeRangeCondition(_EqualToTimeRangeCondition): + payload: SingleTimePayload + + +class NotEqualToTimeRangeCondition(_NotEqualToTimeRangeCondition): + payload: SingleTimePayload + + +class OutsideOfTimeRangeCondition(_OutsideOfTimeRangeCondition): + payload: MinMaxTimePayload + + +class GreaterThanTimeCondition(_GreaterThanTimeCondition): + payload: SingleTimePayload + + +class LessThanTimeCondition(_LessThanTimeCondition): + payload: SingleTimePayload + + +class EqualToTimeCondition(_EqualToTimeCondition): + payload: SingleTimePayload + + +class NotEqualToTimeCondition(_NotEqualToTimeCondition): + payload: SingleTimePayload + + +class OutsideOfTimeCondition(_OutsideOfTimeCondition): + payload: MinMaxTimePayload + + +class BetweenTimeCondition(_BetweenTimeCondition): + payload: MinMaxTimePayload + + +class GreaterThanCondition(_GreaterThanCondition): + payload: ValuePayload | TimePayload + + +class LessThanCondition(_LessThanCondition): + payload: ValuePayload | ValueIndexPayload | TimePayload + + +class EqualToDateCondition(_EqualToDateCondition): + payload: SingleDatePayload + + +class EqualCondition(_EqualCondition): + payload: ValuePayload | ValueIndexPayload | TimePayload | SingleTimePayload + + +class NotEqualToDateCondition(_NotEqualToDateCondition): + payload: SingleDatePayload + + +class NotEqualCondition(_NotEqualCondition): + payload: ValuePayload | ValueIndexPayload | TimePayload + + +class BetweenDatesCondition(_BetweenDatesCondition): + payload: DateRangePayload + + +class BetweenCondition(_BetweenCondition): + payload: MinMaxPayload | MinMaxPayloadRow | TimePayload + + +class OutsideOfCondition(_OutsideOfCondition): + payload: MinMaxPayload | MinMaxPayloadRow | TimePayload + + +class OutsideOfDatesCondition(_OutsideOfDatesCondition): + payload: DateRangePayload class ScoreBoolCondition(BaseCondition): @@ -122,6 +613,46 @@ class ScoreBoolCondition(BaseCondition): payload: ScoreConditionPayload +class ScoreGraterThanCondition(_GreaterThanCondition): + payload: ValuePayload + + +class ScoreLessThanCondition(_LessThanCondition): + payload: ValuePayload + + +class ScoreEqualCondition(_EqualCondition): + payload: ValuePayload + + +class ScoreNotEqualCondition(_NotEqualCondition): + payload: ValuePayload + + +class ScoreBetweenCondition(_BetweenCondition): + payload: MinMaxPayload + + +class ScoreOutsideOfCondition(_OutsideOfCondition): + payload: MinMaxPayload + + +class ScoreNotIncludesOptionCondition(_NotIncludesOptionCondition): + payload: OptionPayload + + +class ScoreIncludesOptionCondition(_IncludesOptionCondition): + payload: OptionPayload + + +class ScoreEqualToOptionCondition(_EqualToOptionCondition): + payload: OptionPayload + + +class ScoreNotEqualToOptionCondition(_NotEqualToOptionCondition): + payload: OptionPayload + + Condition = ( IncludesOptionCondition | NotIncludesOptionCondition @@ -133,39 +664,67 @@ class ScoreBoolCondition(BaseCondition): | NotEqualCondition | BetweenCondition | OutsideOfCondition + | GreaterThanDateCondition + | BetweenTimeRangeCondition + | LessThanDateCondition + | EqualToDateCondition + | BetweenDatesCondition + | NotEqualToDateCondition + | OutsideOfDatesCondition + | GreaterThanTimeRangeCondition + | LessThanTimeRangeCondition + | EqualToTimeRangeCondition + | NotEqualToTimeRangeCondition + | OutsideOfTimeRangeCondition + | EqualToRowOptionCondition + | NotEqualToRowOptionCondition + | IncludesOptionPerRowCondition + | NotIncludesOptionPerRowCondition + | GreaterThanSliderRowCondition + | LessThanSliderRowCondition + | EqualToSliderRowCondition + | NotEqualToSliderRowCondition + | BetweenSliderRowCondition + | OutsideOfSliderRowCondition + | GreaterThanTimeCondition + | LessThanTimeCondition + | EqualToTimeCondition + | NotEqualToTimeCondition + | BetweenTimeCondition + | OutsideOfTimeCondition ) ScoreCondition = ( - GreaterThanCondition - | LessThanCondition - | EqualCondition - | NotEqualCondition - | BetweenCondition - | OutsideOfCondition + ScoreGraterThanCondition + | ScoreLessThanCondition + | ScoreEqualCondition + | ScoreNotEqualCondition + | ScoreBetweenCondition + | ScoreOutsideOfCondition ) SectionCondition = ( - IncludesOptionCondition - | NotIncludesOptionCondition - | EqualToOptionCondition - | NotEqualToOptionCondition - | GreaterThanCondition - | LessThanCondition - | EqualCondition - | NotEqualCondition - | BetweenCondition - | OutsideOfCondition + ScoreIncludesOptionCondition + | ScoreNotIncludesOptionCondition + | ScoreEqualToOptionCondition + | ScoreNotEqualToOptionCondition + | ScoreGraterThanCondition + | ScoreGraterThanCondition + | ScoreEqualCondition + | ScoreNotEqualCondition + | ScoreBetweenCondition + | ScoreOutsideOfCondition | ScoreBoolCondition ) AnyCondition = ( - IncludesOptionCondition - | NotIncludesOptionCondition - | EqualToOptionCondition - | NotEqualToOptionCondition - | GreaterThanCondition - | LessThanCondition - | EqualCondition - | NotEqualCondition - | BetweenCondition - | OutsideOfCondition + ScoreIncludesOptionCondition + | ScoreNotIncludesOptionCondition + | ScoreEqualToOptionCondition + | ScoreNotEqualToOptionCondition + | ScoreGraterThanCondition + | ScoreGraterThanCondition + | ScoreEqualCondition + | ScoreNotEqualCondition + | ScoreBetweenCondition + | ScoreOutsideOfCondition | ScoreBoolCondition ) diff --git a/src/apps/activities/domain/constants.py b/src/apps/activities/domain/constants.py index 5e1f1041ec6..2946d402f47 100644 --- a/src/apps/activities/domain/constants.py +++ b/src/apps/activities/domain/constants.py @@ -1,8 +1,8 @@ -from enum import Enum - __all__ = ["InputType"] +from enum import StrEnum + -class InputType(str, Enum): +class InputType(StrEnum): RADIOBUTTON = "radiobutton" CHECKBOX = "checkbox" diff --git a/src/apps/activities/domain/custom_validation.py b/src/apps/activities/domain/custom_validation.py index 0fb6e6c3c5d..363f47f096e 100644 --- a/src/apps/activities/domain/custom_validation.py +++ b/src/apps/activities/domain/custom_validation.py @@ -1,7 +1,6 @@ -from apps.activities.domain.conditions import MultiSelectConditionType, SingleSelectConditionType from apps.activities.domain.response_type_config import PerformanceTaskType, ResponseType from apps.activities.domain.response_values import PhrasalTemplateFieldType -from apps.activities.domain.scores_reports import ReportType, SubscaleItemType +from apps.activities.domain.scores_reports import ReportType, Score, SubscaleItemType, SubscaleSetting from apps.activities.errors import ( IncorrectConditionItemError, IncorrectConditionItemIndexError, @@ -20,9 +19,14 @@ IncorrectSectionPrintItemTypeError, IncorrectSubscaleInsideSubscaleError, IncorrectSubscaleItemError, + SubscaleDoesNotExist, SubscaleInsideSubscaleError, + SubscaleItemDoesNotExist, SubscaleItemScoreError, SubscaleItemTypeError, + SubscaleItemTypeItemDoesNotExist, + SubscaleNameDoesNotExist, + SubscaleSettingDoesNotExist, ) @@ -40,29 +44,52 @@ def validate_item_flow(values: dict): else: # check if condition item order is less than current item order # noqa: E501 condition_item_index = item_names.index(condition.item_name) + condition_source_item = items[condition_item_index] + item_type = condition_source_item.config.type if condition_item_index > index: raise IncorrectConditionItemIndexError() # check if condition item type is correct - if items[condition_item_index].response_type not in [ - ResponseType.SINGLESELECT, - ResponseType.MULTISELECT, - ResponseType.SLIDER, - ]: + if condition_source_item.response_type not in ResponseType.conditional_logic_types(): raise IncorrectConditionLogicItemTypeError() # check if condition option ids are correct - if condition.type in list(SingleSelectConditionType) or condition.type in list( - MultiSelectConditionType - ): - option_values = [ - str(option.value) for option in items[condition_item_index].response_values.options - ] - if str(condition.payload.option_value) not in option_values: + if item_type in ResponseType.option_based(): + if item_type in ResponseType.options_mapped_on_value(): + option_value_attr = "value" + selected_option = str(condition.payload.option_value) + else: + option_value_attr = "id" + selected_option = str(condition.payload.option_value) + + option_values = [] + for option in condition_source_item.response_values.options: + option_value = getattr(option, option_value_attr) + option_values.append(str(option_value)) + + if selected_option not in option_values: raise IncorrectConditionOptionError() + return values +def validate_subscale_setting_match_reports(report: Score, subscale_setting: SubscaleSetting): + report_subscale_linked = report.subscale_name + subscales = subscale_setting.subscales + if not subscales: + raise SubscaleDoesNotExist() + + linked_subscale = next((subscale for subscale in subscales if subscale.name == report_subscale_linked), None) + if not linked_subscale: + raise SubscaleNameDoesNotExist() + elif not linked_subscale.items: + raise SubscaleItemDoesNotExist() + else: + has_non_subscale_items = any(item.type == SubscaleItemType.ITEM for item in linked_subscale.items) + if not has_non_subscale_items: + raise SubscaleItemTypeItemDoesNotExist() + + def validate_score_and_sections(values: dict): # noqa: C901 items = values.get("items", []) item_names = [item.name for item in items] @@ -78,6 +105,13 @@ def validate_score_and_sections(values: dict): # noqa: C901 for report in list(scores): score_item_ids.append(report.id) + if report.scoring_type == "score": + subscale_setting = values.get("subscale_setting") + if not subscale_setting: # report of type score exist then we need a subscale setting + raise SubscaleSettingDoesNotExist() + else: + validate_subscale_setting_match_reports(report, subscale_setting) + # check if all item names are same as values.name for item in report.items_score: if item not in item_names: diff --git a/src/apps/activities/domain/response_type_config.py b/src/apps/activities/domain/response_type_config.py index 5504df1138c..3348e04f4d2 100644 --- a/src/apps/activities/domain/response_type_config.py +++ b/src/apps/activities/domain/response_type_config.py @@ -1,4 +1,4 @@ -from enum import Enum +from enum import StrEnum from typing import Literal from pydantic import Field, NonNegativeInt, PositiveInt, validator @@ -31,7 +31,7 @@ from apps.shared.domain import PublicModel -class ResponseType(str, Enum): +class ResponseType(StrEnum): TEXT = "text" PARAGRAPHTEXT = "paragraphText" SINGLESELECT = "singleSelect" @@ -75,6 +75,39 @@ def get_non_response_types(cls): cls.UNITY, ) + @classmethod + def conditional_logic_types(cls): + return ( + cls.DATE, + cls.NUMBERSELECT, + cls.TIME, + cls.TIMERANGE, + cls.SINGLESELECTROWS, + cls.MULTISELECTROWS, + cls.SLIDERROWS, + cls.SINGLESELECT, + cls.MULTISELECT, + cls.SLIDER, + ) + + @classmethod + def options_mapped_on_value(cls) -> list[str]: + return [ + cls.SINGLESELECT, + cls.MULTISELECT, + ] + + @classmethod + def options_mapped_on_id(cls) -> list[str]: + return [ + cls.SINGLESELECTROWS, + cls.MULTISELECTROWS, + ] + + @classmethod + def option_based(cls) -> list[str]: + return cls.options_mapped_on_id() + cls.options_mapped_on_value() + class AdditionalResponseOption(PublicModel): text_input_option: bool @@ -235,12 +268,12 @@ class UnityConfig(PublicModel): file: str | None -class InputType(str, Enum): +class InputType(StrEnum): GYROSCOPE = "gyroscope" TOUCH = "touch" -class Phase(str, Enum): +class Phase(StrEnum): PRACTICE = "practice" TEST = "test" @@ -287,12 +320,12 @@ class BlockConfiguration(PublicModel): order: list[StimulusConfigId] -class SamplingMethod(str, Enum): +class SamplingMethod(StrEnum): RANDOMIZE_ORDER = "randomize-order" FIXED_ORDER = "fixed-order" -class BlockType(str, Enum): +class BlockType(StrEnum): TEST = "test" PRACTICE = "practice" @@ -329,14 +362,14 @@ class FlankerConfig(PublicModel): block_type: BlockType -class ABTrailsOrder(str, Enum): +class ABTrailsOrder(StrEnum): FIRST = "first" SECOND = "second" THIRD = "third" FOURTH = "fourth" -class ABTrailsDeviceType(str, Enum): +class ABTrailsDeviceType(StrEnum): TABLET = "tablet" MOBILE = "mobile" @@ -401,7 +434,7 @@ def validate_nodes(cls, value, values) -> ABTrailsNodes | None: return value -class PerformanceTaskType(str, Enum): +class PerformanceTaskType(StrEnum): FLANKER = "flanker" GYROSCOPE = "gyroscope" TOUCH = "touch" diff --git a/src/apps/activities/domain/response_values.py b/src/apps/activities/domain/response_values.py index c4d59824cb0..88ef75e5435 100644 --- a/src/apps/activities/domain/response_values.py +++ b/src/apps/activities/domain/response_values.py @@ -1,4 +1,4 @@ -from enum import Enum +from enum import StrEnum from typing import Literal from pydantic import Field, NonNegativeInt, root_validator, validator @@ -41,13 +41,13 @@ from apps.shared.domain import PublicModel, validate_color, validate_image, validate_uuid -class PhrasalTemplateFieldType(str, Enum): +class PhrasalTemplateFieldType(StrEnum): SENTENCE = "sentence" ITEM_RESPONSE = "item_response" LINE_BREAK = "line_break" -class PhrasalTemplateDisplayMode(str, Enum): +class PhrasalTemplateDisplayMode(StrEnum): BULLET_LIST = "bullet_list" SENTENCE = "sentence" BULLET_LIST_OPTION_ROW = "bullet_list_option_row" diff --git a/src/apps/activities/domain/scores_reports.py b/src/apps/activities/domain/scores_reports.py index ea24fac2fe7..229ce277d48 100644 --- a/src/apps/activities/domain/scores_reports.py +++ b/src/apps/activities/domain/scores_reports.py @@ -1,5 +1,4 @@ import enum -from enum import Enum from pydantic import Field, PositiveInt, validator @@ -24,12 +23,17 @@ from apps.shared.domain.custom_validations import sanitize_string -class CalculationType(str, Enum): +class CalculationType(enum.StrEnum): SUM = "sum" AVERAGE = "average" PERCENTAGE = "percentage" +class ScoringType(enum.StrEnum): + SCORE = "score" + RAW_SCORE = "raw_score" + + class ScoreConditionalLogic(PublicModel): name: str id: str @@ -46,7 +50,7 @@ def validate_string(cls, value): return value -class ReportType(str, enum.Enum): +class ReportType(enum.StrEnum): score = "score" section = "section" @@ -60,6 +64,8 @@ class Score(PublicModel): message: str | None = None items_print: list[str] | None = Field(default_factory=list) conditional_logic: list[ScoreConditionalLogic] | None = None + scoring_type: ScoringType | None = None + subscale_name: str | None = None @validator("conditional_logic") def validate_conditional_logic(cls, value, values): @@ -164,7 +170,7 @@ class ScoreConditionalLogicMobile(PublicModel): conditions: list[ScoreCondition] -class SubscaleCalculationType(str, Enum): +class SubscaleCalculationType(enum.StrEnum): SUM = "sum" AVERAGE = "average" @@ -190,7 +196,7 @@ def validate_age_lookup(cls, value): return validate_age_subscale(value) -class SubscaleItemType(str, Enum): +class SubscaleItemType(enum.StrEnum): ITEM = "item" SUBSCALE = "subscale" diff --git a/src/apps/activities/errors.py b/src/apps/activities/errors.py index ec1036dd679..a7a5b8d7484 100644 --- a/src/apps/activities/errors.py +++ b/src/apps/activities/errors.py @@ -256,6 +256,18 @@ class MultiSelectNoneOptionError(ValidationError): message = _("No more than 1 none option is not allowed for multiselect.") +class IncorrectTimeRange(ValidationError): + message = _("Incorrect timerange") + + +class IncorrectMinTimeRange(ValidationError): + message = _("Mix timerange was not passed") + + +class IncorrectMaxTimeRange(ValidationError): + message = _("Max timerange was not passed") + + class FlowDoesNotExist(NotFoundError): message = _("Flow does not exist.") @@ -270,3 +282,38 @@ class IncorrectPhrasalTemplateItemTypeError(ValidationError): class IncorrectPhrasalTemplateItemIndexError(ValidationError): message = _("Invalid item index for activity item inside phrasal template") + + +class SubscaleIsNotLinked(ValidationError): + message = _("The scoring_type is score but no suscale_name string pased") + code = _("no_subscale_items_exist") + + +class SubscaleDoesNotExist(ValidationError): + message = _("The scoring_type is score but there are no subscales") + code = _("no_subscale_linked") + + +class SubscaleNameDoesNotExist(ValidationError): + message = _("The lookup table with the passed name does not exist in subscale settings") + code = _("no_subscale_name_exist") + + +class SubscaleDataDoesNotExist(ValidationError): + message = _("The scoring_type is score but the subscale data does not exist") + code = _("no_subscaledata_exist") + + +class SubscaleSettingDoesNotExist(ValidationError): + message = _("The scoring_type is score but there are no subscale settings associated with activity") + code = _("no_subscale_setting_exist") + + +class SubscaleItemDoesNotExist(ValidationError): + message = _("The linked subscale should contain at least one item") + code = _("no_items_exist") + + +class SubscaleItemTypeItemDoesNotExist(ValidationError): + message = _("The linked subscale should contain at least one non-subscale type item") + code = _("no_subscale_type_items_exist") diff --git a/src/apps/activities/services/activity_item_change.py b/src/apps/activities/services/activity_item_change.py index 96a23404ead..31ca0e002c3 100644 --- a/src/apps/activities/services/activity_item_change.py +++ b/src/apps/activities/services/activity_item_change.py @@ -5,7 +5,17 @@ from apps.activities.domain.activity_history import ActivityHistoryFull, ActivityItemHistoryFull from apps.activities.domain.activity_item_history import ActivityItemHistoryChange from apps.activities.domain.conditional_logic import ConditionalLogic -from apps.activities.domain.conditions import Condition, MinMaxPayload, OptionPayload, ValuePayload +from apps.activities.domain.conditions import ( + Condition, + DateRangePayload, + MinMaxPayload, + MinMaxSliderRowPayload, + MinMaxTimePayload, + OptionPayload, + SingleDatePayload, + SingleTimePayload, + ValuePayload, +) from apps.activities.domain.response_type_config import AdditionalResponseOption, ResponseType from apps.shared.changes_generator import BaseChangeGenerator @@ -13,7 +23,7 @@ RGT = TypeVar("RGT", None, ActivityHistoryFull, ActivityItemHistoryFull) -class ChangeStatusEnum(str, enum.Enum): +class ChangeStatusEnum(enum.StrEnum): ADDED = "added" UPDATED = "updated" REMOVED = "removed" @@ -260,11 +270,29 @@ def __get_payload(condition: Condition) -> str: return condition.payload.option_value elif isinstance(condition.payload, ValuePayload): return str(condition.payload.value) + elif isinstance(condition.payload, SingleDatePayload): + return condition.payload.date.isoformat() + elif isinstance(condition.payload, DateRangePayload): + if condition.payload.minDate and condition.payload.maxDate: + return f"Between {condition.payload.minDate.isoformat()} and {condition.payload.maxDate.isoformat()}" + elif isinstance(condition.payload, MinMaxTimePayload): + if condition.payload.minTime and condition.payload.maxTime: + minTime = f"{condition.payload.minTime.hour}:{condition.payload.minTime.minute:02d}" + maxTime = f"{condition.payload.maxTime.hour}:{condition.payload.maxTime.minute:02d}" + return f"Between {minTime} and {maxTime}" + elif isinstance(condition.payload, SingleTimePayload): + if condition.payload.time: + return f"{condition.payload.time.hour}:{condition.payload.time.minute:02d}" elif isinstance(condition.payload, MinMaxPayload): min_value = condition.payload.min_value max_value = condition.payload.max_value return f"{min_value} and {max_value}" - return "true" if condition.payload.value else "false" + elif isinstance(condition.payload, MinMaxSliderRowPayload): + return f"Between {condition.payload.minValue} and {condition.payload.maxValue}" + elif hasattr(condition.payload, "value"): + return str(condition.payload.value) + + return "Unknown" class ActivityItemChangeService(BaseChangeGenerator): diff --git a/src/apps/activities/tests/fixtures/conditional_logic.py b/src/apps/activities/tests/fixtures/conditional_logic.py index 306efb7d83d..d656d397592 100644 --- a/src/apps/activities/tests/fixtures/conditional_logic.py +++ b/src/apps/activities/tests/fixtures/conditional_logic.py @@ -1,19 +1,43 @@ import pytest +from apps.activities.domain import conditions as cnd from apps.activities.domain.conditional_logic import ConditionalLogic, Match -from apps.activities.domain.conditions import ConditionType, EqualCondition, ValuePayload from apps.activities.tests.utils import DEFAULT_ITEM_NAME @pytest.fixture -def condition_equal() -> EqualCondition: - return EqualCondition( +def condition_equal() -> cnd.EqualCondition: + return cnd.EqualCondition( item_name=DEFAULT_ITEM_NAME, - type=ConditionType.EQUAL, - payload=ValuePayload(value=1), + type=cnd.ConditionType.EQUAL, + payload=cnd.ValuePayload(value=1), ) @pytest.fixture -def conditional_logic(condition_equal: EqualCondition) -> ConditionalLogic: +def condition_between() -> cnd.BetweenCondition: + return cnd.BetweenCondition( + item_name=DEFAULT_ITEM_NAME, type=cnd.ConditionType.BETWEEN, payload=cnd.MinMaxPayload(min_value=0, max_value=2) + ) + + +@pytest.fixture +def condition_rows_outside_of() -> cnd.OutsideOfCondition: + return cnd.OutsideOfCondition( + item_name=DEFAULT_ITEM_NAME, payload=cnd.MinMaxPayloadRow(min_value=0, max_value=10, row_index=0) + ) + + +@pytest.fixture +def conditional_logic_equal(condition_equal: cnd.EqualCondition) -> ConditionalLogic: return ConditionalLogic(match=Match.ALL, conditions=[condition_equal]) + + +@pytest.fixture +def conditional_logic_between(condition_between: cnd.BetweenCondition) -> ConditionalLogic: + return ConditionalLogic(math=Match.ALL, conditions=[condition_between]) + + +@pytest.fixture +def conditional_logic_rows_outside_of(condition_rows_outside_of: cnd.OutsideOfCondition) -> ConditionalLogic: + return ConditionalLogic(math=Match.ALL, conditions=[condition_rows_outside_of]) diff --git a/src/apps/activities/tests/fixtures/scores_reports.py b/src/apps/activities/tests/fixtures/scores_reports.py index cf73250dfba..1898ef9824a 100644 --- a/src/apps/activities/tests/fixtures/scores_reports.py +++ b/src/apps/activities/tests/fixtures/scores_reports.py @@ -48,6 +48,30 @@ def score() -> Score: ) +@pytest.fixture +def score_with_subscale() -> Score: + return Score( + type=ReportType.score, + name="testscore type score", + id=SCORE_ID, + calculation_type=CalculationType.SUM, + scoring_type="score", + subscale_name="subscale type score", + ) + + +@pytest.fixture +def score_with_subscale_raw() -> Score: + return Score( + type=ReportType.score, + name="testscore type score", + id=SCORE_ID, + calculation_type=CalculationType.SUM, + scoring_type="raw_score", + subscale_name=None, + ) + + @pytest.fixture def section_conditional_logic() -> SectionConditionalLogic: return SectionConditionalLogic( @@ -76,6 +100,15 @@ def scores_and_reports(score: Score, section: Section) -> ScoresAndReports: ) +@pytest.fixture +def scores_and_reports_raw_score(score_with_subscale_raw: Score, section: Section) -> ScoresAndReports: + return ScoresAndReports( + generate_report=True, + show_score_summary=True, + reports=[score_with_subscale_raw, section], + ) + + @pytest.fixture def subscale_item() -> SubscaleItem: return SubscaleItem(name="activity_item_1", type=SubscaleItemType.ITEM) @@ -90,6 +123,26 @@ def subscale(subscale_item: SubscaleItem) -> Subscale: ) +@pytest.fixture +def subscale_score_type() -> Subscale: + return Subscale( + name="subscale type score", + scoring=SubscaleCalculationType.AVERAGE, + items=[SubscaleItem(name="subscale_item", type=SubscaleItemType.ITEM)], + ) + + +@pytest.fixture +def scores_and_reports_lookup_scores( + score_with_subscale: Score, section: Section, subscale: Subscale +) -> ScoresAndReports: + return ScoresAndReports( + generate_report=True, + show_score_summary=True, + reports=[score_with_subscale], + ) + + @pytest.fixture def subscale_item_type_subscale(subscale: Subscale) -> SubscaleItem: # Depends on subscalke because name should contain subscale item @@ -99,7 +152,9 @@ def subscale_item_type_subscale(subscale: Subscale) -> SubscaleItem: @pytest.fixture def subscale_with_item_type_subscale(subscale_item_type_subscale: SubscaleItem) -> Subscale: return Subscale( - name="subscale type subscale", items=[subscale_item_type_subscale], scoring=SubscaleCalculationType.AVERAGE + name="subscale type subscale", + scoring=SubscaleCalculationType.AVERAGE, + items=[subscale_item_type_subscale], ) @@ -111,6 +166,14 @@ def subscale_setting(subscale: Subscale) -> SubscaleSetting: ) +@pytest.fixture +def subscale_setting_score_type(subscale_score_type: Subscale) -> SubscaleSetting: + return SubscaleSetting( + calculate_total_score=SubscaleCalculationType.AVERAGE, + subscales=[subscale_score_type], + ) + + @pytest.fixture def subscale_total_score_table() -> list[TotalScoreTable]: return [ diff --git a/src/apps/activities/tests/unit/domain/test_activity_item_create.py b/src/apps/activities/tests/unit/domain/test_activity_item_create.py index 8158aecec4e..7aab778d997 100644 --- a/src/apps/activities/tests/unit/domain/test_activity_item_create.py +++ b/src/apps/activities/tests/unit/domain/test_activity_item_create.py @@ -28,23 +28,10 @@ from apps.shared.domain.custom_validations import InvalidImageError -def test_create_activity_item_conditional_logic_not_valid_response_type_config( - base_item_data, phrasal_template_config, phrasal_template_with_text_response_values, conditional_logic -) -> None: - with pytest.raises(errors.IncorrectConditionLogicItemTypeError): - ActivityItemCreate( - **base_item_data.dict(), - config=phrasal_template_config, - response_type=ResponseType.PHRASAL_TEMPLATE, - conditional_logic=conditional_logic, - response_values=phrasal_template_with_text_response_values, - ) - - def test_create_activity_item_conditional_logic_can_not_be_hidden( base_item_data, single_select_config, - conditional_logic, + conditional_logic_equal, single_select_response_values, ) -> None: base_item_data.is_hidden = True @@ -52,7 +39,7 @@ def test_create_activity_item_conditional_logic_can_not_be_hidden( ActivityItemCreate( **base_item_data.dict(), config=single_select_config, - conditional_logic=conditional_logic, + conditional_logic=conditional_logic_equal, response_values=single_select_response_values, response_type=ResponseType.SINGLESELECT, ) @@ -610,3 +597,140 @@ def test_create_message_item__sanitize_question(message_item_create): data["question"] = {"en": "One Two"} item = ActivityItemCreate(**data) assert item.question["en"] == "One Two" + + +def test_single_select_logic(base_item_data, request) -> None: + config = request.getfixturevalue("single_select_config") + cnd_logic = request.getfixturevalue("conditional_logic_equal") + response_values = request.getfixturevalue("single_select_response_values") + + ActivityItemCreate( + **base_item_data.dict(), + config=config, + response_type=ResponseType.SINGLESELECT, + conditional_logic=cnd_logic, + response_values=response_values, + ) + + +def test_multi_select_logic(base_item_data, request) -> None: + config = request.getfixturevalue("multi_select_config") + cnd_logic = request.getfixturevalue("conditional_logic_equal") + response_values = request.getfixturevalue("multi_select_response_values") + + ActivityItemCreate( + **base_item_data.dict(), + config=config, + response_type=ResponseType.MULTISELECT, + conditional_logic=cnd_logic, + response_values=response_values, + ) + + +def test_slider_logic(base_item_data, request) -> None: + config = request.getfixturevalue("slider_config") + cnd_logic = request.getfixturevalue("conditional_logic_between") + response_values = request.getfixturevalue("slider_response_values") + + ActivityItemCreate( + **base_item_data.dict(), + config=config, + response_type=ResponseType.SLIDER, + conditional_logic=cnd_logic, + response_values=response_values, + ) + + +def test_time_logic(base_item_data, request) -> None: + config = request.getfixturevalue("time_config") + cnd_logic = request.getfixturevalue("conditional_logic_between") + + ActivityItemCreate( + **base_item_data.dict(), + config=config, + response_type=ResponseType.TIME, + conditional_logic=cnd_logic, + response_values=None, + ) + + +def test_time_range_logic(base_item_data, request) -> None: + config = request.getfixturevalue("time_range_config") + cnd_logic = request.getfixturevalue("conditional_logic_between") + + ActivityItemCreate( + **base_item_data.dict(), + config=config, + response_type=ResponseType.TIMERANGE, + conditional_logic=cnd_logic, + response_values=None, + ) + + +def test_number_select_logic(base_item_data, request) -> None: + config = request.getfixturevalue("number_selection_config") + cnd_logic = request.getfixturevalue("conditional_logic_between") + response_values = request.getfixturevalue("number_selection_response_values") + + ActivityItemCreate( + **base_item_data.dict(), + config=config, + response_type=ResponseType.NUMBERSELECT, + conditional_logic=cnd_logic, + response_values=response_values, + ) + + +def test_date_logic(base_item_data, request) -> None: + config = request.getfixturevalue("date_config") + cnd_logic = request.getfixturevalue("conditional_logic_equal") + + ActivityItemCreate( + **base_item_data.dict(), + config=config, + response_type=ResponseType.DATE, + conditional_logic=cnd_logic, + response_values=None, + ) + + +def test_single_select_row_logic(base_item_data, request) -> None: + config = request.getfixturevalue("single_select_row_config") + cnd_logic = request.getfixturevalue("conditional_logic_equal") + response_values = request.getfixturevalue("single_select_row_response_values") + + ActivityItemCreate( + **base_item_data.dict(), + config=config, + response_type=ResponseType.SINGLESELECTROWS, + conditional_logic=cnd_logic, + response_values=response_values, + ) + + +def test_multi_select_row_logic(base_item_data, request) -> None: + config = request.getfixturevalue("multi_select_row_config") + cnd_logic = request.getfixturevalue("conditional_logic_equal") + response_values = request.getfixturevalue("multi_select_row_response_values") + + ActivityItemCreate( + **base_item_data.dict(), + config=config, + response_type=ResponseType.MULTISELECTROWS, + conditional_logic=cnd_logic, + response_values=response_values, + ) + + +def test_slider_rows_logic(base_item_data, request) -> None: + config = request.getfixturevalue("slider_rows_config") + cnd_logic = request.getfixturevalue("conditional_logic_rows_outside_of") + response_values = request.getfixturevalue("slider_rows_response_values") + + ActivityItemCreate( + **base_item_data.dict(), + config=config, + response_type=ResponseType.SLIDERROWS, + conditional_logic=cnd_logic, + response_values=response_values, + ) diff --git a/src/apps/activities/tests/unit/domain/test_custom_validation.py b/src/apps/activities/tests/unit/domain/test_custom_validation.py index e914fea49aa..331761bf84a 100644 --- a/src/apps/activities/tests/unit/domain/test_custom_validation.py +++ b/src/apps/activities/tests/unit/domain/test_custom_validation.py @@ -1,18 +1,32 @@ from typing import cast import pytest +from pydantic import ValidationError from apps.activities.domain.activity_create import ActivityItemCreate from apps.activities.domain.conditional_logic import ConditionalLogic from apps.activities.domain.conditions import ( + BetweenCondition, Condition, ConditionType, EqualCondition, EqualToOptionCondition, + GreaterThanCondition, + LessThanCondition, + NotEqualCondition, OptionPayload, + OutsideOfCondition, + SingleDatePayload, + SingleTimePayload, # Added for correct payload handling + TimePayload, + TimePayloadType, ValuePayload, ) -from apps.activities.domain.custom_validation import validate_item_flow, validate_score_and_sections, validate_subscales +from apps.activities.domain.custom_validation import ( + validate_item_flow, + validate_score_and_sections, + validate_subscales, +) from apps.activities.domain.response_type_config import ResponseType, SingleSelectionConfig from apps.activities.domain.scores_reports import ( ReportType, @@ -41,6 +55,7 @@ IncorrectSectionPrintItemTypeError, IncorrectSubscaleInsideSubscaleError, IncorrectSubscaleItemError, + IncorrectTimeRange, SubscaleInsideSubscaleError, SubscaleItemScoreError, SubscaleItemTypeError, @@ -75,10 +90,10 @@ def items() -> list[ActivityItemCreate]: is_hidden=False, conditional_logic=ConditionalLogic( conditions=[ - EqualCondition( + EqualToOptionCondition( item_name=item_name, - type=ConditionType.EQUAL, - payload=ValuePayload(value=1), + type=ConditionType.EQUAL_TO_OPTION, + payload=OptionPayload(option_value=1), ) ] ), @@ -139,6 +154,88 @@ def test_incorrect_conditional_option(self, items: list[ActivityItemCreate]): with pytest.raises(IncorrectConditionOptionError): validate_item_flow(values) + @pytest.mark.parametrize( + "payload", + (SingleTimePayload(time={"hours": 1, "minutes": 0}),), + ) + def test_validator_successful_create_eq_condition(self, payload): + EqualCondition( + item_name="test", + type=ConditionType.EQUAL, + payload=payload, + ) + + @pytest.mark.parametrize( + "payload", + (TimePayload(type=TimePayloadType.START_TIME, value="01:00"),), + ) + def test_validator_successful_create_ne_condition(self, payload): + NotEqualCondition( + item_name="test", + type=ConditionType.NOT_EQUAL, + payload=payload, + ) + + @pytest.mark.parametrize( + "payload", + (TimePayload(type=TimePayloadType.START_TIME, value="01:00"),), + ) + def test_validator_successful_create_lt_condition(self, payload): + LessThanCondition( + item_name="test", + type=ConditionType.LESS_THAN, + payload=payload, + ) + + @pytest.mark.parametrize( + "payload", + (TimePayload(type=TimePayloadType.START_TIME, value="01:00"),), + ) + def test_validator_successful_create_gt_condition(self, payload): + GreaterThanCondition( + item_name="test", + type=ConditionType.GREATER_THAN, + payload=payload, + ) + + @pytest.mark.parametrize( + "payload", + (TimePayload(type=TimePayloadType.START_TIME, value="01:00"),), + ) + def test_validator_successful_create_between_condition(self, payload): + BetweenCondition( + item_name="test", + type=ConditionType.BETWEEN, + payload=payload, + ) + + @pytest.mark.parametrize( + "payload", + (TimePayload(type=TimePayloadType.START_TIME, value="01:00"),), + ) + def test_validator_successful_create_outside_condition(self, payload): + OutsideOfCondition( + item_name="test", + type=ConditionType.OUTSIDE_OF, + payload=payload, + ) + + def test_single_date_payload_invalid_date(self): + with pytest.raises(ValidationError): + SingleDatePayload(date="1970-99-01") + + def test_single_time_payload_invalid_hours(self): + with pytest.raises(ValueError): + SingleTimePayload(time={"hours": 80, "minutes": 0}) + + def test_single_time_payload_incorrect_time_range(self): + with pytest.raises(IncorrectTimeRange): + SingleTimePayload(time={"hours": 3, "minutes": 0}, min_value="03:00", max_value="02:00") + + def test_single_time_payload_unknown_item_type(self): + with pytest.raises(ValidationError): + SingleTimePayload(time="unknown_item_type", min_value="01:00", max_value="02:00") + class TestValidateScoreAndSections: def test_successful_validation( diff --git a/src/apps/activity_assignments/service.py b/src/apps/activity_assignments/service.py index 10136eda9b5..f1db62b9c3f 100644 --- a/src/apps/activity_assignments/service.py +++ b/src/apps/activity_assignments/service.py @@ -167,7 +167,6 @@ async def send_email_notification( respondent_subject: SubjectSchema = subjects[respondent_subject_id] language = respondent_subject.language or "en" - template_name = self._get_email_template_name(language) domain = settings.service.urls.frontend.web_base path = settings.service.urls.frontend.applet_home @@ -180,12 +179,12 @@ async def send_email_notification( message = MessageSchema( recipients=[respondent_subject.email], subject=self._get_email_assignment_subject(language), - body=service.get_template( - path=template_name, + body=service.get_localized_html_template( + template_name=self._get_email_template_name(), + language=language, first_name=respondent_subject.first_name, applet_name=applet.display_name, link=link, - language=language, activity_or_flows_names=activities, ), ) @@ -431,8 +430,8 @@ async def check_if_auto_assigned(self, activity_or_flow_id: uuid.UUID) -> bool | return await ActivityAssigmentCRUD(self.session).check_if_auto_assigned(activity_or_flow_id) @staticmethod - def _get_email_template_name(language: str) -> str: - return f"new_activity_assignments_{language}" + def _get_email_template_name() -> str: + return "new_activity_assignments" @staticmethod def _get_email_assignment_subject(language: str) -> str: diff --git a/src/apps/activity_assignments/tests/test_assignments.py b/src/apps/activity_assignments/tests/test_assignments.py index 24c50037b35..56f4a5f3e82 100644 --- a/src/apps/activity_assignments/tests/test_assignments.py +++ b/src/apps/activity_assignments/tests/test_assignments.py @@ -1,4 +1,5 @@ import http +import re import uuid import pytest @@ -22,6 +23,7 @@ from apps.shared.enums import Language from apps.shared.test import BaseTest from apps.shared.test.client import TestClient +from apps.subjects.crud import SubjectsCrud from apps.subjects.db.schemas import SubjectSchema from apps.subjects.domain import Subject, SubjectCreate, SubjectFull from apps.subjects.services import SubjectsService @@ -117,11 +119,19 @@ async def applet_one_shell_account(session: AsyncSession, applet_one: AppletFull ) +def message_language(message_body: str): + assert message_body + match_result = re.search(r"", message_body) + assert match_result + return match_result.group(1) + + class TestActivityAssignments(BaseTest): activities_assignments_applet = "/assignments/applet/{applet_id}" user_activities_assignments = "/users/me/assignments/{applet_id}" activities_assign_unassign_applet = "/assignments/applet/{applet_id}" + @pytest.mark.parametrize("invite_language", ["en", "fr", "el"]) async def test_create_one_assignment( self, client: TestClient, @@ -131,7 +141,10 @@ async def test_create_one_assignment( tom_applet_one_subject, session: AsyncSession, mailbox: TestMail, + invite_language: str, ): + await SubjectsCrud(session).update(SubjectSchema(id=tom_applet_one_subject.id, language=invite_language)) + client.login(tom) assignments_create = ActivitiesAssignmentsCreate( @@ -166,7 +179,7 @@ async def test_create_one_assignment( assert str(model.id) == assignment["id"] assert model.activity_id == applet_one.activities[0].id assert mailbox.mails[0].recipients == [tom_applet_one_subject.email] - assert mailbox.mails[0].subject == "Assignment Notification" + assert message_language(mailbox.mails[0].body) == invite_language async def test_create_assignment_fail_wrong_activity( self, diff --git a/src/apps/answers/crud/answers.py b/src/apps/answers/crud/answers.py index 5a4a688e1bf..be34a4cdc2f 100644 --- a/src/apps/answers/crud/answers.py +++ b/src/apps/answers/crud/answers.py @@ -100,6 +100,7 @@ async def get_list(self, **filters) -> list[Answer]: """ @param filters: see supported filters: _AnswerListFilter """ + self.session.expire_all() query = select(AnswerSchema).join(AnswerSchema.answer_item).options(contains_eager(AnswerSchema.answer_item)) _filters = _AnswerListFilter().get_clauses(**filters) diff --git a/src/apps/answers/domain/answers.py b/src/apps/answers/domain/answers.py index 612d8da1150..7d59542e545 100644 --- a/src/apps/answers/domain/answers.py +++ b/src/apps/answers/domain/answers.py @@ -41,6 +41,10 @@ class Answer(InternalModel): activity_history_id: str respondent_id: uuid.UUID | None is_flow_completed: bool | None = False + target_subject_id: uuid.UUID | None = None + source_subject_id: uuid.UUID | None = None + input_subject_id: uuid.UUID | None = None + relation: str | None = None migrated_data: dict | None = None created_at: datetime.datetime diff --git a/src/apps/answers/service.py b/src/apps/answers/service.py index 40c3a05155f..6f7f7553aeb 100644 --- a/src/apps/answers/service.py +++ b/src/apps/answers/service.py @@ -60,6 +60,7 @@ SummaryActivityFlow, ) from apps.answers.domain.answers import ( + Answer, AnswersCopyCheckResult, AppletSubmission, FilesCopyCheckResult, @@ -1620,7 +1621,9 @@ async def send_alert_mail(users: List[UserSchema]): MessageSchema( recipients=email_list, subject="Response alert", - body=mail_service.get_template(path="response_alert_en", domain=domain), + body=mail_service.get_localized_html_template( + template_name="response_alert", language="en", domain=domain + ), ) ) @@ -1950,9 +1953,14 @@ async def is_flow_finished(self, submit_id: uuid.UUID, answer_id: uuid.UUID) -> return self._is_activity_last_in_flow(applet_full, activity_id, flow_id) async def create_report( - self, submit_id: uuid.UUID, answer_id: uuid.UUID | None = None + self, + submit_id: uuid.UUID, + answer_id: uuid.UUID | None = None, ) -> ReportServerResponse | None: - answers = await AnswersCRUD(self.answers_session).get_by_submit_id(submit_id, answer_id) + filters = dict(submit_id=submit_id) + if answer_id: + filters.update(answer_id=answer_id) + answers = await AnswersCRUD(self.answers_session).get_list(**filters) if not answers: return None applet_id_version: str = answers[0].applet_history_id @@ -1963,8 +1971,8 @@ async def create_report( # If answers only on performance tasks if not answers_for_report: return None - answer_map = dict((answer.id, answer) for answer in answers_for_report) initial_answer = answers_for_report[0] + assert initial_answer.target_subject_id applet = await AppletsCRUD(self.session).get_by_id(initial_answer.applet_id) user_info = await self._get_user_info(initial_answer.target_subject_id) @@ -1976,12 +1984,10 @@ async def create_report( ) encryption = ReportServerEncryption(applet.report_public_key) - responses, user_public_keys = await self._prepare_responses(answer_map) + responses = await self._prepare_responses(answers_for_report) data = dict( responses=responses, - userPublicKeys=user_public_keys, - userPublicKey=user_public_keys[0], now=datetime.datetime.utcnow().strftime("%x"), user=user_info, applet=applet_full, @@ -2047,17 +2053,18 @@ async def _get_user_info(self, subject_id: uuid.UUID): tag=subject.tag, ) - async def _prepare_responses(self, answers_map: dict[uuid.UUID, AnswerSchema]) -> tuple[list[dict], list[str]]: - answer_items = await AnswerItemsCRUD(self.answers_session).get_respondent_submits_by_answer_ids( - list(answers_map.keys()) - ) - + async def _prepare_responses(self, answers: list[Answer]) -> list[dict]: responses = list() - for answer_item in answer_items: - answer = answers_map[answer_item.answer_id] - activity_id, version = answer.activity_history_id.split("_") - responses.append(dict(activityId=activity_id, answer=answer_item.answer)) - return responses, [ai.user_public_key for ai in answer_items] + for answer in answers: + activity_id = HistoryAware().id_from_history_id(answer.activity_history_id) + responses.append( + dict( + activityId=activity_id, + answer=answer.answer_item.answer, + userPublicKey=answer.answer_item.user_public_key, + ) + ) + return responses async def _prepare_loris_responses(self, answers_map: dict[uuid.UUID, AnswerSchema]) -> list[dict]: answer_items = await AnswerItemsCRUD(self.answers_session).get_respondent_submits_by_answer_ids( diff --git a/src/apps/applets/api/applets.py b/src/apps/applets/api/applets.py index 1e6e013ec0b..c674b76827e 100644 --- a/src/apps/applets/api/applets.py +++ b/src/apps/applets/api/applets.py @@ -188,7 +188,9 @@ async def applet_duplicate( await CheckAccessService(session, user.id).check_applet_duplicate_access(applet_id) applet_for_duplicate = await service.get_by_id_for_duplicate(applet_id) - applet = await service.duplicate(applet_for_duplicate, schema.display_name, schema.encryption) + applet = await service.duplicate( + applet_for_duplicate, schema.display_name, schema.encryption, schema.include_report_server + ) return Response(result=public_detail.Applet.from_orm(applet)) diff --git a/src/apps/applets/domain/applet_create_update.py b/src/apps/applets/domain/applet_create_update.py index bbe40e0df2c..dbff1ff7653 100644 --- a/src/apps/applets/domain/applet_create_update.py +++ b/src/apps/applets/domain/applet_create_update.py @@ -108,3 +108,4 @@ class AppletReportConfiguration(AppletReportConfigurationBase, InternalModel): class AppletDuplicateRequest(InternalModel): display_name: str encryption: Encryption + include_report_server: bool = False diff --git a/src/apps/applets/router.py b/src/apps/applets/router.py index ca7e01e8902..2484c6ad469 100644 --- a/src/apps/applets/router.py +++ b/src/apps/applets/router.py @@ -102,7 +102,7 @@ router.post( "/{applet_id}/duplicate", - description="""This endpoint using for duplicate existing applet""", + description="""Duplicate an existing applet, and optionally its report server configuration""", response_model_by_alias=True, response_model=Response[public_detail.Applet], status_code=status.HTTP_201_CREATED, diff --git a/src/apps/applets/service/applet.py b/src/apps/applets/service/applet.py index 3ad2f4db552..f23aff5e535 100644 --- a/src/apps/applets/service/applet.py +++ b/src/apps/applets/service/applet.py @@ -25,7 +25,7 @@ from apps.applets.domain.applet_duplicate import AppletDuplicate from apps.applets.domain.applet_full import AppletFull from apps.applets.domain.applet_link import AppletLink, CreateAccessLink -from apps.applets.domain.base import Encryption +from apps.applets.domain.base import AppletReportConfigurationBase, Encryption from apps.applets.errors import ( AccessLinkDoesNotExistError, AppletAlreadyExist, @@ -220,6 +220,7 @@ async def duplicate( applet_exist: AppletDuplicate, new_name: str, encryption: Encryption, + include_report_server: bool, ): activity_key_id_map = dict() @@ -233,7 +234,7 @@ async def duplicate( ) manager_role = Role.EDITOR if has_editor else Role.MANAGER - create_data = self._prepare_duplicate(applet_exist, new_name, encryption) + create_data = self._prepare_duplicate(applet_exist, new_name, encryption, include_report_server) applet = await self._create(create_data, self.user_id) @@ -253,7 +254,9 @@ async def duplicate( return applet @staticmethod - def _prepare_duplicate(applet_exist: AppletDuplicate, new_name: str, encryption: Encryption) -> AppletCreate: + def _prepare_duplicate( + applet_exist: AppletDuplicate, new_name: str, encryption: Encryption, include_report_server: bool + ) -> AppletCreate: activities = list() for activity in applet_exist.activities: activities.append( @@ -290,7 +293,20 @@ def _prepare_duplicate(applet_exist: AppletDuplicate, new_name: str, encryption: ) ) + report_server_config = ( + AppletReportConfigurationBase( + report_server_ip=applet_exist.report_server_ip, + report_public_key=applet_exist.report_public_key, + report_include_user_id=applet_exist.report_include_user_id, + report_include_case_id=applet_exist.report_include_case_id, + report_email_body=applet_exist.report_email_body, + ).dict() + if include_report_server + else {} + ) + return AppletCreate( + **report_server_config, display_name=new_name, description=applet_exist.description, about=applet_exist.about, diff --git a/src/apps/applets/tests/test_applet.py b/src/apps/applets/tests/test_applet.py index fca45e772ee..1d1e5befdca 100644 --- a/src/apps/applets/tests/test_applet.py +++ b/src/apps/applets/tests/test_applet.py @@ -23,7 +23,7 @@ ) from apps.activity_assignments.crud.assignments import ActivityAssigmentCRUD from apps.activity_assignments.db.schemas import ActivityAssigmentSchema -from apps.applets.domain.applet_create_update import AppletCreate, AppletUpdate +from apps.applets.domain.applet_create_update import AppletCreate, AppletReportConfiguration, AppletUpdate from apps.applets.domain.applet_full import AppletFull from apps.applets.domain.base import AppletReportConfigurationBase, Encryption from apps.applets.errors import AppletAlreadyExist, AppletVersionNotFoundError @@ -245,6 +245,72 @@ async def test_duplicate_applet( assert response.status_code == http.HTTPStatus.CREATED assert response.json()["result"]["displayName"] == new_name + async def test_duplicate_applet_default_exclude_report_server_config( + self, client: TestClient, tom: User, applet_one: AppletFull, encryption: Encryption, session: AsyncSession + ): + await AppletService(session, tom.id).set_report_configuration( + applet_one.id, + AppletReportConfiguration( + report_server_ip="ipaddress", + report_public_key="public key", + report_recipients=["recipient1", "recipient1"], + report_include_user_id=True, + report_include_case_id=True, + report_email_body="email body", + ), + ) + + client.login(tom) + new_name = "New Name" + response = await client.post( + self.applet_duplicate_url.format(pk=applet_one.id), + data=dict(display_name=new_name, encryption=encryption.dict()), + ) + assert response.status_code == http.HTTPStatus.CREATED + + result = response.json()["result"] + assert result["displayName"] == new_name + assert result["reportServerIp"] == "" + assert result["reportPublicKey"] == "" + assert result["reportRecipients"] == [] + assert result["reportIncludeUserId"] is False + assert result["reportIncludeCaseId"] is False + assert result["reportEmailBody"] == "" + + async def test_duplicate_applet_include_report_server_config( + self, client: TestClient, tom: User, applet_one: AppletFull, encryption: Encryption, session: AsyncSession + ): + await AppletService(session, tom.id).set_report_configuration( + applet_one.id, + AppletReportConfiguration( + report_server_ip="ipaddress", + report_public_key="public key", + report_recipients=["recipient1", "recipient1"], + report_include_user_id=True, + report_include_case_id=True, + report_email_body="email body", + ), + ) + + client.login(tom) + new_name = "New Name" + response = await client.post( + self.applet_duplicate_url.format(pk=applet_one.id), + data=dict(display_name=new_name, encryption=encryption.dict(), include_report_server=True), + ) + assert response.status_code == http.HTTPStatus.CREATED + + result = response.json()["result"] + assert result["displayName"] == new_name + assert result["reportServerIp"] == "ipaddress" + assert result["reportPublicKey"] == "public key" + assert result["reportIncludeUserId"] is True + assert result["reportIncludeCaseId"] is True + assert result["reportEmailBody"] == "email body" + + # Recipients are excluded + assert result["reportRecipients"] == [] + async def test_duplicate_applet_name_already_exists( self, client: TestClient, tom: User, applet_one: AppletFull, encryption: Encryption ): diff --git a/src/apps/applets/tests/test_applet_activity_items.py b/src/apps/applets/tests/test_applet_activity_items.py index edb9f546506..6b633d4f04b 100644 --- a/src/apps/applets/tests/test_applet_activity_items.py +++ b/src/apps/applets/tests/test_applet_activity_items.py @@ -16,6 +16,7 @@ from apps.activities.domain.scores_reports import ( ScoreConditionalLogic, ScoresAndReports, + ScoringType, SectionConditionalLogic, Subscale, SubScaleLookupTable, @@ -522,6 +523,38 @@ async def test_create_applet__activity_with_subscale_settings_with_subscale_look result = resp.json()["result"] assert result["activities"][0]["subscaleSetting"] == sub_setting.dict(by_alias=True) + async def test_create_applet__activity_with_subscale_settings_and_lookup_table_and_score_report_lookup_scoring( + self, + client: TestClient, + applet_minimal_data: AppletCreate, + single_select_item_create_with_score: ActivityItemCreate, + tom: User, + subscale_setting_score_type: SubscaleSetting, + subscale_lookup_table: list[SubScaleLookupTable], + scores_and_reports_lookup_scores: ScoresAndReports, + ): + client.login(tom) + data = applet_minimal_data.copy(deep=True) + sub_setting = subscale_setting_score_type.copy(deep=True) + + # Update subscale setting with item name and lookup table + sub_setting.subscales[0].items[0].name = single_select_item_create_with_score.name # type: ignore[index] + sub_setting.subscales[0].subscale_table_data = subscale_lookup_table # type: ignore[index] + + data.activities[0].items = [single_select_item_create_with_score] + data.activities[0].subscale_setting = sub_setting + data.activities[0].scores_and_reports = scores_and_reports_lookup_scores + + # Make the POST request + resp = await client.post(self.applet_create_url.format(owner_id=tom.id), data=data) + + # Assertions + assert resp.status_code == http.HTTPStatus.CREATED + result = resp.json()["result"] + assert result["activities"][0]["subscaleSetting"] == sub_setting.dict(by_alias=True) + assert result["activities"][0]["scoresAndReports"]["reports"][0]["scoringType"] == ScoringType.SCORE.value + assert result["activities"][0]["scoresAndReports"]["reports"][0]["subscaleName"] == "subscale type score" + async def test_create_applet__activity_with_subscale_settings_with_invalid_subscale_lookup_table_age( self, client: TestClient, diff --git a/src/apps/authentication/api/auth.py b/src/apps/authentication/api/auth.py index 7582b62ba1a..b220b8e6777 100644 --- a/src/apps/authentication/api/auth.py +++ b/src/apps/authentication/api/auth.py @@ -1,8 +1,8 @@ import uuid from datetime import datetime +import jwt from fastapi import Body, Depends -from jose import JWTError, jwt from pydantic import ValidationError from apps.authentication.deps import get_current_token, get_current_user @@ -82,7 +82,7 @@ async def refresh_access_token( settings.authentication.refresh_token.secret_key, algorithms=[settings.authentication.algorithm], ) - except JWTError: + except jwt.PyJWTError: # check transition key transition_key = settings.authentication.refresh_token.transition_key transition_expire_date = settings.authentication.refresh_token.transition_expire_date @@ -93,14 +93,14 @@ async def refresh_access_token( raise payload = jwt.decode( schema.refresh_token, - transition_key, + str(transition_key), algorithms=[settings.authentication.algorithm], ) regenerate_refresh_token = True token_data = TokenPayload(**payload) - except (JWTError, ValidationError) as e: + except (jwt.PyJWTError, ValidationError) as e: raise InvalidRefreshToken() from e # Check if the token is in the blacklist diff --git a/src/apps/authentication/deps.py b/src/apps/authentication/deps.py index b12413e8bf1..717aa9cf597 100644 --- a/src/apps/authentication/deps.py +++ b/src/apps/authentication/deps.py @@ -1,9 +1,9 @@ from datetime import datetime +import jwt from fastapi import Depends, HTTPException, status from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm from fastapi.websockets import WebSocket -from jose import JWTError, jwt from pydantic import EmailStr, ValidationError from starlette.requests import Request @@ -46,7 +46,7 @@ async def get_current_user_for_ws(websocket: WebSocket, session=Depends(get_sess if datetime.utcfromtimestamp(token_data.exp) < datetime.utcnow(): raise AuthenticationError - except (JWTError, ValidationError): + except (jwt.PyJWTError, ValidationError): raise AuthenticationError # Check if the token is in the blacklist @@ -77,7 +77,7 @@ async def _get_current_token( if datetime.utcfromtimestamp(token_payload.exp) < datetime.utcnow(): raise AuthenticationError - except (JWTError, ValidationError): + except (jwt.PyJWTError, ValidationError): raise AuthenticationError return InternalToken(payload=token_payload, raw_token=token) diff --git a/src/apps/authentication/domain/token/internal.py b/src/apps/authentication/domain/token/internal.py index 93c97723f11..a346af4ea54 100644 --- a/src/apps/authentication/domain/token/internal.py +++ b/src/apps/authentication/domain/token/internal.py @@ -1,19 +1,19 @@ import uuid -from enum import Enum +from enum import StrEnum from pydantic import EmailStr from apps.shared.domain.base import InternalModel -class TokenPurpose(str, Enum): +class TokenPurpose(StrEnum): """This enumeration is used for internal needs (cache, ...).""" ACCESS = "access" REFRESH = "refresh" -class JWTClaim(str, Enum): +class JWTClaim(StrEnum): sub = "sub" jti = "jti" exp = "exp" diff --git a/src/apps/authentication/services/security.py b/src/apps/authentication/services/security.py index 524198e7c84..cdf3416b379 100644 --- a/src/apps/authentication/services/security.py +++ b/src/apps/authentication/services/security.py @@ -1,13 +1,13 @@ import uuid from datetime import datetime, timedelta, timezone -from jose import jwt +import jwt from apps.authentication.domain.login import UserLoginRequest from apps.authentication.domain.token import InternalToken, JWTClaim, TokenPayload, TokenPurpose from apps.authentication.errors import BadCredentials, InvalidCredentials from apps.authentication.services.core import TokensService -from apps.shared.passlib import get_password_hash, verify +from apps.shared.bcrypt import get_password_hash, verify from apps.users.cruds.user import UsersCRUD from apps.users.domain import User from config import settings diff --git a/src/apps/authentication/tests/test_auth.py b/src/apps/authentication/tests/test_auth.py index e4ce4b93e60..4464aff35d3 100644 --- a/src/apps/authentication/tests/test_auth.py +++ b/src/apps/authentication/tests/test_auth.py @@ -3,8 +3,8 @@ import uuid from unittest import mock +import jwt import pytest -from jose import jwt from pytest_mock import MockerFixture from sqlalchemy.ext.asyncio import AsyncSession diff --git a/src/apps/authentication/tests/unit/test_auth_deps.py b/src/apps/authentication/tests/unit/test_auth_deps.py index 8eaeee849f1..4d49b9136d8 100644 --- a/src/apps/authentication/tests/unit/test_auth_deps.py +++ b/src/apps/authentication/tests/unit/test_auth_deps.py @@ -1,11 +1,11 @@ import uuid from typing import cast +import jwt import pytest from fastapi import HTTPException from fastapi.security import OAuth2PasswordRequestForm from fastapi.websockets import WebSocket -from jose import JWTError from pytest_mock import MockerFixture from sqlalchemy.ext.asyncio import AsyncSession @@ -68,7 +68,7 @@ async def test_get_current_user_for_ws__expired_time_is_less_than_now( async def test_get_current_user_for_ws__internal_error( session: AsyncSession, mock_ws: WebSocket, mocker: MockerFixture, access_token: str ): - mocker.patch("jose.jwt.decode", side_effect=JWTError()) + mocker.patch("jwt.decode", side_effect=jwt.PyJWTError()) mock_ws.headers["sec-websocket-protocol"] = f"{settings.authentication.token_type}|{access_token}" # type: ignore[index] with pytest.raises(AuthenticationError): await get_current_user_for_ws(mock_ws, session=session) @@ -113,7 +113,7 @@ async def test_get_current_refresh_token(refresh_token: str, user: User): async def test_get_current_access_token__internal_error(access_token: str, mocker: MockerFixture): - mocker.patch("jose.jwt.decode", side_effect=JWTError()) + mocker.patch("jwt.decode", side_effect=jwt.PyJWTError()) coro = get_current_token() with pytest.raises(AuthenticationError): await coro(token=access_token) diff --git a/src/apps/file/domain.py b/src/apps/file/domain.py index bb308badf29..0d122a3dff6 100644 --- a/src/apps/file/domain.py +++ b/src/apps/file/domain.py @@ -5,7 +5,7 @@ from apps.shared.domain import PublicModel -class WebmTargetExtenstion(str, enum.Enum): +class WebmTargetExtenstion(enum.StrEnum): MP3 = ".mp3" MP4 = ".mp4" diff --git a/src/apps/file/enums.py b/src/apps/file/enums.py index 85ddf62c754..91f9302a561 100644 --- a/src/apps/file/enums.py +++ b/src/apps/file/enums.py @@ -1,6 +1,6 @@ -from enum import Enum +from enum import StrEnum -class FileScopeEnum(str, Enum): +class FileScopeEnum(StrEnum): CONTENT = "content" ANSWER = "answer" diff --git a/src/apps/healthcheck/domain.py b/src/apps/healthcheck/domain.py index 11e020afdcb..385c06ff3da 100644 --- a/src/apps/healthcheck/domain.py +++ b/src/apps/healthcheck/domain.py @@ -5,7 +5,7 @@ from apps.shared.domain import PublicModel -class EmergencyMessageType(str, enum.Enum): +class EmergencyMessageType(enum.StrEnum): info = "info" warning = "warning" blocker = "blocker" diff --git a/src/apps/invitations/constants.py b/src/apps/invitations/constants.py index 2059883a779..d3cf4b266ae 100644 --- a/src/apps/invitations/constants.py +++ b/src/apps/invitations/constants.py @@ -1,7 +1,7 @@ -from enum import Enum +from enum import StrEnum -class InvitationStatus(str, Enum): +class InvitationStatus(StrEnum): PENDING = "pending" APPROVED = "approved" DECLINED = "declined" diff --git a/src/apps/invitations/domain.py b/src/apps/invitations/domain.py index 9fe1b3830a6..17ffab9d7e4 100644 --- a/src/apps/invitations/domain.py +++ b/src/apps/invitations/domain.py @@ -1,6 +1,6 @@ import uuid from datetime import datetime -from enum import Enum +from enum import StrEnum from pydantic import EmailStr, Extra, Field, root_validator, validator @@ -15,9 +15,10 @@ class Applet(PublicModel): display_name: str -class InvitationLanguage(str, Enum): - EN = "en" - FR = "fr" +class InvitationLanguage(StrEnum): + EN = "en" # English + FR = "fr" # French + EL = "el" # Greek class InvitationRequest(InternalModel): diff --git a/src/apps/invitations/services.py b/src/apps/invitations/services.py index aaa4eb43190..f91068c355a 100644 --- a/src/apps/invitations/services.py +++ b/src/apps/invitations/services.py @@ -136,22 +136,21 @@ async def send_respondent_invitation( invitation_internal: InvitationRespondent = InvitationRespondent.from_orm(invitation_schema) applet = await AppletsCRUD(self.session).get_by_id(invitation_internal.applet_id) - template_name = self._get_email_template_name(invited_user_id, schema.language) # Send email to the user service = MailingService() message = MessageSchema( recipients=[schema.email], subject=self._get_invitation_subject(applet), - body=service.get_template( - path=template_name, + body=service.get_localized_html_template( + template_name=self._get_email_template_name(invited_user_id), + language=schema.language, first_name=subject.first_name, last_name=subject.last_name, applet_name=applet.display_name, role=invitation_internal.role, link=self._get_invitation_url_by_role(invitation_internal.role), key=invitation_internal.key, - language=schema.language, ), ) _ = asyncio.create_task(service.send(message)) @@ -212,8 +211,6 @@ async def send_reviewer_invitation( applet = await AppletsCRUD(self.session).get_by_id(invitation_internal.applet_id) - template_name = self._get_email_template_name(invited_user_id, schema.language) - await WorkspaceService(self.session, self._user.id).update_workspace_name(self._user, schema.workspace_prefix) # Send email to the user @@ -221,15 +218,15 @@ async def send_reviewer_invitation( message = MessageSchema( recipients=[schema.email], subject=self._get_invitation_subject(applet), - body=service.get_template( - path=template_name, + body=service.get_localized_html_template( + template_name=self._get_email_template_name(invited_user_id), + language=schema.language, first_name=schema.first_name, last_name=schema.last_name, applet_name=applet.display_name, role=invitation_internal.role, link=self._get_invitation_url_by_role(invitation_internal.role), key=invitation_internal.key, - language=schema.language, ), ) @@ -286,8 +283,9 @@ async def send_managers_invitation( else: invitation_schema = await self.invitations_crud.save(InvitationSchema(**payload)) invitation_internal = InvitationManagers.from_orm(invitation_schema) + applet = await AppletsCRUD(self.session).get_by_id(invitation_internal.applet_id) - template_name = self._get_email_template_name(invited_user_id, schema.language) + await WorkspaceService(self.session, self._user.id).update_workspace_name(self._user, schema.workspace_prefix) # Send email to the user @@ -295,15 +293,15 @@ async def send_managers_invitation( message = MessageSchema( recipients=[schema.email], subject=self._get_invitation_subject(applet), - body=service.get_template( - path=template_name, + body=service.get_localized_html_template( + template_name=self._get_email_template_name(invited_user_id), + language=schema.language, first_name=schema.first_name, last_name=schema.last_name, applet_name=applet.display_name, role=invitation_internal.role, link=self._get_invitation_url_by_role(invitation_internal.role), key=invitation_internal.key, - language=schema.language, ), ) @@ -427,10 +425,10 @@ async def delete_for_respondents(self, applet_ids: list[uuid.UUID]): await InvitationCRUD(self.session).delete_by_applet_ids(self._user.email, applet_ids, roles) @staticmethod - def _get_email_template_name(invited_user_id: uuid.UUID | None, language: str) -> str: + def _get_email_template_name(invited_user_id: uuid.UUID | None) -> str: if not invited_user_id: - return f"invitation_new_user_{language}" - return f"invitation_registered_user_{language}" + return "invitation_new_user" + return "invitation_registered_user" async def get_meta(self, key: uuid.UUID) -> dict | None: return await InvitationCRUD(self.session).get_meta(key) diff --git a/src/apps/invitations/test_invite.py b/src/apps/invitations/test_invite.py index 3749cf194c4..3a36de67c95 100644 --- a/src/apps/invitations/test_invite.py +++ b/src/apps/invitations/test_invite.py @@ -1,7 +1,8 @@ import http import json +import re import uuid -from typing import Literal +from typing import Any, Literal import pytest from pydantic import EmailStr @@ -14,6 +15,7 @@ from apps.applets.service.applet import AppletService from apps.invitations.crud import InvitationCRUD from apps.invitations.domain import ( + InvitationLanguage, InvitationManagersRequest, InvitationRespondentRequest, InvitationReviewerRequest, @@ -29,6 +31,7 @@ ) from apps.mailing.services import TestMail from apps.shared.test import BaseTest +from apps.shared.test.client import TestClient from apps.subjects.crud import SubjectsCrud from apps.subjects.domain import Subject, SubjectCreate from apps.subjects.services import SubjectsService @@ -40,7 +43,7 @@ @pytest.fixture -async def applet_one_with_public_link(session: AsyncSession, applet_one: AppletFull, tom): +async def applet_one_with_public_link(session: AsyncSession, applet_one: AppletFull, tom: User): srv = AppletService(session, tom.id) await srv.create_access_link(applet_one.id, CreateAccessLink(require_login=False)) applet = await srv.get_full_applet(applet_one.id) @@ -49,7 +52,7 @@ async def applet_one_with_public_link(session: AsyncSession, applet_one: AppletF @pytest.fixture -async def applet_one_with_link(session: AsyncSession, applet_one: AppletFull, tom): +async def applet_one_with_link(session: AsyncSession, applet_one: AppletFull, tom: User): srv = AppletService(session, tom.id) await srv.create_access_link(applet_one.id, CreateAccessLink(require_login=True)) applet = await srv.get_full_applet(applet_one.id) @@ -58,19 +61,23 @@ async def applet_one_with_link(session: AsyncSession, applet_one: AppletFull, to @pytest.fixture -async def applet_one_lucy_manager(session: AsyncSession, applet_one: AppletFull, tom, lucy) -> AppletFull: +async def applet_one_lucy_manager(session: AsyncSession, applet_one: AppletFull, tom: User, lucy: User) -> AppletFull: await UserAppletAccessService(session, tom.id, applet_one.id).add_role(lucy.id, Role.MANAGER) return applet_one @pytest.fixture -async def applet_one_lucy_coordinator(session: AsyncSession, applet_one: AppletFull, tom, lucy) -> AppletFull: +async def applet_one_lucy_coordinator( + session: AsyncSession, applet_one: AppletFull, tom: User, lucy: User +) -> AppletFull: await UserAppletAccessService(session, tom.id, applet_one.id).add_role(lucy.id, Role.COORDINATOR) return applet_one @pytest.fixture -async def applet_one_lucy_respondent(session: AsyncSession, applet_one: AppletFull, tom, lucy) -> AppletFull: +async def applet_one_lucy_respondent( + session: AsyncSession, applet_one: AppletFull, tom: User, lucy: User +) -> AppletFull: await UserAppletAccessService(session, tom.id, applet_one.id).add_role(lucy.id, Role.RESPONDENT) return applet_one @@ -93,7 +100,7 @@ def user_create_data() -> UserCreateRequest: @pytest.fixture -def subject_ids(tom, tom_applet_one_subject) -> list[str]: +def subject_ids(tom: User, tom_applet_one_subject: Subject) -> list[uuid.UUID]: return [tom_applet_one_subject.id] @@ -176,6 +183,13 @@ async def applet_one_lucy_subject(session: AsyncSession, applet_one: AppletFull, ) +def message_language(message_body: str): + assert message_body + match_result = re.search(r"", message_body) + assert match_result + return match_result.group(1) + + class TestInvite(BaseTest): fixtures = [ "invitations/fixtures/invitations.json", @@ -196,7 +210,143 @@ class TestInvite(BaseTest): shell_acc_create_url = f"{invitation_list}/{{applet_id}}/shell-account" shell_acc_invite_url = f"{invitation_list}/{{applet_id}}/subject" - async def test_invitation_list(self, client, tom): + @pytest.mark.parametrize("invite_language", ["en", "fr", "el"]) + @pytest.mark.parametrize( + "inviter_type,invitee_type,invite_status", + [ + ("admin", "manager", http.HTTPStatus.OK), + ("admin", "coordinator", http.HTTPStatus.OK), + ("admin", "editor", http.HTTPStatus.OK), + ("admin", "reviewer", http.HTTPStatus.OK), + ("admin", "respondent", http.HTTPStatus.OK), + ("manager", "manager", http.HTTPStatus.OK), + ("manager", "coordinator", http.HTTPStatus.OK), + ("manager", "editor", http.HTTPStatus.OK), + ("manager", "reviewer", http.HTTPStatus.OK), + ("manager", "respondent", http.HTTPStatus.OK), + ("coordinator", "respondent", http.HTTPStatus.OK), + ("coordinator", "reviewer", http.HTTPStatus.OK), + ("coordinator", "manager", http.HTTPStatus.FORBIDDEN), + ("editor", "respondent", http.HTTPStatus.FORBIDDEN), + ], + ) + async def test_invite_existing_user( + self, + client: TestClient, + session: AsyncSession, + tom: User, + lucy: User, + user: User, + applet_one: AppletFull, + invitation_manager_data: InvitationManagersRequest, + invitation_coordinator_data: InvitationManagersRequest, + invitation_editor_data: InvitationManagersRequest, + invitation_reviewer_data: InvitationReviewerRequest, + invitation_respondent_data: InvitationRespondentRequest, + mailbox: TestMail, + invite_language: str, + inviter_type: str, + invitee_type: str, + invite_status: str, + ): + if inviter_type == "admin": + client.login(tom) + elif inviter_type == "manager": + client.login(lucy) + await UserAppletAccessService(session, tom.id, applet_one.id).add_role(lucy.id, Role.MANAGER) + elif inviter_type == "coordinator": + client.login(lucy) + await UserAppletAccessService(session, tom.id, applet_one.id).add_role(lucy.id, Role.COORDINATOR) + elif inviter_type == "editor": + client.login(lucy) + await UserAppletAccessService(session, tom.id, applet_one.id).add_role(lucy.id, Role.EDITOR) + else: + raise Exception(f"Invalid inviter_type: {inviter_type}") + + payload: Any + if invitee_type == "manager": + url = self.invite_manager_url + payload = invitation_manager_data + elif invitee_type == "coordinator": + url = self.invite_manager_url + payload = invitation_coordinator_data + elif invitee_type == "editor": + url = self.invite_manager_url + payload = invitation_editor_data + elif invitee_type == "reviewer": + url = self.invite_reviewer_url + payload = invitation_reviewer_data + elif invitee_type == "respondent": + url = self.invite_respondent_url + payload = invitation_respondent_data + else: + raise Exception(f"Invalid invitee_type: {invitee_type}") + payload.language = InvitationLanguage(invite_language) + + response = await client.post(url.format(applet_id=str(applet_one.id)), payload) + assert response.status_code == invite_status + + if invite_status == http.HTTPStatus.OK: + assert response.json()["result"]["userId"] == str(user.id) + assert len(mailbox.mails) == 1 + assert message_language(mailbox.mails[0].body) == invite_language + assert len(mailbox.mails[0].recipients) == 1 + assert mailbox.mails[0].recipients[0] == payload.email + + if invitee_type == "respondent": + assert response.json()["result"]["userId"] == str(user.id) + assert response.json()["result"]["tag"] is not None + assert response.json()["result"]["tag"] == payload.tag + + @pytest.mark.parametrize("invite_language", ["en", "fr"]) + @pytest.mark.parametrize("invitee_type", ["manager", "coordinator", "editor", "reviewer", "respondent"]) + async def test_invite_new_user( + self, + client: TestClient, + tom: User, + applet_one: AppletFull, + invitation_manager_data: InvitationManagersRequest, + invitation_coordinator_data: InvitationManagersRequest, + invitation_editor_data: InvitationManagersRequest, + invitation_reviewer_data: InvitationReviewerRequest, + invitation_respondent_data: InvitationRespondentRequest, + mailbox: TestMail, + invite_language: str, + invitee_type: str, + ): + client.login(tom) + + payload: Any + if invitee_type == "manager": + payload = invitation_manager_data + url = self.invite_manager_url + elif invitee_type == "coordinator": + payload = invitation_coordinator_data + url = self.invite_manager_url + elif invitee_type == "editor": + payload = invitation_editor_data + url = self.invite_manager_url + elif invitee_type == "reviewer": + payload = invitation_reviewer_data + url = self.invite_reviewer_url + elif invitee_type == "respondent": + payload = invitation_respondent_data + url = self.invite_respondent_url + else: + raise Exception(f"Invalid invitee_type: {invitee_type}") + payload.email = EmailStr(f"new{invitation_manager_data.email}") + payload.language = InvitationLanguage(invite_language) + + response = await client.post( + url.format(applet_id=str(applet_one.id)), + payload, + ) + assert response.status_code == http.HTTPStatus.OK + assert not response.json()["result"]["userId"] + assert len(mailbox.mails) == 1 + assert message_language(mailbox.mails[0].body) == invite_language + + async def test_invitation_list(self, client: TestClient, tom: User): client.login(tom) response = await client.get(self.invitation_list) @@ -204,7 +354,7 @@ async def test_invitation_list(self, client, tom): assert len(response.json()["result"]) == 3 - async def test_applets_invitation_list(self, client, tom, applet_one): + async def test_applets_invitation_list(self, client: TestClient, tom: User, applet_one: AppletFull): client.login(tom) response = await client.get( @@ -215,7 +365,9 @@ async def test_applets_invitation_list(self, client, tom, applet_one): assert len(response.json()["result"]) == 2 - async def test_invitation_retrieve(self, client, applet_one, lucy, applet_one_lucy_subject): + async def test_invitation_retrieve( + self, client: TestClient, applet_one: AppletFull, lucy: User, applet_one_lucy_subject: Subject + ): client.login(lucy) response = await client.get(self.invitation_detail.format(key="6a3ab8e6-f2fa-49ae-b2db-197136677da6")) assert response.status_code == http.HTTPStatus.OK @@ -227,7 +379,7 @@ async def test_invitation_retrieve(self, client, applet_one, lucy, applet_one_lu assert response.json()["result"]["tag"] is not None assert response.json()["result"]["title"] == "PHD" - async def test_private_invitation_retrieve(self, client, applet_one_with_link, lucy): + async def test_private_invitation_retrieve(self, client: TestClient, applet_one_with_link: AppletFull, lucy: User): client.login(lucy) response = await client.get(self.private_invitation_detail.format(key=applet_one_with_link.link)) @@ -236,80 +388,12 @@ async def test_private_invitation_retrieve(self, client, applet_one_with_link, l assert response.json()["result"]["appletId"] == str(applet_one_with_link.id) assert response.json()["result"]["role"] == Role.RESPONDENT - async def test_admin_invite_manager_success( - self, client, invitation_manager_data, tom, user, applet_one, mailbox: TestMail - ): - client.login(tom) - response = await client.post( - self.invite_manager_url.format(applet_id=str(applet_one.id)), - invitation_manager_data, - ) - assert response.status_code == http.HTTPStatus.OK - assert response.json()["result"]["userId"] == str(user.id) - assert len(mailbox.mails) == 1 - assert mailbox.mails[0].recipients == [invitation_manager_data.email] - assert mailbox.mails[0].subject == "Applet 1 invitation" - - async def test_admin_invite_coordinator_success( - self, client, invitation_coordinator_data, tom, user, applet_one, mailbox: TestMail - ): - client.login(tom) - response = await client.post( - self.invite_manager_url.format(applet_id=str(applet_one.id)), - invitation_coordinator_data, - ) - assert response.status_code == http.HTTPStatus.OK - assert response.json()["result"]["userId"] == str(user.id) - assert len(mailbox.mails) == 1 - assert mailbox.mails[0].recipients == [invitation_coordinator_data.email] - - async def test_admin_invite_editor_success( - self, client, invitation_editor_data, tom, user, applet_one, mailbox: TestMail - ): - client.login(tom) - response = await client.post( - self.invite_manager_url.format(applet_id=str(applet_one.id)), - invitation_editor_data, - ) - assert response.status_code == http.HTTPStatus.OK - assert response.json()["result"]["userId"] == str(user.id) - assert response.json()["result"]["tag"] == "Team" - assert len(mailbox.mails) == 1 - assert mailbox.mails[0].recipients == [invitation_editor_data.email] - - async def test_admin_invite_reviewer_success( - self, client, invitation_reviewer_data, tom, user, applet_one, mailbox: TestMail - ): - client.login(tom) - response = await client.post( - self.invite_reviewer_url.format(applet_id=str(applet_one.id)), - invitation_reviewer_data, - ) - assert response.status_code == http.HTTPStatus.OK, response.json() - assert response.json()["result"]["userId"] == str(user.id) - assert response.json()["result"]["tag"] == "Team" - assert len(mailbox.mails) == 1 - assert mailbox.mails[0].recipients == [invitation_reviewer_data.email] - assert mailbox.mails[0].subject == "Applet 1 invitation" - - async def test_admin_invite_respondent_success( - self, client, invitation_respondent_data, tom, user, applet_one, mailbox: TestMail - ): - client.login(tom) - response = await client.post( - self.invite_respondent_url.format(applet_id=str(applet_one.id)), - invitation_respondent_data, - ) - assert response.status_code == http.HTTPStatus.OK - assert response.json()["result"]["userId"] == str(user.id) - assert response.json()["result"]["tag"] == invitation_respondent_data.tag - assert response.json()["result"]["tag"] is not None - assert len(mailbox.mails) == 1 - assert mailbox.mails[0].recipients == [invitation_respondent_data.email] - assert mailbox.mails[0].subject == "Applet 1 invitation" - async def test_admin_invite_respondent_duplicate_pending_secret_id( - self, client, invitation_respondent_data, tom, applet_one + self, + client: TestClient, + invitation_respondent_data: InvitationRespondentRequest, + tom: User, + applet_one: AppletFull, ): client.login(tom) response = await client.post( @@ -318,7 +402,7 @@ async def test_admin_invite_respondent_duplicate_pending_secret_id( ) assert response.status_code == http.HTTPStatus.OK - invitation_respondent_data.email = "patric1@gmail.com" + invitation_respondent_data.email = EmailStr("patric1@gmail.com") response = await client.post( self.invite_respondent_url.format(applet_id=str(applet_one.id)), invitation_respondent_data, @@ -329,123 +413,15 @@ async def test_admin_invite_respondent_duplicate_pending_secret_id( assert result[0]["message"] == NonUniqueValue.message assert result[0]["path"] == ["body", "secretUserId"] - async def test_manager_invite_manager_success( - self, client, invitation_manager_data, applet_one_lucy_manager, lucy, mailbox: TestMail - ): - client.login(lucy) - response = await client.post( - self.invite_manager_url.format(applet_id=str(applet_one_lucy_manager.id)), - invitation_manager_data, - ) - assert response.status_code == http.HTTPStatus.OK - - assert len(mailbox.mails) == 1 - assert mailbox.mails[0].recipients == [invitation_manager_data.email] - assert mailbox.mails[0].subject == "Applet 1 invitation" - - async def test_manager_invite_coordinator_success( - self, client, invitation_coordinator_data, applet_one_lucy_manager, lucy, mailbox: TestMail - ): - client.login(lucy) - response = await client.post( - self.invite_manager_url.format(applet_id=str(applet_one_lucy_manager.id)), - invitation_coordinator_data, - ) - assert response.status_code == http.HTTPStatus.OK - - assert len(mailbox.mails) == 1 - assert mailbox.mails[0].recipients == [invitation_coordinator_data.email] - - async def test_manager_invite_editor_success( - self, client, invitation_editor_data, applet_one_lucy_manager, lucy, mailbox: TestMail - ): - client.login(lucy) - response = await client.post( - self.invite_manager_url.format(applet_id=str(applet_one_lucy_manager.id)), - invitation_editor_data, - ) - assert response.status_code == http.HTTPStatus.OK - - assert len(mailbox.mails) == 1 - assert mailbox.mails[0].recipients == [invitation_editor_data.email] - - async def test_manager_invite_reviewer_success( - self, client, invitation_reviewer_data, lucy, applet_one_lucy_manager, mailbox - ): - client.login(lucy) - response = await client.post( - self.invite_reviewer_url.format(applet_id=str(applet_one_lucy_manager.id)), - invitation_reviewer_data, - ) - assert response.status_code == http.HTTPStatus.OK - - assert len(mailbox.mails) == 1 - assert mailbox.mails[0].recipients == [invitation_reviewer_data.email] - - async def test_manager_invite_respondent_success( - self, client, invitation_respondent_data, applet_one_lucy_manager, lucy, mailbox: TestMail - ): - client.login(lucy) - response = await client.post( - self.invite_respondent_url.format(applet_id=str(applet_one_lucy_manager.id)), - invitation_respondent_data, - ) - assert response.status_code == http.HTTPStatus.OK - - assert len(mailbox.mails) == 1 - assert mailbox.mails[0].recipients == [invitation_respondent_data.email] - - async def test_coordinator_invite_respondent_success( - self, client, invitation_respondent_data, applet_one_lucy_coordinator, lucy, mailbox: TestMail - ): - client.login(lucy) - response = await client.post( - self.invite_respondent_url.format(applet_id=str(applet_one_lucy_coordinator.id)), - invitation_respondent_data, - ) - assert response.status_code == http.HTTPStatus.OK - - assert len(mailbox.mails) == 1 - assert mailbox.mails[0].recipients == [invitation_respondent_data.email] - - async def test_coordinator_invite_reviewer_success( - self, client, invitation_reviewer_data, applet_one_lucy_coordinator, lucy, mailbox: TestMail - ): - client.login(lucy) - response = await client.post( - self.invite_reviewer_url.format(applet_id=str(applet_one_lucy_coordinator.id)), - invitation_reviewer_data, - ) - assert response.status_code == http.HTTPStatus.OK - - assert len(mailbox.mails) == 1 - assert mailbox.mails[0].recipients == [invitation_reviewer_data.email] - - async def test_coordinator_invite_manager_fail( - self, client, invitation_manager_data, applet_one_lucy_coordinator, lucy - ): - client.login(lucy) - response = await client.post( - self.invite_manager_url.format(applet_id=str(applet_one_lucy_coordinator.id)), - invitation_manager_data, - ) - - assert response.status_code == 403 - assert response.json()["result"][0]["message"] == "Access denied." - - async def test_editor_invite_respondent_fail( - self, client, invitation_respondent_data, lucy, applet_one_lucy_editor + async def test_invitation_accept_and_absorb_roles( + self, + session: AsyncSession, + client: TestClient, + lucy: User, + applet_one_lucy_roles: AppletFull, + applet_one: AppletFull, ): client.login(lucy) - response = await client.post( - self.invite_respondent_url.format(applet_id=str(applet_one_lucy_editor.id)), - invitation_respondent_data, - ) - assert response.status_code == 403 - assert response.json()["result"][0]["message"] == "Access denied to manipulate with invites of the applet." - - async def test_invitation_accept_and_absorb_roles(self, session, client, lucy, applet_one_lucy_roles, applet_one): - client.login(lucy) roles = await UserAppletAccessCRUD(session).get_user_roles_to_applet(lucy.id, applet_one.id) assert len(roles) == 3 @@ -460,7 +436,9 @@ async def test_invitation_accept_and_absorb_roles(self, session, client, lucy, a assert Role.MANAGER in roles assert Role.RESPONDENT in roles - async def test_private_invitation_accept(self, session, client, lucy, applet_one_with_link): + async def test_private_invitation_accept( + self, session: AsyncSession, client: TestClient, lucy: User, applet_one_with_link: AppletFull + ): client.login(lucy) response = await client.post(self.accept_private_url.format(key=applet_one_with_link.link)) @@ -470,21 +448,22 @@ async def test_private_invitation_accept(self, session, client, lucy, applet_one applet_id=applet_one_with_link.id, ordered_roles=[Role.RESPONDENT], ) - assert access.role == Role.RESPONDENT + assert access + assert access.role == Role.RESPONDENT.value - async def test_invitation_accept_invitation_does_not_exists(self, client, tom, uuid_zero): + async def test_invitation_accept_invitation_does_not_exists(self, client: TestClient, tom: User, uuid_zero): client.login(tom) response = await client.post(self.accept_url.format(key=uuid_zero)) assert response.status_code == http.HTTPStatus.NOT_FOUND - async def test_invitation_decline(self, client, lucy): + async def test_invitation_decline(self, client: TestClient, lucy: User): client.login(lucy) response = await client.delete(self.decline_url.format(key="6a3ab8e6-f2fa-49ae-b2db-197136677da6")) assert response.status_code == http.HTTPStatus.OK - async def test_invitation_decline_wrong_invitation_does_not_exists(self, client, tom): + async def test_invitation_decline_wrong_invitation_does_not_exists(self, client: TestClient, tom: User): client.login(tom) response = await client.delete(self.decline_url.format(key="6a3ab8e6-f2fa-49ae-b2db-197136677da9")) @@ -493,10 +472,16 @@ async def test_invitation_decline_wrong_invitation_does_not_exists(self, client, @pytest.mark.parametrize("role", (Role.MANAGER, Role.COORDINATOR, Role.EDITOR)) async def test_manager_invite_if_duplicate_email_and_role_not_accepted( - self, client, role, invitation_manager_data, applet_one_lucy_manager, lucy, mailbox: TestMail + self, + client: TestClient, + role: Role, + invitation_manager_data: InvitationManagersRequest, + applet_one_lucy_manager: AppletFull, + lucy: User, + mailbox: TestMail, ): client.login(lucy) - invitation_manager_data.role = role + invitation_manager_data.role = ManagersRole(role) response = await client.post( self.invite_manager_url.format(applet_id=str(applet_one_lucy_manager.id)), invitation_manager_data, @@ -509,12 +494,20 @@ async def test_manager_invite_if_duplicate_email_and_role_not_accepted( ) assert response.status_code == http.HTTPStatus.OK assert len(mailbox.mails) == 2 + assert message_language(mailbox.mails[0].body) == "en" + assert message_language(mailbox.mails[1].body) == "en" async def test_admin_invite_respondent_fail_if_duplicate_email( - self, client, invitation_respondent_data, tom, applet_one_lucy_respondent, lucy, mailbox: TestMail + self, + client: TestClient, + invitation_respondent_data: InvitationRespondentRequest, + tom: User, + applet_one_lucy_respondent: AppletFull, + lucy: User, + mailbox: TestMail, ): client.login(tom) - invitation_respondent_data.email = lucy.email_encrypted + invitation_respondent_data.email = EmailStr(lucy.email_encrypted) response = await client.post( self.invite_respondent_url.format(applet_id=str(applet_one_lucy_respondent.id)), invitation_respondent_data, @@ -526,10 +519,16 @@ async def test_admin_invite_respondent_fail_if_duplicate_email( assert len(mailbox.mails) == 0 async def test_fail_if_invite_manager_on_editor_role( - self, client, invitation_editor_data, tom, applet_one_lucy_manager, lucy, mailbox: TestMail + self, + client: TestClient, + invitation_editor_data: InvitationManagersRequest, + tom: User, + applet_one_lucy_manager: AppletFull, + lucy: User, + mailbox: TestMail, ): client.login(tom) - invitation_editor_data.email = lucy.email_encrypted + invitation_editor_data.email = EmailStr(lucy.email_encrypted) response = await client.post( self.invite_manager_url.format(applet_id=applet_one_lucy_manager.id), invitation_editor_data, @@ -540,45 +539,6 @@ async def test_fail_if_invite_manager_on_editor_role( assert res["message"] == ManagerInvitationExist.message assert len(mailbox.mails) == 0 - async def test_invite_not_registered_user_manager( - self, client, invitation_manager_data, tom, applet_one, mailbox: TestMail - ): - client.login(tom) - invitation_manager_data.email = f"new{invitation_manager_data.email}" - response = await client.post( - self.invite_manager_url.format(applet_id=str(applet_one.id)), - invitation_manager_data, - ) - assert response.status_code == http.HTTPStatus.OK - assert not response.json()["result"]["userId"] - assert len(mailbox.mails) == 1 - - async def test_invite_not_registered_user_reviewer( - self, client, invitation_reviewer_data, tom, applet_one, mailbox: TestMail - ): - client.login(tom) - invitation_reviewer_data.email = f"new{invitation_reviewer_data.email}" - response = await client.post( - self.invite_reviewer_url.format(applet_id=str(applet_one.id)), - invitation_reviewer_data.dict(), - ) - assert response.status_code == http.HTTPStatus.OK, response.json() - assert not response.json()["result"]["userId"] - assert len(mailbox.mails) == 1 - - async def test_invite_not_registered_user_respondent( - self, client, invitation_respondent_data, tom, applet_one, mailbox: TestMail - ): - client.login(tom) - invitation_respondent_data.email = f"new{invitation_respondent_data.email}" - response = await client.post( - self.invite_respondent_url.format(applet_id=str(applet_one.id)), - invitation_respondent_data.dict(), - ) - assert response.status_code == http.HTTPStatus.OK - assert not response.json()["result"]["userId"] - assert len(mailbox.mails) == 1 - @pytest.mark.parametrize( "status,url,method", ( @@ -587,11 +547,20 @@ async def test_invite_not_registered_user_respondent( ), ) async def test_new_user_accept_decline_invitation( - self, session, client, user_create_data, status, url, method, invitation_manager_data, tom, applet_one + self, + session: AsyncSession, + client: TestClient, + user_create_data: UserCreateRequest, + status: InvitationStatus, + url: str, + method: str, + invitation_manager_data: InvitationManagersRequest, + tom: User, + applet_one: AppletFull, ) -> None: client.login(tom) new_email = f"new{invitation_manager_data.email}" - invitation_manager_data.email = new_email + invitation_manager_data.email = EmailStr(new_email) # Send an invite response = await client.post( self.invite_manager_url.format(applet_id=str(applet_one.id)), @@ -601,7 +570,7 @@ async def test_new_user_accept_decline_invitation( assert not response.json()["result"]["userId"] invitation_key = response.json()["result"]["key"] - user_create_data.email = new_email + user_create_data.email = EmailStr(new_email) # An invited user creates an account resp = await client.post("/users", data=user_create_data.dict()) assert resp.status_code == http.HTTPStatus.CREATED @@ -618,11 +587,16 @@ async def test_new_user_accept_decline_invitation( assert inv.status == status # type: ignore[union-attr] async def test_update_invitation_for_new_user_who_registered_after_first_invitation( - self, client, user_create_data, invitation_manager_data, tom, applet_one + self, + client: TestClient, + user_create_data, + invitation_manager_data: InvitationManagersRequest, + tom: User, + applet_one: AppletFull, ) -> None: client.login(tom) new_email = f"new{invitation_manager_data.email}" - invitation_manager_data.email = new_email + invitation_manager_data.email = EmailStr(new_email) # Send an invite response = await client.post( self.invite_manager_url.format(applet_id=str(applet_one.id)), @@ -648,7 +622,12 @@ async def test_update_invitation_for_new_user_who_registered_after_first_invitat assert response.json()["result"]["userId"] == exp_user_id async def test_resend_invitation_with_updates_for_respondent_with_pending_invitation( - self, session, client, invitation_respondent_data, tom: User, applet_one: AppletFull + self, + session: AsyncSession, + client: TestClient, + invitation_respondent_data: InvitationRespondentRequest, + tom: User, + applet_one: AppletFull, ): client.login(tom) response = await client.post( @@ -669,7 +648,12 @@ async def test_resend_invitation_with_updates_for_respondent_with_pending_invita assert response.status_code == http.HTTPStatus.UNPROCESSABLE_ENTITY async def test_resend_invitation_for_respondent_with_pending_invitation_only_last_key_valid( - self, client, invitation_respondent_data, tom, applet_one, user + self, + client: TestClient, + invitation_respondent_data: InvitationRespondentRequest, + tom: User, + applet_one: AppletFull, + user: User, ): client.login(tom) response = await client.post( @@ -698,16 +682,16 @@ async def test_resend_invitation_for_respondent_with_pending_invitation_only_las async def test_send_many_pending_invitations_for_one_email_valid_only_last( self, - client, - session, - invitation_coordinator_data, - invitation_editor_data, - invitation_manager_data, - invitation_respondent_data, - invitation_reviewer_data, - tom, - applet_one, - user, + client: TestClient, + session: AsyncSession, + invitation_coordinator_data: InvitationManagersRequest, + invitation_editor_data: InvitationManagersRequest, + invitation_manager_data: InvitationManagersRequest, + invitation_respondent_data: InvitationRespondentRequest, + invitation_reviewer_data: InvitationReviewerRequest, + tom: User, + applet_one: AppletFull, + user: User, ): client.login(tom) invitations_urls = [ @@ -742,7 +726,9 @@ async def test_send_many_pending_invitations_for_one_email_valid_only_last( response = await client.get(self.invitation_detail.format(key=keys[-1])) assert response.status_code == http.HTTPStatus.OK - async def test_get_invitation_by_key_invitation_does_not_exist(self, client, tom, uuid_zero): + async def test_get_invitation_by_key_invitation_does_not_exist( + self, client: TestClient, tom: User, uuid_zero: uuid.UUID + ): client.login(tom) response = await client.get(self.invitation_detail.format(key=uuid_zero)) @@ -754,7 +740,11 @@ async def test_get_invitation_by_key_invitation_does_not_exist(self, client, tom (("decline_url", "delete"), ("accept_url", "post")), ) async def test_get_invitation_by_key_already_accpted_declined( - self, client, url: Literal["decline_url", "accept_url"], method: Literal["delete", "post"], lucy + self, + client: TestClient, + url: Literal["decline_url", "accept_url"], + method: Literal["delete", "post"], + lucy: User, ): client.login(lucy) key = "6a3ab8e6-f2fa-49ae-b2db-197136677da6" @@ -767,14 +757,18 @@ async def test_get_invitation_by_key_already_accpted_declined( assert response.status_code == http.HTTPStatus.BAD_REQUEST assert response.json()["result"][0]["message"] == InvitationAlreadyProcessed.message - async def test_get_private_invitation_by_link_does_not_exist(self, client, tom, uuid_zero): + async def test_get_private_invitation_by_link_does_not_exist( + self, client: TestClient, tom: User, uuid_zero: uuid.UUID + ): client.login(tom) response = await client.get(self.private_invitation_detail.format(key=uuid_zero)) assert response.status_code == http.HTTPStatus.NOT_FOUND assert response.json()["result"][0]["message"] == InvitationDoesNotExist.message - async def test_private_invitation_accept_invitation_does_not_exist(self, client, tom, uuid_zero): + async def test_private_invitation_accept_invitation_does_not_exist( + self, client: TestClient, tom: User, uuid_zero: uuid.UUID + ): client.login(tom) response = await client.post(self.accept_private_url.format(key=uuid_zero)) @@ -782,7 +776,12 @@ async def test_private_invitation_accept_invitation_does_not_exist(self, client, assert response.json()["result"][0]["message"] == InvitationDoesNotExist.message async def test_send_invitation_to_reviewer_invitation_already_approved( - self, client, invitation_reviewer_data, tom, applet_one, user + self, + client: TestClient, + invitation_reviewer_data: InvitationReviewerRequest, + tom: User, + applet_one: AppletFull, + user: User, ): client.login(tom) # send an invite @@ -806,7 +805,9 @@ async def test_send_invitation_to_reviewer_invitation_already_approved( assert response.status_code == http.HTTPStatus.UNPROCESSABLE_ENTITY assert response.json()["result"][0]["message"] == ManagerInvitationExist.message - async def test_send_incorrect_role_to_invite_managers(self, client, invitation_manager_data, tom, applet_one): + async def test_send_incorrect_role_to_invite_managers( + self, client: TestClient, invitation_manager_data: InvitationManagersRequest, tom: User, applet_one: AppletFull + ): client.login(tom) data = invitation_manager_data.dict() data["role"] = "notvalid" @@ -821,7 +822,12 @@ async def test_send_incorrect_role_to_invite_managers(self, client, invitation_m assert result[0]["message"] == emsg async def test_invite_reviewer_with_respondent_does_not_exist( - self, client, invitation_reviewer_data, tom, applet_one, uuid_zero + self, + client: TestClient, + invitation_reviewer_data: InvitationReviewerRequest, + tom: User, + applet_one: AppletFull, + uuid_zero: uuid.UUID, ): client.login(tom) invitation_reviewer_data.subjects = [uuid_zero] @@ -839,7 +845,14 @@ async def test_invite_reviewer_with_respondent_does_not_exist( (("accept_url", "post"), ("decline_url", "delete")), ) async def test_accept_or_decline_already_processed_invitation( - self, client, url, method, invitation_manager_data, tom, applet_one, user + self, + client: TestClient, + url: str, + method: str, + invitation_manager_data: InvitationManagersRequest, + tom: User, + applet_one: AppletFull, + user: User, ) -> None: client.login(tom) # Send an invite @@ -860,7 +873,9 @@ async def test_accept_or_decline_already_processed_invitation( resp = await client_method(getattr(self, url).format(key=invitation_key)) assert resp.status_code == http.HTTPStatus.BAD_REQUEST - async def test_shell_create_account(self, client, shell_create_data, bob: User, applet_four: AppletFull): + async def test_shell_create_account( + self, client: TestClient, shell_create_data: dict, bob: User, applet_four: AppletFull + ): client.login(bob) applet_id = str(applet_four.id) creator_id = str(bob.id) @@ -892,7 +907,9 @@ async def test_shell_create_account(self, client, shell_create_data, bob: User, ), ), ) - async def test_shell_invite(self, client, session, bob: User, applet_four: AppletFull, shell_create): + async def test_shell_invite( + self, client: TestClient, session: AsyncSession, bob: User, applet_four: AppletFull, shell_create: dict + ): client.login(bob) email = "mm@mail.com" applet_id = str(applet_four.id) @@ -910,7 +927,7 @@ async def test_shell_invite(self, client, session, bob: User, applet_four: Apple assert subject_model.language == "fr" async def test_shell_invite_no_language( - self, client, session, shell_create_data, bob: User, applet_four: AppletFull + self, client: TestClient, session: AsyncSession, shell_create_data: dict, bob: User, applet_four: AppletFull ): client.login(bob) email = "mm_english@mail.com" @@ -929,7 +946,13 @@ async def test_shell_invite_no_language( assert subject_model.language == shell_create_data["language"] async def test_invite_and_accept_invitation_as_respondent( - self, client, session, invitation_respondent_data, tom: User, applet_one: AppletFull, bill_bronson: User + self, + client: TestClient, + session: AsyncSession, + invitation_respondent_data: InvitationRespondentRequest, + tom: User, + applet_one: AppletFull, + bill_bronson: User, ): subject_crud = SubjectsCrud(session) applet_id = applet_one.id @@ -937,7 +960,7 @@ async def test_invite_and_accept_invitation_as_respondent( user_id = tom.id # Create invitation to Mike client.login(tom) - invitation_respondent_data.email = user_email + invitation_respondent_data.email = EmailStr(user_email) subjects_on_applet0 = await subject_crud.count(applet_id=applet_id) response = await client.post( self.invite_respondent_url.format(applet_id=applet_id), @@ -958,7 +981,13 @@ async def test_invite_and_accept_invitation_as_respondent( assert subjects_on_applet2 == subjects_on_applet1 async def test_invite_and_accept_invitation_as_manager( - self, client, session, invitation_manager_data, tom: User, user: UserSchema, applet_one: AppletFull + self, + client: TestClient, + session: AsyncSession, + invitation_manager_data: InvitationManagersRequest, + tom: User, + user: UserSchema, + applet_one: AppletFull, ): subject_crud = SubjectsCrud(session) applet_id = applet_one.id @@ -985,7 +1014,7 @@ async def test_invite_and_accept_invitation_as_manager( assert subjects_on_applet2 == (subjects_on_applet1 + 1) async def test_private_invitation_accept_create_subject( - self, client, session, user: User, applet_one_with_link: AppletFull + self, client: TestClient, session: AsyncSession, user: User, applet_one_with_link: AppletFull ): assert applet_one_with_link.link subject_crud = SubjectsCrud(session) @@ -1000,7 +1029,13 @@ async def test_private_invitation_accept_create_subject( assert subject async def test_move_pins_from_subject_to_user( - self, client, session, tom: User, bob: User, shell_create_data, applet_one: AppletFull + self, + client: TestClient, + session: AsyncSession, + tom: User, + bob: User, + shell_create_data: dict, + applet_one: AppletFull, ): client.login(tom) applet_id = str(applet_one.id) @@ -1026,38 +1061,14 @@ async def test_move_pins_from_subject_to_user( pins = await UserAppletAccessCRUD(session).get_workspace_pins(tom.id) assert pins[0].pinned_user_id == bob.id - @pytest.mark.skip("Not actual") - async def test_shell_invite_cant_twice(self, client, session, shell_create_data, tom: User, applet_one: AppletFull): - client.login(self.login_url, tom.email_encrypted, "Test1234!") - email = "mm@mail.com" - applet_id = str(applet_one.id) - url = self.shell_acc_create_url.format(applet_id=applet_id) - - subjects = [] - for i in range(2): - body = {**shell_create_data, "secretUserId": f"{uuid.uuid4()}"} - response = await client.post(url, body) - subject = response.json()["result"] - subjects.append(subject) - - url = self.shell_acc_invite_url.format(applet_id=applet_id) - # Invite first subject - response = await client.post(url, dict(subjectId=subjects[0]["id"], email=email)) - assert response.status_code == http.HTTPStatus.OK - # Try to invite next subject on same email - response = await client.post(url, dict(subjectId=subjects[1]["id"], email=email)) - assert response.status_code == http.HTTPStatus.UNPROCESSABLE_ENTITY - message = response.json()["result"][0]["message"] - assert message == RespondentInvitationExist.message - async def test_cant_create_invitation_with_same_secret_id_as_shell_account( self, - client, - session, + client: TestClient, + session: AsyncSession, applet_one: AppletFull, applet_one_shell_account: Subject, tom: User, - invitation_respondent_data, + invitation_respondent_data: InvitationRespondentRequest, ): client.login(tom) invitation_respondent_data.secret_user_id = applet_one_shell_account.secret_user_id @@ -1071,7 +1082,13 @@ async def test_cant_create_invitation_with_same_secret_id_as_shell_account( assert payload["result"][0]["message"] == NonUniqueValue().error async def test_shell_update_email_on_accept( - self, client, session, bob: User, lucy: User, applet_four: AppletFull, shell_create_data + self, + client: TestClient, + session: AsyncSession, + bob: User, + lucy: User, + applet_four: AppletFull, + shell_create_data: dict, ): client.login(bob) applet_id = str(applet_four.id) @@ -1103,3 +1120,50 @@ async def test_shell_update_email_on_accept( subject_model = await crud.get_by_id(subject["id"]) assert subject_model assert subject_model.email == lucy.email_encrypted + + async def test_shell_reinvite( + self, + client: TestClient, + session: AsyncSession, + bob: User, + lucy: User, + applet_four: AppletFull, + shell_create_data: dict, + mailbox: TestMail, + ): + client.login(bob) + response = await client.post(self.shell_acc_create_url.format(applet_id=str(applet_four.id)), shell_create_data) + assert response.status_code == http.HTTPStatus.OK + subject = response.json()["result"] + assert subject + + response = await client.post( + self.shell_acc_invite_url.format(applet_id=str(applet_four.id)), + dict(subjectId=subject["id"], email=lucy.email_encrypted), + ) + assert response.status_code == http.HTTPStatus.OK + assert len(mailbox.mails) == 1 + assert message_language(mailbox.mails[0].body) == "en" + invitation_key = response.json()["result"]["key"] + assert invitation_key + + client.login(lucy) + response = await client.post(self.accept_url.format(key=invitation_key)) + assert response.status_code == http.HTTPStatus.OK + + client.login(bob) + response = await client.post( + self.shell_acc_create_url.format(applet_id=str(applet_four.id)), + {**shell_create_data, "secretUserId": f"{uuid.uuid4()}"}, + ) + assert response.status_code == http.HTTPStatus.OK + subject = response.json()["result"] + assert subject + + response = await client.post( + self.shell_acc_invite_url.format(applet_id=str(applet_four.id)), + dict(subjectId=subject["id"], email=lucy.email_encrypted), + ) + assert response.status_code == http.HTTPStatus.UNPROCESSABLE_ENTITY + message = response.json()["result"][0]["message"] + assert message == RespondentInvitationExist.message diff --git a/src/apps/job/constants.py b/src/apps/job/constants.py index d3ebdc64e8f..1f0139ac394 100644 --- a/src/apps/job/constants.py +++ b/src/apps/job/constants.py @@ -1,7 +1,7 @@ import enum -class JobStatus(str, enum.Enum): +class JobStatus(enum.StrEnum): pending = "pending" in_progress = "in_progress" success = "success" diff --git a/src/apps/jsonld_converter/service/base.py b/src/apps/jsonld_converter/service/base.py index 823d13d82db..5d911341281 100644 --- a/src/apps/jsonld_converter/service/base.py +++ b/src/apps/jsonld_converter/service/base.py @@ -8,7 +8,7 @@ from apps.jsonld_converter.errors import JsonLDLoaderError, JsonLDProcessingError -class LdKeyword(str, enum.Enum): +class LdKeyword(enum.StrEnum): context = "@context" type = "@type" id = "@id" diff --git a/src/apps/jsonld_converter/service/converter.py b/src/apps/jsonld_converter/service/converter.py index 9f30790d344..3e3f3669f19 100644 --- a/src/apps/jsonld_converter/service/converter.py +++ b/src/apps/jsonld_converter/service/converter.py @@ -101,7 +101,7 @@ async def convert(self, input_: str | dict, base_url: str | None = None): return obj.export() -class ExportFormat(enum.Enum): +class ExportFormat(enum.StrEnum): zip = "zip" list = "list" diff --git a/src/apps/mailing/services.py b/src/apps/mailing/services.py index 9d2cc966444..7876dd09058 100644 --- a/src/apps/mailing/services.py +++ b/src/apps/mailing/services.py @@ -1,5 +1,5 @@ from fastapi_mail import ConnectionConfig, FastMail -from jinja2 import Environment, PackageLoader, select_autoescape +from jinja2 import Environment, PackageLoader, TemplateNotFound, select_autoescape from apps.mailing.domain import MessageSchema from config import settings @@ -62,8 +62,11 @@ async def send(self, message: MessageSchema) -> None: fm = mailing_class(self._connection) await fm.send_message(message) - def get_template(self, path: str, **kwargs): - template = self.env.get_template(f"{path}.html") - html = template.render(**kwargs) - - return html + def get_localized_html_template(self, template_name: str, language: str, **kwargs) -> str: + kwargs["language"] = language + try: + return self.env.get_template(f"{template_name}_{language}.html").render(**kwargs) + except TemplateNotFound: + if language != "en": + return self.get_localized_html_template(template_name, "en", **kwargs) + raise diff --git a/src/apps/mailing/static/templates/blocks/team_info_en.html b/src/apps/mailing/static/templates/blocks/team_info_en.html index dc1ccd5f00a..8f6cbff029c 100644 --- a/src/apps/mailing/static/templates/blocks/team_info_en.html +++ b/src/apps/mailing/static/templates/blocks/team_info_en.html @@ -1,3 +1,3 @@ - – The MindLogger Team + – The MindLogger Team diff --git a/src/apps/mailing/static/templates/blocks/team_info_fr.html b/src/apps/mailing/static/templates/blocks/team_info_fr.html index a605af3c467..084b3ec23ca 100644 --- a/src/apps/mailing/static/templates/blocks/team_info_fr.html +++ b/src/apps/mailing/static/templates/blocks/team_info_fr.html @@ -1,3 +1,3 @@ - – L'équipe MindLogger + – L'équipe MindLogger diff --git a/src/apps/mailing/static/templates/footers/footer_info_en.html b/src/apps/mailing/static/templates/footers/footer_info_en.html index e7b5930b73d..8b3e65bdcf5 100644 --- a/src/apps/mailing/static/templates/footers/footer_info_en.html +++ b/src/apps/mailing/static/templates/footers/footer_info_en.html @@ -25,31 +25,30 @@ - + Get iOS app + /> + - + Get Android app + /> + Need help? - Visit our Help Center. + + Visit our Help Center + . diff --git a/src/apps/mailing/static/templates/footers/footer_info_fr.html b/src/apps/mailing/static/templates/footers/footer_info_fr.html index 099ebb214e5..2c407584025 100644 --- a/src/apps/mailing/static/templates/footers/footer_info_fr.html +++ b/src/apps/mailing/static/templates/footers/footer_info_fr.html @@ -1,36 +1,40 @@ - - - - - - - - - + + + + + + + + +
- - - - - - - - - - - -
- Obtenez l'application mobile MindLogger: -
- Obtenez l'application iOS - - Obtenez l'application Android -
- Besoin d'aide? Visitez notre centre d'aide. -
-
- Child Mind Institute -
- Le Child Mind Institute est le créateur de MindLogger mais n'est pas responsable du contenu créé par des tiers. -
+ + + + + + + + + + + +
+ Obtenez l'application mobile MindLogger: +
+ + Obtenez l'application iOS + + + + Obtenez l'application Android + +
+ Besoin d'aide? Visitez notre centre d'aide. +
+
+ Child Mind Institute +
+ Le Child Mind Institute est le créateur de MindLogger mais n'est pas responsable du contenu créé par des tiers. +
diff --git a/src/apps/mailing/static/templates/header.html b/src/apps/mailing/static/templates/header.html index 1fe9ce31c9c..7b06ddc1f11 100644 --- a/src/apps/mailing/static/templates/header.html +++ b/src/apps/mailing/static/templates/header.html @@ -1,3 +1,5 @@ + +