diff --git a/.docker/run.sh b/.docker/run.sh index 16b13d72..844bcc48 100644 --- a/.docker/run.sh +++ b/.docker/run.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash set -ex @@ -19,12 +19,20 @@ done if [ "$1" = "test" ]; then - venv/bin/python manage.py compilemessages -l en -l ko - venv/bin/pytest tests --verbose + python3 manage.py compilemessages -l en -l ko + pytest tests --verbose +elif [ "$1" = "dx" ]; then + if [ ! -f .init.lock.log ]; then + python manage.py collectstatic --noinput + python manage.py migrate --no-input + python manage.py compilemessages -l en -l ko + touch .init.lock.log + fi + sleep infinity else - venv/bin/python manage.py collectstatic --noinput - venv/bin/python manage.py migrate --no-input - venv/bin/python manage.py compilemessages -l en -l ko + python3 manage.py collectstatic --noinput + python3 manage.py migrate --no-input + python3 manage.py compilemessages -l en -l ko ln -s /newara/www/.docker/supervisor-app.conf /etc/supervisor/conf.d/ || true exec supervisord -n fi diff --git a/.docker/supervisor-app.conf b/.docker/supervisor-app.conf index 7fb8875c..378a3c41 100644 --- a/.docker/supervisor-app.conf +++ b/.docker/supervisor-app.conf @@ -1,12 +1,12 @@ [program:gunicorn] -command=/newara/www/venv/bin/gunicorn -b 0.0.0.0:9000 -w 3 --timeout 120 ara.wsgi:application +command=gunicorn -b 0.0.0.0:9000 -w 3 --timeout 120 ara.wsgi:application stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 [program:celery-beat] -command=/newara/www/venv/bin/celery -A ara beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler +command=celery -A ara beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler directory=/newara/www stdout_logfile=/var/log/newara/celery-beat.log stderr_logfile=/var/log/newara/celery-beat.log diff --git a/.docker/supervisor-celery-worker.conf b/.docker/supervisor-celery-worker.conf index 757c72f3..aacc17be 100644 --- a/.docker/supervisor-celery-worker.conf +++ b/.docker/supervisor-celery-worker.conf @@ -1,5 +1,5 @@ [program:celery-worker] -command = /newara/www/venv/bin/celery -A ara worker -l info +command=celery -A ara worker -l info directory=/newara/www stdout_logfile=/var/log/newara/celery-worker.log stderr_logfile=/var/log/newara/celery-worker.log diff --git a/.editorconfig b/.editorconfig index 8bcb8ab9..b317fd68 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,19 +1,14 @@ -# EditorConfig is awesome: https://EditorConfig.org - -# top-most EditorConfig file root = true -# Set default charset -# Unix-style newlines with a newline ending every file [*] -charset = utf-8 end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true insert_final_newline = true -[.env] -insert_final_newline = false - -# 4 space indentation [*.py] -indent_size = 4 indent_style = space +indent_size = 4 + +[.env] +insert_final_newline = false diff --git a/.github/workflows/generate-docker-tag.sh b/.github/workflows/generate-docker-tag.sh index 02abdef0..773e082d 100644 --- a/.github/workflows/generate-docker-tag.sh +++ b/.github/workflows/generate-docker-tag.sh @@ -11,32 +11,32 @@ if [ ! -z $GITHUB_REF ]; then export PUSH=true if [ $NAME = "master" ]; then export DOCKER_TAG=prod - export CACHE_DOCKER_TAG=prod + export DJANGO_ENV=production echo $FIREBASE_SERVICE_ACCOUNT_KEY_PROD > firebaseServiceAccountKey.json elif [ $NAME = "develop" ]; then # Docker tag에 /가 들어갈 수 없어서 -로 변경 export DOCKER_TAG=develop - export CACHE_DOCKER_TAG=develop + export DJANGO_ENV=development echo $FIREBASE_SERVICE_ACCOUNT_KEY_DEV > firebaseServiceAccountKey.json else export DOCKER_TAG=manual - export CACHE_DOCKER_TAG=develop + export DJANGO_ENV=development export PUSH=true echo $FIREBASE_SERVICE_ACCOUNT_KEY_DEV > firebaseServiceAccountKey.json fi elif [ $TRIGGER_TYPE = "tags" ]; then export PUSH=true export DOCKER_TAG=$NAME - export CACHE_DOCKER_TAG=prod + export DJANGO_ENV=production echo $FIREBASE_SERVICE_ACCOUNT_KEY_PROD > firebaseServiceAccountKey.json elif [ $TRIGGER_TYPE = "pull" ]; then export PUSH=true export DOCKER_TAG="pr$NAME" - export CACHE_DOCKER_TAG=develop + export DJANGO_ENV=development echo $FIREBASE_SERVICE_ACCOUNT_KEY_DEV > firebaseServiceAccountKey.json fi fi -echo $PUSH $TRIGGER_TYPE $CACHE_DOCKER_TAG $DOCKER_TAG +echo $PUSH $TRIGGER_TYPE $DJANGO_ENV $DOCKER_TAG diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index 70385dcd..9064444a 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -24,8 +24,7 @@ env: jobs: deploy: name: Run Tests - # runs-on: ubuntu-20.04 - runs-on: [self-hosted] + runs-on: ubuntu-22.04 steps: - name: Checkout @@ -49,11 +48,11 @@ jobs: . .github/workflows/generate-docker-tag.sh echo "PUSH=$PUSH" >> $GITHUB_ENV echo "DOCKER_TAG=$DOCKER_TAG" >> $GITHUB_ENV - echo "CACHE_DOCKER_TAG=$CACHE_DOCKER_TAG" >> $GITHUB_ENV - docker pull $ECR/$PROJECT_NAME:$CACHE_DOCKER_TAG || true + echo "DJANGO_ENV=$DJANGO_ENV" >> $GITHUB_ENV + docker pull $ECR/$PROJECT_NAME:$DJANGO_ENV || true - name: Build run: | - docker build --build-arg AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID --build-arg AWS_SECRET_ACCESS_KEY=$(echo $AWS_SECRET_ACCESS_KEY) --cache-from $ECR/$PROJECT_NAME:$CACHE_DOCKER_TAG -t $PROJECT_NAME . + docker build --build-arg AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID --build-arg AWS_SECRET_ACCESS_KEY=$(echo $AWS_SECRET_ACCESS_KEY) --cache-from $ECR/$PROJECT_NAME:$DJANGO_ENV -t $PROJECT_NAME . - name: Run test run: | diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e8e8e4fe..2ce2d621 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -23,8 +23,3 @@ repos: hooks: - id: isort args: [--profile=black] - - - repo: https://github.com/python-poetry/poetry - rev: 1.3.1 - hooks: - - id: poetry-check diff --git a/Dockerfile b/Dockerfile index 43728f50..4c560e7d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,18 +1,16 @@ -FROM python:3.7 +FROM python:3.11 -RUN pip install --upgrade pip virtualenv awscli +RUN apt update && apt install netcat-openbsd supervisor gettext -y -ENV VIRTUAL_ENV=/newara/www/venv -RUN virtualenv -p python3 $VIRTUAL_ENV -ENV PATH="$VIRTUAL_ENV/bin:$PATH" +WORKDIR /newara/www -RUN apt-get update && apt-get install netcat-openbsd supervisor vim gettext -y +COPY Pipfile Pipfile.lock ./ -ADD ./ /newara/www +RUN pip install pipenv +RUN pipenv requirements > requirements.txt +RUN pip install --no-cache-dir -r requirements.txt -WORKDIR /newara/www -RUN pip install poetry -RUN poetry config virtualenvs.create false && poetry install +COPY . . RUN mkdir -p /var/log/newara/ RUN chmod +x /newara/www/.docker/run.sh diff --git a/Makefile b/Makefile index 559727b3..b97d93fd 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ run: python manage.py runserver 0.0.0.0:9000 shell: - python manage.py shell -i bpython + python manage.py shell -i ipython migrate: python manage.py makemigrations --merge @@ -64,3 +64,6 @@ elasticsearch_index: show_sql: python manage.py shell_plus --print-sql + +schema: + python3 manage.py spectacular --color --file schema.yml diff --git a/Pipfile b/Pipfile new file mode 100644 index 00000000..822629f2 --- /dev/null +++ b/Pipfile @@ -0,0 +1,50 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +django = "~=4.2" +djangorestframework = "~=3.14" +python-dotenv = "*" +awscli = "*" +gunicorn = "*" +celery = "*" +django-environ = "*" +firebase-admin = "*" +sentry-sdk = "*" +redis = "*" +django-filter = "*" +django-extensions = "*" +django-s3-storage = "*" +django-celery-beat = "*" +django-celery-results = "*" +drf-spectacular = "*" +django-cacheops = "*" +django-elasticsearch-dsl = "~=7.3" +mysqlclient = "*" +beautifulsoup4 = "*" +bleach = "*" +django-redis = "*" +pillow = "*" +html5lib = "*" +pytest = "*" +pytest-django = "*" +django-cors-headers = "*" +django-debug-toolbar = "*" +django-debug-toolbar-force = "*" +pyyaml = "~=5.3.1" +uritemplate = "*" +tqdm = "*" +lxml = "*" +django-ses = "*" + +[dev-packages] +black = "*" +isort = "*" +pre-commit = "*" +ipython = "*" +pytest-cov = "*" + +[requires] +python_version = "3.11" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 00000000..c79a627e --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,1838 @@ +{ + "_meta": { + "hash": { + "sha256": "e5f574b1ccc1ac2ae81c6ec3125c2474c1a151d48a25e5774a5fd6c38b4c4df7" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.11" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "amqp": { + "hashes": [ + "sha256:2c1b13fecc0893e946c65cbd5f36427861cffa4ea2201d8f6fca22e2a373b5e2", + "sha256:6f0956d2c23d8fa6e7691934d8c3930eadb44972cbbd1a7ae3a520f735d43359" + ], + "markers": "python_version >= '3.6'", + "version": "==5.1.1" + }, + "asgiref": { + "hashes": [ + "sha256:89b2ef2247e3b562a16eef663bc0e2e703ec6468e2fa8a5cd61cd449786d4f6e", + "sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed" + ], + "markers": "python_version >= '3.7'", + "version": "==3.7.2" + }, + "attrs": { + "hashes": [ + "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04", + "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015" + ], + "markers": "python_version >= '3.7'", + "version": "==23.1.0" + }, + "awscli": { + "hashes": [ + "sha256:57125cfff39186e6137bf06a9dd734f1af57ffd39484856b276861457f7865f3", + "sha256:b3a7076cb317a21410a2d41734ba338add80f0480804cf9d68cbc52b1d39612a" + ], + "index": "pypi", + "version": "==1.29.7" + }, + "beautifulsoup4": { + "hashes": [ + "sha256:492bbc69dca35d12daac71c4db1bfff0c876c00ef4a2ffacce226d4638eb72da", + "sha256:bd2520ca0d9d7d12694a53d44ac482d181b4ec1888909b035a3dbf40d0f57d4a" + ], + "index": "pypi", + "version": "==4.12.2" + }, + "billiard": { + "hashes": [ + "sha256:0f50d6be051c6b2b75bfbc8bfd85af195c5739c281d3f5b86a5640c65563614a", + "sha256:1ad2eeae8e28053d729ba3373d34d9d6e210f6e4d8bf0a9c64f92bd053f1edf5" + ], + "markers": "python_version >= '3.7'", + "version": "==4.1.0" + }, + "bleach": { + "hashes": [ + "sha256:1a1a85c1595e07d8db14c5f09f09e6433502c51c595970edc090551f0db99414", + "sha256:33c16e3353dbd13028ab4799a0f89a83f113405c766e9c122df8a06f5b85b3f4" + ], + "index": "pypi", + "version": "==6.0.0" + }, + "boto3": { + "hashes": [ + "sha256:46803b8ae114ff139f2a87fcb5d2f5a5728f6c96fe3a2b9416a8fcbe761423ae", + "sha256:ef6a465d3b25b89bcd00ff69675b33917166145e544735dcb9978091f5b0b752" + ], + "markers": "python_version >= '3.7'", + "version": "==1.28.7" + }, + "botocore": { + "hashes": [ + "sha256:f211ef5714bec8ae24b3fe737b8689611ef4d0dbea0ab46ef8328e112dd10ada", + "sha256:f4473f66c153c262b8262404d737f4249366daf00fb068b495577a24b830ebcb" + ], + "markers": "python_version >= '3.7'", + "version": "==1.31.7" + }, + "cachecontrol": { + "hashes": [ + "sha256:95dedbec849f46dda3137866dc28b9d133fc9af55f5b805ab1291833e4457aa4", + "sha256:f012366b79d2243a6118309ce73151bf52a38d4a5dac8ea57f09bd29087e506b" + ], + "markers": "python_version >= '3.7'", + "version": "==0.13.1" + }, + "cachetools": { + "hashes": [ + "sha256:95ef631eeaea14ba2e36f06437f36463aac3a096799e876ee55e5cdccb102590", + "sha256:dce83f2d9b4e1f732a8cd44af8e8fab2dbe46201467fc98b3ef8f269092bf62b" + ], + "markers": "python_version >= '3.7'", + "version": "==5.3.1" + }, + "celery": { + "hashes": [ + "sha256:27f8f3f3b58de6e0ab4f174791383bbd7445aff0471a43e99cfd77727940753f", + "sha256:f84d1c21a1520c116c2b7d26593926581191435a03aa74b77c941b93ca1c6210" + ], + "index": "pypi", + "version": "==5.3.1" + }, + "certifi": { + "hashes": [ + "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7", + "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716" + ], + "markers": "python_version >= '3.6'", + "version": "==2023.5.7" + }, + "cffi": { + "hashes": [ + "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5", + "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef", + "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104", + "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426", + "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405", + "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375", + "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a", + "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e", + "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc", + "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf", + "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185", + "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497", + "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3", + "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35", + "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c", + "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83", + "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21", + "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca", + "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984", + "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac", + "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd", + "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee", + "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a", + "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2", + "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192", + "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7", + "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585", + "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f", + "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e", + "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27", + "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b", + "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e", + "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e", + "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d", + "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c", + "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415", + "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82", + "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02", + "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314", + "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325", + "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c", + "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3", + "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914", + "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045", + "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d", + "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9", + "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5", + "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2", + "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c", + "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3", + "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2", + "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8", + "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d", + "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d", + "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9", + "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162", + "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76", + "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4", + "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e", + "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9", + "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6", + "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b", + "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01", + "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0" + ], + "version": "==1.15.1" + }, + "charset-normalizer": { + "hashes": [ + "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96", + "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c", + "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710", + "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706", + "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020", + "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252", + "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad", + "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329", + "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a", + "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f", + "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6", + "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4", + "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a", + "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46", + "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2", + "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23", + "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace", + "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd", + "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982", + "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10", + "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2", + "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea", + "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09", + "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5", + "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149", + "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489", + "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9", + "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80", + "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592", + "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3", + "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6", + "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed", + "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c", + "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200", + "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a", + "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e", + "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d", + "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6", + "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623", + "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669", + "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3", + "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa", + "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9", + "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2", + "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f", + "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1", + "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4", + "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a", + "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8", + "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3", + "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029", + "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f", + "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959", + "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22", + "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7", + "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952", + "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346", + "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e", + "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d", + "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299", + "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd", + "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a", + "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3", + "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037", + "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94", + "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c", + "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858", + "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a", + "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449", + "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c", + "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918", + "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1", + "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c", + "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac", + "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa" + ], + "markers": "python_full_version >= '3.7.0'", + "version": "==3.2.0" + }, + "click": { + "hashes": [ + "sha256:48ee849951919527a045bfe3bf7baa8a959c423134e1a5b98c05c20ba75a1cbd", + "sha256:fa244bb30b3b5ee2cae3da8f55c9e5e0c0e86093306301fb418eb9dc40fbded5" + ], + "markers": "python_version >= '3.7'", + "version": "==8.1.6" + }, + "click-didyoumean": { + "hashes": [ + "sha256:a0713dc7a1de3f06bc0df5a9567ad19ead2d3d5689b434768a6145bff77c0667", + "sha256:f184f0d851d96b6d29297354ed981b7dd71df7ff500d82fa6d11f0856bee8035" + ], + "markers": "python_full_version >= '3.6.2' and python_full_version < '4.0.0'", + "version": "==0.3.0" + }, + "click-plugins": { + "hashes": [ + "sha256:46ab999744a9d831159c3411bb0c79346d94a444df9a3a3742e9ed63645f264b", + "sha256:5d262006d3222f5057fd81e1623d4443e41dcda5dc815c06b442aa3c02889fc8" + ], + "version": "==1.1.1" + }, + "click-repl": { + "hashes": [ + "sha256:17849c23dba3d667247dc4defe1757fff98694e90fe37474f3feebb69ced26a9", + "sha256:fb7e06deb8da8de86180a33a9da97ac316751c094c6899382da7feeeeb51b812" + ], + "markers": "python_version >= '3.6'", + "version": "==0.3.0" + }, + "colorama": { + "hashes": [ + "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b", + "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==0.4.4" + }, + "cron-descriptor": { + "hashes": [ + "sha256:b6ff4e3a988d7ca04a4ab150248e9f166fb7a5c828a85090e75bcc25aa93b4dd" + ], + "version": "==1.4.0" + }, + "cryptography": { + "hashes": [ + "sha256:01f1d9e537f9a15b037d5d9ee442b8c22e3ae11ce65ea1f3316a41c78756b711", + "sha256:079347de771f9282fbfe0e0236c716686950c19dee1b76240ab09ce1624d76d7", + "sha256:182be4171f9332b6741ee818ec27daff9fb00349f706629f5cbf417bd50e66fd", + "sha256:192255f539d7a89f2102d07d7375b1e0a81f7478925b3bc2e0549ebf739dae0e", + "sha256:2a034bf7d9ca894720f2ec1d8b7b5832d7e363571828037f9e0c4f18c1b58a58", + "sha256:342f3767e25876751e14f8459ad85e77e660537ca0a066e10e75df9c9e9099f0", + "sha256:439c3cc4c0d42fa999b83ded80a9a1fb54d53c58d6e59234cfe97f241e6c781d", + "sha256:49c3222bb8f8e800aead2e376cbef687bc9e3cb9b58b29a261210456a7783d83", + "sha256:674b669d5daa64206c38e507808aae49904c988fa0a71c935e7006a3e1e83831", + "sha256:7a9a3bced53b7f09da251685224d6a260c3cb291768f54954e28f03ef14e3766", + "sha256:7af244b012711a26196450d34f483357e42aeddb04128885d95a69bd8b14b69b", + "sha256:7d230bf856164de164ecb615ccc14c7fc6de6906ddd5b491f3af90d3514c925c", + "sha256:84609ade00a6ec59a89729e87a503c6e36af98ddcd566d5f3be52e29ba993182", + "sha256:9a6673c1828db6270b76b22cc696f40cde9043eb90373da5c2f8f2158957f42f", + "sha256:9b6d717393dbae53d4e52684ef4f022444fc1cce3c48c38cb74fca29e1f08eaa", + "sha256:9c3fe6534d59d071ee82081ca3d71eed3210f76ebd0361798c74abc2bcf347d4", + "sha256:a719399b99377b218dac6cf547b6ec54e6ef20207b6165126a280b0ce97e0d2a", + "sha256:b332cba64d99a70c1e0836902720887fb4529ea49ea7f5462cf6640e095e11d2", + "sha256:d124682c7a23c9764e54ca9ab5b308b14b18eba02722b8659fb238546de83a76", + "sha256:d73f419a56d74fef257955f51b18d046f3506270a5fd2ac5febbfa259d6c0fa5", + "sha256:f0dc40e6f7aa37af01aba07277d3d64d5a03dc66d682097541ec4da03cc140ee", + "sha256:f14ad275364c8b4e525d018f6716537ae7b6d369c094805cae45300847e0894f", + "sha256:f772610fe364372de33d76edcd313636a25684edb94cee53fd790195f5989d14" + ], + "version": "==41.0.2" + }, + "django": { + "hashes": [ + "sha256:45a747e1c5b3d6df1b141b1481e193b033fd1fdbda3ff52677dc81afdaacbaed", + "sha256:f7c7852a5ac5a3da5a8d5b35cc6168f31b605971441798dac845f17ca8028039" + ], + "index": "pypi", + "version": "==4.2.3" + }, + "django-cacheops": { + "hashes": [ + "sha256:11ddea87dd039568978a4083d89c89dfb866ea55a7a48fb685a68fc198a8b650" + ], + "index": "pypi", + "version": "==7.0.1" + }, + "django-celery-beat": { + "hashes": [ + "sha256:ae460faa5ea142fba0875409095d22f6bd7bcc7377889b85e8cab5c0dfb781fe", + "sha256:cd0a47f5958402f51ac0c715bc942ae33d7b50b4e48cba91bc3f2712be505df1" + ], + "index": "pypi", + "version": "==2.5.0" + }, + "django-celery-results": { + "hashes": [ + "sha256:0da4cd5ecc049333e4524a23fcfc3460dfae91aa0a60f1fae4b6b2889c254e01", + "sha256:3ecb7147f773f34d0381bac6246337ce4cf88a2ea7b82774ed48e518b67bb8fd" + ], + "index": "pypi", + "version": "==2.5.1" + }, + "django-cors-headers": { + "hashes": [ + "sha256:9ada212b0e2efd4a5e339360ffc869cb21ac5605e810afe69f7308e577ea5bde", + "sha256:f9749c6410fe738278bc2b6ef17f05195bc7b251693c035752d8257026af024f" + ], + "index": "pypi", + "version": "==4.2.0" + }, + "django-debug-toolbar": { + "hashes": [ + "sha256:a0b532ef5d52544fd745d1dcfc0557fa75f6f0d1962a8298bd568427ef2fa436", + "sha256:f57882e335593cb8e74c2bda9f1116bbb9ca8fc0d81b50a75ace0f83de5173c7" + ], + "index": "pypi", + "version": "==4.1.0" + }, + "django-debug-toolbar-force": { + "hashes": [ + "sha256:2ab28dca4a5cd0261dfe555d709935f2dabbbb09b4be5ac0ce82103a8da0a735", + "sha256:3f580982051079dc5e85e13590d9f13d70bf012be693a81b167183cf9a3f6eec" + ], + "index": "pypi", + "version": "==0.2" + }, + "django-elasticsearch-dsl": { + "hashes": [ + "sha256:084a790edf26131a7897d13a3b5c08a6e129ca145b2b3fcbc2b2d4e902a919c1", + "sha256:c1be1c6d25ee6e99dc246282a4f6de8cc0630d0f8d9863ed512c0baa9d21be94" + ], + "index": "pypi", + "version": "==7.3" + }, + "django-environ": { + "hashes": [ + "sha256:510f8c9c1d0a38b0815f91504270c29440a0cf44fab07f55942fa8d31bbb9be6", + "sha256:b3559a91439c9d774a9e0c1ced872364772c612cdf6dc919506a2b13f7a77225" + ], + "index": "pypi", + "version": "==0.10.0" + }, + "django-extensions": { + "hashes": [ + "sha256:44d27919d04e23b3f40231c4ab7af4e61ce832ef46d610cc650d53e68328410a", + "sha256:9600b7562f79a92cbf1fde6403c04fee314608fefbb595502e34383ae8203401" + ], + "index": "pypi", + "version": "==3.2.3" + }, + "django-filter": { + "hashes": [ + "sha256:2fe15f78108475eda525692813205fa6f9e8c1caf1ae65daa5862d403c6dbf00", + "sha256:d12d8e0fc6d3eb26641e553e5d53b191eb8cec611427d4bdce0becb1f7c172b5" + ], + "index": "pypi", + "version": "==23.2" + }, + "django-nine": { + "hashes": [ + "sha256:304e0f83cea5a35359375fc919d00f9917b655c1d388244cbfc7363f59489177", + "sha256:4d93208ca5bb4a63bf65cf098a82ee469127b04ebde698d72fe12d258b73c291" + ], + "version": "==0.2.7" + }, + "django-redis": { + "hashes": [ + "sha256:2d8660d39f586c41c9907d5395693c477434141690fd7eca9d32376af00b0aac", + "sha256:8bc5793ec06b28ea802aad85ec437e7646511d4e571e07ccad19cfed8b9ddd44" + ], + "index": "pypi", + "version": "==5.3.0" + }, + "django-s3-storage": { + "hashes": [ + "sha256:1afdef915a1a5e5d3d46247faa4ee0ec760e5f9ab9e431856117de11a4a9ced5", + "sha256:8585565db2dc39c5d10977f36003032acbfc81d20117c4be7d9430dbdc60dbbb" + ], + "index": "pypi", + "version": "==0.14.0" + }, + "django-ses": { + "hashes": [ + "sha256:3522fe531155eb06bb015b3b36324c059194450633b33f9bd5bc9d1328822fe2", + "sha256:dc1644f50608fbf3a64f085a371c61d56d68eba3c5efa69651f13dc3ba05049d" + ], + "index": "pypi", + "version": "==3.5.0" + }, + "django-timezone-field": { + "hashes": [ + "sha256:16ca9955a4e16064e32168b1a0d1cdb2839679c6cb56856c1f49f506e2ca4281", + "sha256:73fc49519273cd5da1c7f16abc04a4bcad87b00cc02968d0d384c0fecf9a8a86" + ], + "markers": "python_version >= '3.7' and python_version < '4.0'", + "version": "==5.1" + }, + "djangorestframework": { + "hashes": [ + "sha256:579a333e6256b09489cbe0a067e66abe55c6595d8926be6b99423786334350c8", + "sha256:eb63f58c9f218e1a7d064d17a70751f528ed4e1d35547fdade9aaf4cd103fd08" + ], + "index": "pypi", + "version": "==3.14.0" + }, + "docutils": { + "hashes": [ + "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af", + "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==0.16" + }, + "drf-spectacular": { + "hashes": [ + "sha256:1d84ac70522baaadd6d84a25ce5fe5ea50cfcba0387856689f98ac536f14aa32", + "sha256:b907a72a0244e5dcfeca625e9632cd8ebccdbe2cb528b7c1de1191708be6f31e" + ], + "index": "pypi", + "version": "==0.26.3" + }, + "elasticsearch": { + "hashes": [ + "sha256:0e2454645dc00517dee4c6de3863411a9c5f1955d013c5fefa29123dadc92f98", + "sha256:66c4ece2adfe7cc120e2b6a6798a1fd5c777aecf82eec39bb95cef7cfc7ea2b3" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' and python_version < '4'", + "version": "==7.17.9" + }, + "elasticsearch-dsl": { + "hashes": [ + "sha256:07ee9c87dc28cc3cae2daa19401e1e18a172174ad9e5ca67938f752e3902a1d5", + "sha256:97f79239a252be7c4cce554c29e64695d7ef6a4828372316a5e5ff815e7a7498" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==7.4.1" + }, + "firebase-admin": { + "hashes": [ + "sha256:e3b334d18bbea039f2f3e8a792ad6870d2a7cc79a13ed10659dedd63f5b475e4", + "sha256:e3c42351fb6194d7279a6fd9209a947005fb4ee7e9037d19762e6cb3da4a82e1" + ], + "index": "pypi", + "version": "==6.2.0" + }, + "funcy": { + "hashes": [ + "sha256:00ce91afc850357a131dc54f0db2ad8a1110d5087f1fa4480d7ea3ba0249f89d", + "sha256:15448d19a8ebcc7a585afe7a384a19186d0bd67cbf56fb42cd1fd0f76313f9b2" + ], + "version": "==1.18" + }, + "google-api-core": { + "extras": [ + "grpc" + ], + "hashes": [ + "sha256:25d29e05a0058ed5f19c61c0a78b1b53adea4d9364b464d014fbda941f6d1c9a", + "sha256:d92a5a92dc36dd4f4b9ee4e55528a90e432b059f93aee6ad857f9de8cc7ae94a" + ], + "markers": "platform_python_implementation != 'PyPy'", + "version": "==2.11.1" + }, + "google-api-python-client": { + "hashes": [ + "sha256:28b2f0c2c6380a119e2efd7ecd28fa9d313becf37d71f00bfa49332428e071b4", + "sha256:4ff598b7b83d5c0c5582927e74947286070b5b21a13e1bb64409fd92e45bfb26" + ], + "markers": "python_version >= '3.7'", + "version": "==2.94.0" + }, + "google-auth": { + "hashes": [ + "sha256:164cba9af4e6e4e40c3a4f90a1a6c12ee56f14c0b4868d1ca91b32826ab334ce", + "sha256:d61d1b40897407b574da67da1a833bdc10d5a11642566e506565d1b1a46ba873" + ], + "markers": "python_version >= '3.6'", + "version": "==2.22.0" + }, + "google-auth-httplib2": { + "hashes": [ + "sha256:31e49c36c6b5643b57e82617cb3e021e3e1d2df9da63af67252c02fa9c1f4a10", + "sha256:a07c39fd632becacd3f07718dfd6021bf396978f03ad3ce4321d060015cc30ac" + ], + "version": "==0.1.0" + }, + "google-cloud-core": { + "hashes": [ + "sha256:37b80273c8d7eee1ae816b3a20ae43585ea50506cb0e60f3cf5be5f87f1373cb", + "sha256:fbd11cad3e98a7e5b0343dc07cb1039a5ffd7a5bb96e1f1e27cee4bda4a90863" + ], + "markers": "python_version >= '3.7'", + "version": "==2.3.3" + }, + "google-cloud-firestore": { + "hashes": [ + "sha256:7f7dfa86567c8d66c66c8dba8bc5ef85677c8532b4206055a339413f8071525d", + "sha256:833019175b6c82727da71e2db2fdea9bf203d0b8239c696492f7e2b24566bb3e" + ], + "markers": "platform_python_implementation != 'PyPy'", + "version": "==2.11.1" + }, + "google-cloud-storage": { + "hashes": [ + "sha256:934b31ead5f3994e5360f9ff5750982c5b6b11604dc072bc452c25965e076dc7", + "sha256:9433cf28801671de1c80434238fb1e7e4a1ba3087470e90f70c928ea77c2b9d7" + ], + "markers": "python_version >= '3.7'", + "version": "==2.10.0" + }, + "google-crc32c": { + "hashes": [ + "sha256:024894d9d3cfbc5943f8f230e23950cd4906b2fe004c72e29b209420a1e6b05a", + "sha256:02c65b9817512edc6a4ae7c7e987fea799d2e0ee40c53ec573a692bee24de876", + "sha256:02ebb8bf46c13e36998aeaad1de9b48f4caf545e91d14041270d9dca767b780c", + "sha256:07eb3c611ce363c51a933bf6bd7f8e3878a51d124acfc89452a75120bc436289", + "sha256:1034d91442ead5a95b5aaef90dbfaca8633b0247d1e41621d1e9f9db88c36298", + "sha256:116a7c3c616dd14a3de8c64a965828b197e5f2d121fedd2f8c5585c547e87b02", + "sha256:19e0a019d2c4dcc5e598cd4a4bc7b008546b0358bd322537c74ad47a5386884f", + "sha256:1c7abdac90433b09bad6c43a43af253e688c9cfc1c86d332aed13f9a7c7f65e2", + "sha256:1e986b206dae4476f41bcec1faa057851f3889503a70e1bdb2378d406223994a", + "sha256:272d3892a1e1a2dbc39cc5cde96834c236d5327e2122d3aaa19f6614531bb6eb", + "sha256:278d2ed7c16cfc075c91378c4f47924c0625f5fc84b2d50d921b18b7975bd210", + "sha256:2ad40e31093a4af319dadf503b2467ccdc8f67c72e4bcba97f8c10cb078207b5", + "sha256:2e920d506ec85eb4ba50cd4228c2bec05642894d4c73c59b3a2fe20346bd00ee", + "sha256:3359fc442a743e870f4588fcf5dcbc1bf929df1fad8fb9905cd94e5edb02e84c", + "sha256:37933ec6e693e51a5b07505bd05de57eee12f3e8c32b07da7e73669398e6630a", + "sha256:398af5e3ba9cf768787eef45c803ff9614cc3e22a5b2f7d7ae116df8b11e3314", + "sha256:3b747a674c20a67343cb61d43fdd9207ce5da6a99f629c6e2541aa0e89215bcd", + "sha256:461665ff58895f508e2866824a47bdee72497b091c730071f2b7575d5762ab65", + "sha256:4c6fdd4fccbec90cc8a01fc00773fcd5fa28db683c116ee3cb35cd5da9ef6c37", + "sha256:5829b792bf5822fd0a6f6eb34c5f81dd074f01d570ed7f36aa101d6fc7a0a6e4", + "sha256:596d1f98fc70232fcb6590c439f43b350cb762fb5d61ce7b0e9db4539654cc13", + "sha256:5ae44e10a8e3407dbe138984f21e536583f2bba1be9491239f942c2464ac0894", + "sha256:635f5d4dd18758a1fbd1049a8e8d2fee4ffed124462d837d1a02a0e009c3ab31", + "sha256:64e52e2b3970bd891309c113b54cf0e4384762c934d5ae56e283f9a0afcd953e", + "sha256:66741ef4ee08ea0b2cc3c86916ab66b6aef03768525627fd6a1b34968b4e3709", + "sha256:67b741654b851abafb7bc625b6d1cdd520a379074e64b6a128e3b688c3c04740", + "sha256:6ac08d24c1f16bd2bf5eca8eaf8304812f44af5cfe5062006ec676e7e1d50afc", + "sha256:6f998db4e71b645350b9ac28a2167e6632c239963ca9da411523bb439c5c514d", + "sha256:72218785ce41b9cfd2fc1d6a017dc1ff7acfc4c17d01053265c41a2c0cc39b8c", + "sha256:74dea7751d98034887dbd821b7aae3e1d36eda111d6ca36c206c44478035709c", + "sha256:759ce4851a4bb15ecabae28f4d2e18983c244eddd767f560165563bf9aefbc8d", + "sha256:77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906", + "sha256:7c074fece789b5034b9b1404a1f8208fc2d4c6ce9decdd16e8220c5a793e6f61", + "sha256:7c42c70cd1d362284289c6273adda4c6af8039a8ae12dc451dcd61cdabb8ab57", + "sha256:7f57f14606cd1dd0f0de396e1e53824c371e9544a822648cd76c034d209b559c", + "sha256:83c681c526a3439b5cf94f7420471705bbf96262f49a6fe546a6db5f687a3d4a", + "sha256:8485b340a6a9e76c62a7dce3c98e5f102c9219f4cfbf896a00cf48caf078d438", + "sha256:84e6e8cd997930fc66d5bb4fde61e2b62ba19d62b7abd7a69920406f9ecca946", + "sha256:89284716bc6a5a415d4eaa11b1726d2d60a0cd12aadf5439828353662ede9dd7", + "sha256:8b87e1a59c38f275c0e3676fc2ab6d59eccecfd460be267ac360cc31f7bcde96", + "sha256:8f24ed114432de109aa9fd317278518a5af2d31ac2ea6b952b2f7782b43da091", + "sha256:98cb4d057f285bd80d8778ebc4fde6b4d509ac3f331758fb1528b733215443ae", + "sha256:998679bf62b7fb599d2878aa3ed06b9ce688b8974893e7223c60db155f26bd8d", + "sha256:9ba053c5f50430a3fcfd36f75aff9caeba0440b2d076afdb79a318d6ca245f88", + "sha256:9c99616c853bb585301df6de07ca2cadad344fd1ada6d62bb30aec05219c45d2", + "sha256:a1fd716e7a01f8e717490fbe2e431d2905ab8aa598b9b12f8d10abebb36b04dd", + "sha256:a2355cba1f4ad8b6988a4ca3feed5bff33f6af2d7f134852cf279c2aebfde541", + "sha256:b1f8133c9a275df5613a451e73f36c2aea4fe13c5c8997e22cf355ebd7bd0728", + "sha256:b8667b48e7a7ef66afba2c81e1094ef526388d35b873966d8a9a447974ed9178", + "sha256:ba1eb1843304b1e5537e1fca632fa894d6f6deca8d6389636ee5b4797affb968", + "sha256:be82c3c8cfb15b30f36768797a640e800513793d6ae1724aaaafe5bf86f8f346", + "sha256:c02ec1c5856179f171e032a31d6f8bf84e5a75c45c33b2e20a3de353b266ebd8", + "sha256:c672d99a345849301784604bfeaeba4db0c7aae50b95be04dd651fd2a7310b93", + "sha256:c6c777a480337ac14f38564ac88ae82d4cd238bf293f0a22295b66eb89ffced7", + "sha256:cae0274952c079886567f3f4f685bcaf5708f0a23a5f5216fdab71f81a6c0273", + "sha256:cd67cf24a553339d5062eff51013780a00d6f97a39ca062781d06b3a73b15462", + "sha256:d3515f198eaa2f0ed49f8819d5732d70698c3fa37384146079b3799b97667a94", + "sha256:d5280312b9af0976231f9e317c20e4a61cd2f9629b7bfea6a693d1878a264ebd", + "sha256:de06adc872bcd8c2a4e0dc51250e9e65ef2ca91be023b9d13ebd67c2ba552e1e", + "sha256:e1674e4307fa3024fc897ca774e9c7562c957af85df55efe2988ed9056dc4e57", + "sha256:e2096eddb4e7c7bdae4bd69ad364e55e07b8316653234a56552d9c988bd2d61b", + "sha256:e560628513ed34759456a416bf86b54b2476c59144a9138165c9a1575801d0d9", + "sha256:edfedb64740750e1a3b16152620220f51d58ff1b4abceb339ca92e934775c27a", + "sha256:f13cae8cc389a440def0c8c52057f37359014ccbc9dc1f0827936bcd367c6100", + "sha256:f314013e7dcd5cf45ab1945d92e713eec788166262ae8deb2cfacd53def27325", + "sha256:f583edb943cf2e09c60441b910d6a20b4d9d626c75a36c8fcac01a6c96c01183", + "sha256:fd8536e902db7e365f49e7d9029283403974ccf29b13fc7028b97e2295b33556", + "sha256:fe70e325aa68fa4b5edf7d1a4b6f691eb04bbccac0ace68e34820d283b5f80d4" + ], + "markers": "python_version >= '3.7'", + "version": "==1.5.0" + }, + "google-resumable-media": { + "hashes": [ + "sha256:218931e8e2b2a73a58eb354a288e03a0fd5fb1c4583261ac6e4c078666468c93", + "sha256:da1bd943e2e114a56d85d6848497ebf9be6a14d3db23e9fc57581e7c3e8170ec" + ], + "markers": "python_version >= '3.7'", + "version": "==2.5.0" + }, + "googleapis-common-protos": { + "hashes": [ + "sha256:0cbedb6fb68f1c07e18eb4c48256320777707e7d0c55063ae56c15db3224a61e", + "sha256:b35d530fe825fb4227857bc47ad84c33c809ac96f312e13182bdeaa2abe1178a" + ], + "markers": "python_version >= '3.7'", + "version": "==1.59.1" + }, + "grpcio": { + "hashes": [ + "sha256:06e84ad9ae7668a109e970c7411e7992751a116494cba7c4fb877656527f9a57", + "sha256:0ff789ae7d8ddd76d2ac02e7d13bfef6fc4928ac01e1dcaa182be51b6bcc0aaa", + "sha256:10954662f77dc36c9a1fb5cc4a537f746580d6b5734803be1e587252682cda8d", + "sha256:139f66656a762572ae718fa0d1f2dce47c05e9fbf7a16acd704c354405b97df9", + "sha256:1c31e52a04e62c8577a7bf772b3e7bed4df9c9e0dd90f92b6ffa07c16cab63c9", + "sha256:33971197c47965cc1d97d78d842163c283e998223b151bab0499b951fd2c0b12", + "sha256:345356b307cce5d14355e8e055b4ca5f99bc857c33a3dc1ddbc544fca9cd0475", + "sha256:373b48f210f43327a41e397391715cd11cfce9ded2fe76a5068f9bacf91cc226", + "sha256:3ccb621749a81dc7755243665a70ce45536ec413ef5818e013fe8dfbf5aa497b", + "sha256:42a3bbb2bc07aef72a7d97e71aabecaf3e4eb616d39e5211e2cfe3689de860ca", + "sha256:42e63904ee37ae46aa23de50dac8b145b3596f43598fa33fe1098ab2cbda6ff5", + "sha256:4eb37dd8dd1aa40d601212afa27ca5be255ba792e2e0b24d67b8af5e012cdb7d", + "sha256:51173e8fa6d9a2d85c14426bdee5f5c4a0654fd5fddcc21fe9d09ab0f6eb8b35", + "sha256:5144feb20fe76e73e60c7d73ec3bf54f320247d1ebe737d10672480371878b48", + "sha256:5344be476ac37eb9c9ad09c22f4ea193c1316bf074f1daf85bddb1b31fda5116", + "sha256:6108e5933eb8c22cd3646e72d5b54772c29f57482fd4c41a0640aab99eb5071d", + "sha256:6a007a541dff984264981fbafeb052bfe361db63578948d857907df9488d8774", + "sha256:6ee26e9dfb3996aff7c870f09dc7ad44a5f6732b8bdb5a5f9905737ac6fd4ef1", + "sha256:750de923b456ca8c0f1354d6befca45d1f3b3a789e76efc16741bd4132752d95", + "sha256:7c5ede2e2558f088c49a1ddda19080e4c23fb5d171de80a726b61b567e3766ed", + "sha256:830215173ad45d670140ff99aac3b461f9be9a6b11bee1a17265aaaa746a641a", + "sha256:8391cea5ce72f4a12368afd17799474015d5d3dc00c936a907eb7c7eaaea98a5", + "sha256:8940d6de7068af018dfa9a959a3510e9b7b543f4c405e88463a1cbaa3b2b379a", + "sha256:89a49cc5ad08a38b6141af17e00d1dd482dc927c7605bc77af457b5a0fca807c", + "sha256:900bc0096c2ca2d53f2e5cebf98293a7c32f532c4aeb926345e9747452233950", + "sha256:97e0efaebbfd222bcaac2f1735c010c1d3b167112d9d237daebbeedaaccf3d1d", + "sha256:9e04d4e4cfafa7c5264e535b5d28e786f0571bea609c3f0aaab13e891e933e9c", + "sha256:a4c60abd950d6de3e4f1ddbc318075654d275c29c846ab6a043d6ed2c52e4c8c", + "sha256:a6ff459dac39541e6a2763a4439c4ca6bc9ecb4acc05a99b79246751f9894756", + "sha256:a72797549935c9e0b9bc1def1768c8b5a709538fa6ab0678e671aec47ebfd55e", + "sha256:af4063ef2b11b96d949dccbc5a987272f38d55c23c4c01841ea65a517906397f", + "sha256:b975b85d1d5efc36cf8b237c5f3849b64d1ba33d6282f5e991f28751317504a1", + "sha256:bf0b9959e673505ee5869950642428046edb91f99942607c2ecf635f8a4b31c9", + "sha256:c0c85c5cbe8b30a32fa6d802588d55ffabf720e985abe9590c7c886919d875d4", + "sha256:c3f3237a57e42f79f1e560726576aedb3a7ef931f4e3accb84ebf6acc485d316", + "sha256:c3fa3ab0fb200a2c66493828ed06ccd1a94b12eddbfb985e7fd3e5723ff156c6", + "sha256:c435f5ce1705de48e08fcbcfaf8aee660d199c90536e3e06f2016af7d6a938dd", + "sha256:c90da4b124647547a68cf2f197174ada30c7bb9523cb976665dfd26a9963d328", + "sha256:cbdf2c498e077282cd427cfd88bdce4668019791deef0be8155385ab2ba7837f", + "sha256:d1fbad1f9077372b6587ec589c1fc120b417b6c8ad72d3e3cc86bbbd0a3cee93", + "sha256:d39f5d4af48c138cb146763eda14eb7d8b3ccbbec9fe86fb724cd16e0e914c64", + "sha256:ddb4a6061933bd9332b74eac0da25f17f32afa7145a33a0f9711ad74f924b1b8", + "sha256:ded637176addc1d3eef35331c39acc598bac550d213f0a1bedabfceaa2244c87", + "sha256:f20fd21f7538f8107451156dd1fe203300b79a9ddceba1ee0ac8132521a008ed", + "sha256:fda2783c12f553cdca11c08e5af6eecbd717280dc8fbe28a110897af1c15a88c" + ], + "version": "==1.56.2" + }, + "grpcio-status": { + "hashes": [ + "sha256:63f3842867735f59f5d70e723abffd2e8501a6bcd915612a1119e52f10614782", + "sha256:a046b2c0118df4a5687f4585cca9d3c3bae5c498c4dff055dcb43fb06a1180c8" + ], + "version": "==1.56.2" + }, + "gunicorn": { + "hashes": [ + "sha256:3213aa5e8c24949e792bcacfc176fef362e7aac80b76c56f6b5122bf350722f0", + "sha256:88ec8bff1d634f98e61b9f65bc4bf3cd918a90806c6f5c48bc5603849ec81033" + ], + "index": "pypi", + "version": "==21.2.0" + }, + "html5lib": { + "hashes": [ + "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d", + "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f" + ], + "index": "pypi", + "version": "==1.1" + }, + "httplib2": { + "hashes": [ + "sha256:14ae0a53c1ba8f3d37e9e27cf37eabb0fb9980f435ba405d546948b009dd64dc", + "sha256:d7a10bc5ef5ab08322488bde8c726eeee5c8618723fdb399597ec58f3d82df81" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.22.0" + }, + "idna": { + "hashes": [ + "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4", + "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2" + ], + "markers": "python_version >= '3.5'", + "version": "==3.4" + }, + "inflection": { + "hashes": [ + "sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417", + "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2" + ], + "markers": "python_version >= '3.5'", + "version": "==0.5.1" + }, + "iniconfig": { + "hashes": [ + "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", + "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374" + ], + "markers": "python_version >= '3.7'", + "version": "==2.0.0" + }, + "jmespath": { + "hashes": [ + "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980", + "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe" + ], + "markers": "python_version >= '3.7'", + "version": "==1.0.1" + }, + "jsonschema": { + "hashes": [ + "sha256:971be834317c22daaa9132340a51c01b50910724082c2c1a2ac87eeec153a3fe", + "sha256:fb3642735399fa958c0d2aad7057901554596c63349f4f6b283c493cf692a25d" + ], + "markers": "python_version >= '3.8'", + "version": "==4.18.4" + }, + "jsonschema-specifications": { + "hashes": [ + "sha256:05adf340b659828a004220a9613be00fa3f223f2b82002e273dee62fd50524b1", + "sha256:c91a50404e88a1f6ba40636778e2ee08f6e24c5613fe4c53ac24578a5a7f72bb" + ], + "markers": "python_version >= '3.8'", + "version": "==2023.7.1" + }, + "kombu": { + "hashes": [ + "sha256:48ee589e8833126fd01ceaa08f8a2041334e9f5894e5763c8486a550454551e9", + "sha256:fbd7572d92c0bf71c112a6b45163153dea5a7b6a701ec16b568c27d0fd2370f2" + ], + "markers": "python_version >= '3.8'", + "version": "==5.3.1" + }, + "lxml": { + "hashes": [ + "sha256:05186a0f1346ae12553d66df1cfce6f251589fea3ad3da4f3ef4e34b2d58c6a3", + "sha256:075b731ddd9e7f68ad24c635374211376aa05a281673ede86cbe1d1b3455279d", + "sha256:081d32421db5df44c41b7f08a334a090a545c54ba977e47fd7cc2deece78809a", + "sha256:0a3d3487f07c1d7f150894c238299934a2a074ef590b583103a45002035be120", + "sha256:0bfd0767c5c1de2551a120673b72e5d4b628737cb05414f03c3277bf9bed3305", + "sha256:0c0850c8b02c298d3c7006b23e98249515ac57430e16a166873fc47a5d549287", + "sha256:0e2cb47860da1f7e9a5256254b74ae331687b9672dfa780eed355c4c9c3dbd23", + "sha256:120fa9349a24c7043854c53cae8cec227e1f79195a7493e09e0c12e29f918e52", + "sha256:1247694b26342a7bf47c02e513d32225ededd18045264d40758abeb3c838a51f", + "sha256:141f1d1a9b663c679dc524af3ea1773e618907e96075262726c7612c02b149a4", + "sha256:14e019fd83b831b2e61baed40cab76222139926b1fb5ed0e79225bc0cae14584", + "sha256:1509dd12b773c02acd154582088820893109f6ca27ef7291b003d0e81666109f", + "sha256:17a753023436a18e27dd7769e798ce302963c236bc4114ceee5b25c18c52c693", + "sha256:1e224d5755dba2f4a9498e150c43792392ac9b5380aa1b845f98a1618c94eeef", + "sha256:1f447ea5429b54f9582d4b955f5f1985f278ce5cf169f72eea8afd9502973dd5", + "sha256:23eed6d7b1a3336ad92d8e39d4bfe09073c31bfe502f20ca5116b2a334f8ec02", + "sha256:25f32acefac14ef7bd53e4218fe93b804ef6f6b92ffdb4322bb6d49d94cad2bc", + "sha256:2c74524e179f2ad6d2a4f7caf70e2d96639c0954c943ad601a9e146c76408ed7", + "sha256:303bf1edce6ced16bf67a18a1cf8339d0db79577eec5d9a6d4a80f0fb10aa2da", + "sha256:3331bece23c9ee066e0fb3f96c61322b9e0f54d775fccefff4c38ca488de283a", + "sha256:3e9bdd30efde2b9ccfa9cb5768ba04fe71b018a25ea093379c857c9dad262c40", + "sha256:411007c0d88188d9f621b11d252cce90c4a2d1a49db6c068e3c16422f306eab8", + "sha256:42871176e7896d5d45138f6d28751053c711ed4d48d8e30b498da155af39aebd", + "sha256:46f409a2d60f634fe550f7133ed30ad5321ae2e6630f13657fb9479506b00601", + "sha256:48628bd53a426c9eb9bc066a923acaa0878d1e86129fd5359aee99285f4eed9c", + "sha256:48d6ed886b343d11493129e019da91d4039826794a3e3027321c56d9e71505be", + "sha256:4930be26af26ac545c3dffb662521d4e6268352866956672231887d18f0eaab2", + "sha256:4aec80cde9197340bc353d2768e2a75f5f60bacda2bab72ab1dc499589b3878c", + "sha256:4c28a9144688aef80d6ea666c809b4b0e50010a2aca784c97f5e6bf143d9f129", + "sha256:4d2d1edbca80b510443f51afd8496be95529db04a509bc8faee49c7b0fb6d2cc", + "sha256:4dd9a263e845a72eacb60d12401e37c616438ea2e5442885f65082c276dfb2b2", + "sha256:4f1026bc732b6a7f96369f7bfe1a4f2290fb34dce00d8644bc3036fb351a4ca1", + "sha256:4fb960a632a49f2f089d522f70496640fdf1218f1243889da3822e0a9f5f3ba7", + "sha256:50670615eaf97227d5dc60de2dc99fb134a7130d310d783314e7724bf163f75d", + "sha256:50baa9c1c47efcaef189f31e3d00d697c6d4afda5c3cde0302d063492ff9b477", + "sha256:53ace1c1fd5a74ef662f844a0413446c0629d151055340e9893da958a374f70d", + "sha256:5515edd2a6d1a5a70bfcdee23b42ec33425e405c5b351478ab7dc9347228f96e", + "sha256:56dc1f1ebccc656d1b3ed288f11e27172a01503fc016bcabdcbc0978b19352b7", + "sha256:578695735c5a3f51569810dfebd05dd6f888147a34f0f98d4bb27e92b76e05c2", + "sha256:57aba1bbdf450b726d58b2aea5fe47c7875f5afb2c4a23784ed78f19a0462574", + "sha256:57d6ba0ca2b0c462f339640d22882acc711de224d769edf29962b09f77129cbf", + "sha256:5c245b783db29c4e4fbbbfc9c5a78be496c9fea25517f90606aa1f6b2b3d5f7b", + "sha256:5c31c7462abdf8f2ac0577d9f05279727e698f97ecbb02f17939ea99ae8daa98", + "sha256:64f479d719dc9f4c813ad9bb6b28f8390360660b73b2e4beb4cb0ae7104f1c12", + "sha256:65299ea57d82fb91c7f019300d24050c4ddeb7c5a190e076b5f48a2b43d19c42", + "sha256:6689a3d7fd13dc687e9102a27e98ef33730ac4fe37795d5036d18b4d527abd35", + "sha256:690dafd0b187ed38583a648076865d8c229661ed20e48f2335d68e2cf7dc829d", + "sha256:6fc3c450eaa0b56f815c7b62f2b7fba7266c4779adcf1cece9e6deb1de7305ce", + "sha256:704f61ba8c1283c71b16135caf697557f5ecf3e74d9e453233e4771d68a1f42d", + "sha256:71c52db65e4b56b8ddc5bb89fb2e66c558ed9d1a74a45ceb7dcb20c191c3df2f", + "sha256:71d66ee82e7417828af6ecd7db817913cb0cf9d4e61aa0ac1fde0583d84358db", + "sha256:7d298a1bd60c067ea75d9f684f5f3992c9d6766fadbc0bcedd39750bf344c2f4", + "sha256:8b77946fd508cbf0fccd8e400a7f71d4ac0e1595812e66025bac475a8e811694", + "sha256:8d7e43bd40f65f7d97ad8ef5c9b1778943d02f04febef12def25f7583d19baac", + "sha256:8df133a2ea5e74eef5e8fc6f19b9e085f758768a16e9877a60aec455ed2609b2", + "sha256:8ed74706b26ad100433da4b9d807eae371efaa266ffc3e9191ea436087a9d6a7", + "sha256:92af161ecbdb2883c4593d5ed4815ea71b31fafd7fd05789b23100d081ecac96", + "sha256:97047f0d25cd4bcae81f9ec9dc290ca3e15927c192df17331b53bebe0e3ff96d", + "sha256:9719fe17307a9e814580af1f5c6e05ca593b12fb7e44fe62450a5384dbf61b4b", + "sha256:9767e79108424fb6c3edf8f81e6730666a50feb01a328f4a016464a5893f835a", + "sha256:9a92d3faef50658dd2c5470af249985782bf754c4e18e15afb67d3ab06233f13", + "sha256:9bb6ad405121241e99a86efff22d3ef469024ce22875a7ae045896ad23ba2340", + "sha256:9e28c51fa0ce5674be9f560c6761c1b441631901993f76700b1b30ca6c8378d6", + "sha256:aca086dc5f9ef98c512bac8efea4483eb84abbf926eaeedf7b91479feb092458", + "sha256:ae8b9c6deb1e634ba4f1930eb67ef6e6bf6a44b6eb5ad605642b2d6d5ed9ce3c", + "sha256:b0a545b46b526d418eb91754565ba5b63b1c0b12f9bd2f808c852d9b4b2f9b5c", + "sha256:b4e4bc18382088514ebde9328da057775055940a1f2e18f6ad2d78aa0f3ec5b9", + "sha256:b6420a005548ad52154c8ceab4a1290ff78d757f9e5cbc68f8c77089acd3c432", + "sha256:b86164d2cff4d3aaa1f04a14685cbc072efd0b4f99ca5708b2ad1b9b5988a991", + "sha256:bb3bb49c7a6ad9d981d734ef7c7193bc349ac338776a0360cc671eaee89bcf69", + "sha256:bef4e656f7d98aaa3486d2627e7d2df1157d7e88e7efd43a65aa5dd4714916cf", + "sha256:c0781a98ff5e6586926293e59480b64ddd46282953203c76ae15dbbbf302e8bb", + "sha256:c2006f5c8d28dee289f7020f721354362fa304acbaaf9745751ac4006650254b", + "sha256:c41bfca0bd3532d53d16fd34d20806d5c2b1ace22a2f2e4c0008570bf2c58833", + "sha256:cd47b4a0d41d2afa3e58e5bf1f62069255aa2fd6ff5ee41604418ca925911d76", + "sha256:cdb650fc86227eba20de1a29d4b2c1bfe139dc75a0669270033cb2ea3d391b85", + "sha256:cef2502e7e8a96fe5ad686d60b49e1ab03e438bd9123987994528febd569868e", + "sha256:d27be7405547d1f958b60837dc4c1007da90b8b23f54ba1f8b728c78fdb19d50", + "sha256:d37017287a7adb6ab77e1c5bee9bcf9660f90ff445042b790402a654d2ad81d8", + "sha256:d3ff32724f98fbbbfa9f49d82852b159e9784d6094983d9a8b7f2ddaebb063d4", + "sha256:d73d8ecf8ecf10a3bd007f2192725a34bd62898e8da27eb9d32a58084f93962b", + "sha256:dd708cf4ee4408cf46a48b108fb9427bfa00b9b85812a9262b5c668af2533ea5", + "sha256:e3cd95e10c2610c360154afdc2f1480aea394f4a4f1ea0a5eacce49640c9b190", + "sha256:e4da8ca0c0c0aea88fd46be8e44bd49716772358d648cce45fe387f7b92374a7", + "sha256:eadfbbbfb41b44034a4c757fd5d70baccd43296fb894dba0295606a7cf3124aa", + "sha256:ed667f49b11360951e201453fc3967344d0d0263aa415e1619e85ae7fd17b4e0", + "sha256:f3df3db1d336b9356dd3112eae5f5c2b8b377f3bc826848567f10bfddfee77e9", + "sha256:f6bdac493b949141b733c5345b6ba8f87a226029cbabc7e9e121a413e49441e0", + "sha256:fbf521479bcac1e25a663df882c46a641a9bff6b56dc8b0fafaebd2f66fb231b", + "sha256:fc9b106a1bf918db68619fdcd6d5ad4f972fdd19c01d19bdb6bf63f3589a9ec5", + "sha256:fcdd00edfd0a3001e0181eab3e63bd5c74ad3e67152c84f93f13769a40e073a7", + "sha256:fe4bda6bd4340caa6e5cf95e73f8fea5c4bfc55763dd42f1b50a94c1b4a2fbd4" + ], + "index": "pypi", + "version": "==4.9.3" + }, + "msgpack": { + "hashes": [ + "sha256:06f5174b5f8ed0ed919da0e62cbd4ffde676a374aba4020034da05fab67b9164", + "sha256:0c05a4a96585525916b109bb85f8cb6511db1c6f5b9d9cbcbc940dc6b4be944b", + "sha256:137850656634abddfb88236008339fdaba3178f4751b28f270d2ebe77a563b6c", + "sha256:17358523b85973e5f242ad74aa4712b7ee560715562554aa2134d96e7aa4cbbf", + "sha256:18334484eafc2b1aa47a6d42427da7fa8f2ab3d60b674120bce7a895a0a85bdd", + "sha256:1835c84d65f46900920b3708f5ba829fb19b1096c1800ad60bae8418652a951d", + "sha256:1967f6129fc50a43bfe0951c35acbb729be89a55d849fab7686004da85103f1c", + "sha256:1ab2f3331cb1b54165976a9d976cb251a83183631c88076613c6c780f0d6e45a", + "sha256:1c0f7c47f0087ffda62961d425e4407961a7ffd2aa004c81b9c07d9269512f6e", + "sha256:20a97bf595a232c3ee6d57ddaadd5453d174a52594bf9c21d10407e2a2d9b3bd", + "sha256:20c784e66b613c7f16f632e7b5e8a1651aa5702463d61394671ba07b2fc9e025", + "sha256:266fa4202c0eb94d26822d9bfd7af25d1e2c088927fe8de9033d929dd5ba24c5", + "sha256:28592e20bbb1620848256ebc105fc420436af59515793ed27d5c77a217477705", + "sha256:288e32b47e67f7b171f86b030e527e302c91bd3f40fd9033483f2cacc37f327a", + "sha256:3055b0455e45810820db1f29d900bf39466df96ddca11dfa6d074fa47054376d", + "sha256:332360ff25469c346a1c5e47cbe2a725517919892eda5cfaffe6046656f0b7bb", + "sha256:362d9655cd369b08fda06b6657a303eb7172d5279997abe094512e919cf74b11", + "sha256:366c9a7b9057e1547f4ad51d8facad8b406bab69c7d72c0eb6f529cf76d4b85f", + "sha256:36961b0568c36027c76e2ae3ca1132e35123dcec0706c4b7992683cc26c1320c", + "sha256:379026812e49258016dd84ad79ac8446922234d498058ae1d415f04b522d5b2d", + "sha256:382b2c77589331f2cb80b67cc058c00f225e19827dbc818d700f61513ab47bea", + "sha256:476a8fe8fae289fdf273d6d2a6cb6e35b5a58541693e8f9f019bfe990a51e4ba", + "sha256:48296af57cdb1d885843afd73c4656be5c76c0c6328db3440c9601a98f303d87", + "sha256:4867aa2df9e2a5fa5f76d7d5565d25ec76e84c106b55509e78c1ede0f152659a", + "sha256:4c075728a1095efd0634a7dccb06204919a2f67d1893b6aa8e00497258bf926c", + "sha256:4f837b93669ce4336e24d08286c38761132bc7ab29782727f8557e1eb21b2080", + "sha256:4f8d8b3bf1ff2672567d6b5c725a1b347fe838b912772aa8ae2bf70338d5a198", + "sha256:525228efd79bb831cf6830a732e2e80bc1b05436b086d4264814b4b2955b2fa9", + "sha256:5494ea30d517a3576749cad32fa27f7585c65f5f38309c88c6d137877fa28a5a", + "sha256:55b56a24893105dc52c1253649b60f475f36b3aa0fc66115bffafb624d7cb30b", + "sha256:56a62ec00b636583e5cb6ad313bbed36bb7ead5fa3a3e38938503142c72cba4f", + "sha256:57e1f3528bd95cc44684beda696f74d3aaa8a5e58c816214b9046512240ef437", + "sha256:586d0d636f9a628ddc6a17bfd45aa5b5efaf1606d2b60fa5d87b8986326e933f", + "sha256:5cb47c21a8a65b165ce29f2bec852790cbc04936f502966768e4aae9fa763cb7", + "sha256:6c4c68d87497f66f96d50142a2b73b97972130d93677ce930718f68828b382e2", + "sha256:821c7e677cc6acf0fd3f7ac664c98803827ae6de594a9f99563e48c5a2f27eb0", + "sha256:916723458c25dfb77ff07f4c66aed34e47503b2eb3188b3adbec8d8aa6e00f48", + "sha256:9e6ca5d5699bcd89ae605c150aee83b5321f2115695e741b99618f4856c50898", + "sha256:9f5ae84c5c8a857ec44dc180a8b0cc08238e021f57abdf51a8182e915e6299f0", + "sha256:a2b031c2e9b9af485d5e3c4520f4220d74f4d222a5b8dc8c1a3ab9448ca79c57", + "sha256:a61215eac016f391129a013c9e46f3ab308db5f5ec9f25811e811f96962599a8", + "sha256:a740fa0e4087a734455f0fc3abf5e746004c9da72fbd541e9b113013c8dc3282", + "sha256:a9985b214f33311df47e274eb788a5893a761d025e2b92c723ba4c63936b69b1", + "sha256:ab31e908d8424d55601ad7075e471b7d0140d4d3dd3272daf39c5c19d936bd82", + "sha256:ac9dd47af78cae935901a9a500104e2dea2e253207c924cc95de149606dc43cc", + "sha256:addab7e2e1fcc04bd08e4eb631c2a90960c340e40dfc4a5e24d2ff0d5a3b3edb", + "sha256:b1d46dfe3832660f53b13b925d4e0fa1432b00f5f7210eb3ad3bb9a13c6204a6", + "sha256:b2de4c1c0538dcb7010902a2b97f4e00fc4ddf2c8cda9749af0e594d3b7fa3d7", + "sha256:b5ef2f015b95f912c2fcab19c36814963b5463f1fb9049846994b007962743e9", + "sha256:b72d0698f86e8d9ddf9442bdedec15b71df3598199ba33322d9711a19f08145c", + "sha256:bae7de2026cbfe3782c8b78b0db9cbfc5455e079f1937cb0ab8d133496ac55e1", + "sha256:bf22a83f973b50f9d38e55c6aade04c41ddda19b00c4ebc558930d78eecc64ed", + "sha256:c075544284eadc5cddc70f4757331d99dcbc16b2bbd4849d15f8aae4cf36d31c", + "sha256:c396e2cc213d12ce017b686e0f53497f94f8ba2b24799c25d913d46c08ec422c", + "sha256:cb5aaa8c17760909ec6cb15e744c3ebc2ca8918e727216e79607b7bbce9c8f77", + "sha256:cdc793c50be3f01106245a61b739328f7dccc2c648b501e237f0699fe1395b81", + "sha256:d25dd59bbbbb996eacf7be6b4ad082ed7eacc4e8f3d2df1ba43822da9bfa122a", + "sha256:e42b9594cc3bf4d838d67d6ed62b9e59e201862a25e9a157019e171fbe672dd3", + "sha256:e57916ef1bd0fee4f21c4600e9d1da352d8816b52a599c46460e93a6e9f17086", + "sha256:ed40e926fa2f297e8a653c954b732f125ef97bdd4c889f243182299de27e2aa9", + "sha256:ef8108f8dedf204bb7b42994abf93882da1159728a2d4c5e82012edd92c9da9f", + "sha256:f933bbda5a3ee63b8834179096923b094b76f0c7a73c1cfe8f07ad608c58844b", + "sha256:fe5c63197c55bce6385d9aee16c4d0641684628f63ace85f73571e65ad1c1e8d" + ], + "version": "==1.0.5" + }, + "mysqlclient": { + "hashes": [ + "sha256:004fe1d30d2c2ff8072f8ea513bcec235fd9b896f70dad369461d0ad7e570e98", + "sha256:04368445f9c487d8abb7a878e3d23e923e6072c04a6c320f9e0dc8a82efba14e", + "sha256:530ece9995a36cadb6211b9787f0c9e05cdab6702549bdb4236af5e9b535ed6a", + "sha256:5670679ff1be1cc3fef0fa81bf39f0cd70605ba121141050f02743eb878ac114", + "sha256:68837b6bb23170acffb43ae411e47533a560b6360c06dac39aa55700972c93b2", + "sha256:955dba905a7443ce4788c63fdb9f8d688316260cf60b20ff51ac3b1c77616ede", + "sha256:9c6b142836c7dba4f723bf9c93cc46b6e5081d65b2af807f400dda9eb85a16d0" + ], + "index": "pypi", + "version": "==2.2.0" + }, + "packaging": { + "hashes": [ + "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61", + "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f" + ], + "markers": "python_version >= '3.7'", + "version": "==23.1" + }, + "pillow": { + "hashes": [ + "sha256:00e65f5e822decd501e374b0650146063fbb30a7264b4d2744bdd7b913e0cab5", + "sha256:040586f7d37b34547153fa383f7f9aed68b738992380ac911447bb78f2abe530", + "sha256:0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d", + "sha256:1ce91b6ec08d866b14413d3f0bbdea7e24dfdc8e59f562bb77bc3fe60b6144ca", + "sha256:1f62406a884ae75fb2f818694469519fb685cc7eaff05d3451a9ebe55c646891", + "sha256:22c10cc517668d44b211717fd9775799ccec4124b9a7f7b3635fc5386e584992", + "sha256:3400aae60685b06bb96f99a21e1ada7bc7a413d5f49bce739828ecd9391bb8f7", + "sha256:349930d6e9c685c089284b013478d6f76e3a534e36ddfa912cde493f235372f3", + "sha256:368ab3dfb5f49e312231b6f27b8820c823652b7cd29cfbd34090565a015e99ba", + "sha256:38250a349b6b390ee6047a62c086d3817ac69022c127f8a5dc058c31ccef17f3", + "sha256:3a684105f7c32488f7153905a4e3015a3b6c7182e106fe3c37fbb5ef3e6994c3", + "sha256:3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f", + "sha256:3b08d4cc24f471b2c8ca24ec060abf4bebc6b144cb89cba638c720546b1cf538", + "sha256:3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3", + "sha256:3f07ea8d2f827d7d2a49ecf1639ec02d75ffd1b88dcc5b3a61bbb37a8759ad8d", + "sha256:520f2a520dc040512699f20fa1c363eed506e94248d71f85412b625026f6142c", + "sha256:5c6e3df6bdd396749bafd45314871b3d0af81ff935b2d188385e970052091017", + "sha256:608bfdee0d57cf297d32bcbb3c728dc1da0907519d1784962c5f0c68bb93e5a3", + "sha256:685ac03cc4ed5ebc15ad5c23bc555d68a87777586d970c2c3e216619a5476223", + "sha256:76de421f9c326da8f43d690110f0e79fe3ad1e54be811545d7d91898b4c8493e", + "sha256:76edb0a1fa2b4745fb0c99fb9fb98f8b180a1bbceb8be49b087e0b21867e77d3", + "sha256:7be600823e4c8631b74e4a0d38384c73f680e6105a7d3c6824fcf226c178c7e6", + "sha256:81ff539a12457809666fef6624684c008e00ff6bf455b4b89fd00a140eecd640", + "sha256:88af2003543cc40c80f6fca01411892ec52b11021b3dc22ec3bc9d5afd1c5334", + "sha256:8c11160913e3dd06c8ffdb5f233a4f254cb449f4dfc0f8f4549eda9e542c93d1", + "sha256:8f8182b523b2289f7c415f589118228d30ac8c355baa2f3194ced084dac2dbba", + "sha256:9211e7ad69d7c9401cfc0e23d49b69ca65ddd898976d660a2fa5904e3d7a9baa", + "sha256:92be919bbc9f7d09f7ae343c38f5bb21c973d2576c1d45600fce4b74bafa7ac0", + "sha256:9c82b5b3e043c7af0d95792d0d20ccf68f61a1fec6b3530e718b688422727396", + "sha256:9f7c16705f44e0504a3a2a14197c1f0b32a95731d251777dcb060aa83022cb2d", + "sha256:9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485", + "sha256:a74ba0c356aaa3bb8e3eb79606a87669e7ec6444be352870623025d75a14a2bf", + "sha256:b4f69b3700201b80bb82c3a97d5e9254084f6dd5fb5b16fc1a7b974260f89f43", + "sha256:bc2ec7c7b5d66b8ec9ce9f720dbb5fa4bace0f545acd34870eff4a369b44bf37", + "sha256:c189af0545965fa8d3b9613cfdb0cd37f9d71349e0f7750e1fd704648d475ed2", + "sha256:c1fbe7621c167ecaa38ad29643d77a9ce7311583761abf7836e1510c580bf3dd", + "sha256:c7cf14a27b0d6adfaebb3ae4153f1e516df54e47e42dcc073d7b3d76111a8d86", + "sha256:c9f72a021fbb792ce98306ffb0c348b3c9cb967dce0f12a49aa4c3d3fdefa967", + "sha256:cd25d2a9d2b36fcb318882481367956d2cf91329f6892fe5d385c346c0649629", + "sha256:ce543ed15570eedbb85df19b0a1a7314a9c8141a36ce089c0a894adbfccb4568", + "sha256:ce7b031a6fc11365970e6a5686d7ba8c63e4c1cf1ea143811acbb524295eabed", + "sha256:d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f", + "sha256:d50b6aec14bc737742ca96e85d6d0a5f9bfbded018264b3b70ff9d8c33485551", + "sha256:d5d0dae4cfd56969d23d94dc8e89fb6a217be461c69090768227beb8ed28c0a3", + "sha256:d5db32e2a6ccbb3d34d87c87b432959e0db29755727afb37290e10f6e8e62614", + "sha256:d72e2ecc68a942e8cf9739619b7f408cc7b272b279b56b2c83c6123fcfa5cdff", + "sha256:d737a602fbd82afd892ca746392401b634e278cb65d55c4b7a8f48e9ef8d008d", + "sha256:d80cf684b541685fccdd84c485b31ce73fc5c9b5d7523bf1394ce134a60c6883", + "sha256:db24668940f82321e746773a4bc617bfac06ec831e5c88b643f91f122a785684", + "sha256:dbc02381779d412145331789b40cc7b11fdf449e5d94f6bc0b080db0a56ea3f0", + "sha256:dffe31a7f47b603318c609f378ebcd57f1554a3a6a8effbc59c3c69f804296de", + "sha256:edf4392b77bdc81f36e92d3a07a5cd072f90253197f4a52a55a8cec48a12483b", + "sha256:efe8c0681042536e0d06c11f48cebe759707c9e9abf880ee213541c5b46c5bf3", + "sha256:f31f9fdbfecb042d046f9d91270a0ba28368a723302786c0009ee9b9f1f60199", + "sha256:f88a0b92277de8e3ca715a0d79d68dc82807457dae3ab8699c758f07c20b3c51", + "sha256:faaf07ea35355b01a35cb442dd950d8f1bb5b040a7787791a535de13db15ed90" + ], + "index": "pypi", + "version": "==10.0.0" + }, + "pluggy": { + "hashes": [ + "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849", + "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3" + ], + "markers": "python_version >= '3.7'", + "version": "==1.2.0" + }, + "prompt-toolkit": { + "hashes": [ + "sha256:04505ade687dc26dc4284b1ad19a83be2f2afe83e7a828ace0c72f3a1df72aac", + "sha256:9dffbe1d8acf91e3de75f3b544e4842382fc06c6babe903ac9acb74dc6e08d88" + ], + "markers": "python_full_version >= '3.7.0'", + "version": "==3.0.39" + }, + "proto-plus": { + "hashes": [ + "sha256:a49cd903bc0b6ab41f76bf65510439d56ca76f868adf0274e738bfdd096894df", + "sha256:fdcd09713cbd42480740d2fe29c990f7fbd885a67efc328aa8be6ee3e9f76a6b" + ], + "markers": "python_version >= '3.6'", + "version": "==1.22.3" + }, + "protobuf": { + "hashes": [ + "sha256:0a5759f5696895de8cc913f084e27fd4125e8fb0914bb729a17816a33819f474", + "sha256:351cc90f7d10839c480aeb9b870a211e322bf05f6ab3f55fcb2f51331f80a7d2", + "sha256:5fea3c64d41ea5ecf5697b83e41d09b9589e6f20b677ab3c48e5f242d9b7897b", + "sha256:6dd9b9940e3f17077e820b75851126615ee38643c2c5332aa7a359988820c720", + "sha256:7b19b6266d92ca6a2a87effa88ecc4af73ebc5cfde194dc737cf8ef23a9a3b12", + "sha256:8547bf44fe8cec3c69e3042f5c4fb3e36eb2a7a013bb0a44c018fc1e427aafbd", + "sha256:9053df6df8e5a76c84339ee4a9f5a2661ceee4a0dab019e8663c50ba324208b0", + "sha256:c3e0939433c40796ca4cfc0fac08af50b00eb66a40bbbc5dee711998fb0bbc1e", + "sha256:ccd9430c0719dce806b93f89c91de7977304729e55377f872a92465d548329a9", + "sha256:e1c915778d8ced71e26fcf43c0866d7499891bca14c4368448a82edc61fdbc70", + "sha256:e9d0be5bf34b275b9f87ba7407796556abeeba635455d036c7351f7c183ef8ff", + "sha256:effeac51ab79332d44fba74660d40ae79985901ac21bca408f8dc335a81aa597", + "sha256:fee88269a090ada09ca63551bf2f573eb2424035bcf2cb1b121895b01a46594a" + ], + "markers": "python_version >= '3.7'", + "version": "==4.23.4" + }, + "pyasn1": { + "hashes": [ + "sha256:87a2121042a1ac9358cabcaf1d07680ff97ee6404333bacca15f76aa8ad01a57", + "sha256:97b7290ca68e62a832558ec3976f15cbf911bf5d7c7039d8b861c2a0ece69fde" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==0.5.0" + }, + "pyasn1-modules": { + "hashes": [ + "sha256:5bd01446b736eb9d31512a30d46c1ac3395d676c6f3cafa4c03eb54b9925631c", + "sha256:d3ccd6ed470d9ffbc716be08bd90efbd44d0734bc9303818f7336070984a162d" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==0.3.0" + }, + "pycparser": { + "hashes": [ + "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", + "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206" + ], + "version": "==2.21" + }, + "pyjwt": { + "extras": [ + "crypto" + ], + "hashes": [ + "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de", + "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320" + ], + "markers": "python_version >= '3.7'", + "version": "==2.8.0" + }, + "pyparsing": { + "hashes": [ + "sha256:d554a96d1a7d3ddaf7183104485bc19fd80543ad6ac5bdb6426719d766fb06c1", + "sha256:edb662d6fe322d6e990b1594b5feaeadf806803359e3d4d42f11e295e588f0ea" + ], + "markers": "python_version >= '3.1'", + "version": "==3.1.0" + }, + "pytest": { + "hashes": [ + "sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32", + "sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a" + ], + "index": "pypi", + "version": "==7.4.0" + }, + "pytest-django": { + "hashes": [ + "sha256:c60834861933773109334fe5a53e83d1ef4828f2203a1d6a0fa9972f4f75ab3e", + "sha256:d9076f759bb7c36939dbdd5ae6633c18edfc2902d1a69fdbefd2426b970ce6c2" + ], + "index": "pypi", + "version": "==4.5.2" + }, + "python-crontab": { + "hashes": [ + "sha256:6d5ba3c190ec76e4d252989a1644fcb233dbf53fbc8fceeb9febe1657b9fb1d4", + "sha256:79fb7465039ddfd4fb93d072d6ee0d45c1ac8bf1597f0686ea14fd4361dba379" + ], + "version": "==3.0.0" + }, + "python-dateutil": { + "hashes": [ + "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", + "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.8.2" + }, + "python-dotenv": { + "hashes": [ + "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba", + "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a" + ], + "index": "pypi", + "version": "==1.0.0" + }, + "pytz": { + "hashes": [ + "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588", + "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb" + ], + "version": "==2023.3" + }, + "pyyaml": { + "hashes": [ + "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97", + "sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76", + "sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2", + "sha256:6034f55dab5fea9e53f436aa68fa3ace2634918e8b5994d82f3621c04ff5ed2e", + "sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648", + "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf", + "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f", + "sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2", + "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee", + "sha256:ad9c67312c84def58f3c04504727ca879cb0013b2517c85a9a253f0cb6380c0a", + "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d", + "sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c", + "sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a" + ], + "index": "pypi", + "version": "==5.3.1" + }, + "redis": { + "hashes": [ + "sha256:585dc516b9eb042a619ef0a39c3d7d55fe81bdb4df09a52c9cdde0d07bf1aa7d", + "sha256:e2b03db868160ee4591de3cb90d40ebb50a90dd302138775937f6a42b7ed183c" + ], + "index": "pypi", + "version": "==4.6.0" + }, + "referencing": { + "hashes": [ + "sha256:47237742e990457f7512c7d27486394a9aadaf876cbfaa4be65b27b4f4d47c6b", + "sha256:c257b08a399b6c2f5a3510a50d28ab5dbc7bbde049bcaf954d43c446f83ab548" + ], + "markers": "python_version >= '3.8'", + "version": "==0.30.0" + }, + "requests": { + "hashes": [ + "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f", + "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1" + ], + "markers": "python_version >= '3.7'", + "version": "==2.31.0" + }, + "rpds-py": { + "hashes": [ + "sha256:0173c0444bec0a3d7d848eaeca2d8bd32a1b43f3d3fde6617aac3731fa4be05f", + "sha256:01899794b654e616c8625b194ddd1e5b51ef5b60ed61baa7a2d9c2ad7b2a4238", + "sha256:02938432352359805b6da099c9c95c8a0547fe4b274ce8f1a91677401bb9a45f", + "sha256:03421628f0dc10a4119d714a17f646e2837126a25ac7a256bdf7c3943400f67f", + "sha256:03975db5f103997904c37e804e5f340c8fdabbb5883f26ee50a255d664eed58c", + "sha256:0766babfcf941db8607bdaf82569ec38107dbb03c7f0b72604a0b346b6eb3298", + "sha256:07e2c54bef6838fa44c48dfbc8234e8e2466d851124b551fc4e07a1cfeb37260", + "sha256:0836d71ca19071090d524739420a61580f3f894618d10b666cf3d9a1688355b1", + "sha256:095b460e117685867d45548fbd8598a8d9999227e9061ee7f012d9d264e6048d", + "sha256:0e7521f5af0233e89939ad626b15278c71b69dc1dfccaa7b97bd4cdf96536bb7", + "sha256:0f2996fbac8e0b77fd67102becb9229986396e051f33dbceada3debaacc7033f", + "sha256:1054a08e818f8e18910f1bee731583fe8f899b0a0a5044c6e680ceea34f93876", + "sha256:13b602dc3e8dff3063734f02dcf05111e887f301fdda74151a93dbbc249930fe", + "sha256:141acb9d4ccc04e704e5992d35472f78c35af047fa0cfae2923835d153f091be", + "sha256:14c408e9d1a80dcb45c05a5149e5961aadb912fff42ca1dd9b68c0044904eb32", + "sha256:159fba751a1e6b1c69244e23ba6c28f879a8758a3e992ed056d86d74a194a0f3", + "sha256:190ca6f55042ea4649ed19c9093a9be9d63cd8a97880106747d7147f88a49d18", + "sha256:196cb208825a8b9c8fc360dc0f87993b8b260038615230242bf18ec84447c08d", + "sha256:1fcdee18fea97238ed17ab6478c66b2095e4ae7177e35fb71fbe561a27adf620", + "sha256:207f57c402d1f8712618f737356e4b6f35253b6d20a324d9a47cb9f38ee43a6b", + "sha256:24a81c177379300220e907e9b864107614b144f6c2a15ed5c3450e19cf536fae", + "sha256:29cd8bfb2d716366a035913ced99188a79b623a3512292963d84d3e06e63b496", + "sha256:2d8b3b3a2ce0eaa00c5bbbb60b6713e94e7e0becab7b3db6c5c77f979e8ed1f1", + "sha256:35da5cc5cb37c04c4ee03128ad59b8c3941a1e5cd398d78c37f716f32a9b7f67", + "sha256:44659b1f326214950a8204a248ca6199535e73a694be8d3e0e869f820767f12f", + "sha256:47c5f58a8e0c2c920cc7783113df2fc4ff12bf3a411d985012f145e9242a2764", + "sha256:4bd4dc3602370679c2dfb818d9c97b1137d4dd412230cfecd3c66a1bf388a196", + "sha256:4ea6b73c22d8182dff91155af018b11aac9ff7eca085750455c5990cb1cfae6e", + "sha256:50025635ba8b629a86d9d5474e650da304cb46bbb4d18690532dd79341467846", + "sha256:517cbf6e67ae3623c5127206489d69eb2bdb27239a3c3cc559350ef52a3bbf0b", + "sha256:5855c85eb8b8a968a74dc7fb014c9166a05e7e7a8377fb91d78512900aadd13d", + "sha256:5a46859d7f947061b4010e554ccd1791467d1b1759f2dc2ec9055fa239f1bc26", + "sha256:65a0583c43d9f22cb2130c7b110e695fff834fd5e832a776a107197e59a1898e", + "sha256:674c704605092e3ebbbd13687b09c9f78c362a4bc710343efe37a91457123044", + "sha256:682726178138ea45a0766907957b60f3a1bf3acdf212436be9733f28b6c5af3c", + "sha256:686ba516e02db6d6f8c279d1641f7067ebb5dc58b1d0536c4aaebb7bf01cdc5d", + "sha256:6a5d3fbd02efd9cf6a8ffc2f17b53a33542f6b154e88dd7b42ef4a4c0700fdad", + "sha256:6aa8326a4a608e1c28da191edd7c924dff445251b94653988efb059b16577a4d", + "sha256:700375326ed641f3d9d32060a91513ad668bcb7e2cffb18415c399acb25de2ab", + "sha256:71f2f7715935a61fa3e4ae91d91b67e571aeb5cb5d10331ab681256bda2ad920", + "sha256:745f5a43fdd7d6d25a53ab1a99979e7f8ea419dfefebcab0a5a1e9095490ee5e", + "sha256:79f594919d2c1a0cc17d1988a6adaf9a2f000d2e1048f71f298b056b1018e872", + "sha256:7d68dc8acded354c972116f59b5eb2e5864432948e098c19fe6994926d8e15c3", + "sha256:7f67da97f5b9eac838b6980fc6da268622e91f8960e083a34533ca710bec8611", + "sha256:83b32f0940adec65099f3b1c215ef7f1d025d13ff947975a055989cb7fd019a4", + "sha256:876bf9ed62323bc7dcfc261dbc5572c996ef26fe6406b0ff985cbcf460fc8a4c", + "sha256:890ba852c16ace6ed9f90e8670f2c1c178d96510a21b06d2fa12d8783a905193", + "sha256:8b08605d248b974eb02f40bdcd1a35d3924c83a2a5e8f5d0fa5af852c4d960af", + "sha256:8b2eb034c94b0b96d5eddb290b7b5198460e2d5d0c421751713953a9c4e47d10", + "sha256:8b9ec12ad5f0a4625db34db7e0005be2632c1013b253a4a60e8302ad4d462afd", + "sha256:8c8d7594e38cf98d8a7df25b440f684b510cf4627fe038c297a87496d10a174f", + "sha256:8d3335c03100a073883857e91db9f2e0ef8a1cf42dc0369cbb9151c149dbbc1b", + "sha256:8d70e8f14900f2657c249ea4def963bed86a29b81f81f5b76b5a9215680de945", + "sha256:9039a11bca3c41be5a58282ed81ae422fa680409022b996032a43badef2a3752", + "sha256:91378d9f4151adc223d584489591dbb79f78814c0734a7c3bfa9c9e09978121c", + "sha256:9251eb8aa82e6cf88510530b29eef4fac825a2b709baf5b94a6094894f252387", + "sha256:933a7d5cd4b84f959aedeb84f2030f0a01d63ae6cf256629af3081cf3e3426e8", + "sha256:978fa96dbb005d599ec4fd9ed301b1cc45f1a8f7982d4793faf20b404b56677d", + "sha256:987b06d1cdb28f88a42e4fb8a87f094e43f3c435ed8e486533aea0bf2e53d931", + "sha256:99b1c16f732b3a9971406fbfe18468592c5a3529585a45a35adbc1389a529a03", + "sha256:99e7c4bb27ff1aab90dcc3e9d37ee5af0231ed98d99cb6f5250de28889a3d502", + "sha256:9c439fd54b2b9053717cca3de9583be6584b384d88d045f97d409f0ca867d80f", + "sha256:9ea4d00850ef1e917815e59b078ecb338f6a8efda23369677c54a5825dbebb55", + "sha256:9f30d205755566a25f2ae0382944fcae2f350500ae4df4e795efa9e850821d82", + "sha256:a06418fe1155e72e16dddc68bb3780ae44cebb2912fbd8bb6ff9161de56e1798", + "sha256:a0805911caedfe2736935250be5008b261f10a729a303f676d3d5fea6900c96a", + "sha256:a1f044792e1adcea82468a72310c66a7f08728d72a244730d14880cd1dabe36b", + "sha256:a216b26e5af0a8e265d4efd65d3bcec5fba6b26909014effe20cd302fd1138fa", + "sha256:a987578ac5214f18b99d1f2a3851cba5b09f4a689818a106c23dbad0dfeb760f", + "sha256:aad51239bee6bff6823bbbdc8ad85136c6125542bbc609e035ab98ca1e32a192", + "sha256:ab2299e3f92aa5417d5e16bb45bb4586171c1327568f638e8453c9f8d9e0f020", + "sha256:ab6919a09c055c9b092798ce18c6c4adf49d24d4d9e43a92b257e3f2548231e7", + "sha256:b0c43f8ae8f6be1d605b0465671124aa8d6a0e40f1fb81dcea28b7e3d87ca1e1", + "sha256:b1440c291db3f98a914e1afd9d6541e8fc60b4c3aab1a9008d03da4651e67386", + "sha256:b52e7c5ae35b00566d244ffefba0f46bb6bec749a50412acf42b1c3f402e2c90", + "sha256:bf4151acb541b6e895354f6ff9ac06995ad9e4175cbc6d30aaed08856558201f", + "sha256:c27ee01a6c3223025f4badd533bea5e87c988cb0ba2811b690395dfe16088cfe", + "sha256:c545d9d14d47be716495076b659db179206e3fd997769bc01e2d550eeb685596", + "sha256:c5934e2833afeaf36bd1eadb57256239785f5af0220ed8d21c2896ec4d3a765f", + "sha256:c7671d45530fcb6d5e22fd40c97e1e1e01965fc298cbda523bb640f3d923b387", + "sha256:c861a7e4aef15ff91233751619ce3a3d2b9e5877e0fcd76f9ea4f6847183aa16", + "sha256:d25b1c1096ef0447355f7293fbe9ad740f7c47ae032c2884113f8e87660d8f6e", + "sha256:d55777a80f78dd09410bd84ff8c95ee05519f41113b2df90a69622f5540c4f8b", + "sha256:d576c3ef8c7b2d560e301eb33891d1944d965a4d7a2eacb6332eee8a71827db6", + "sha256:dd9da77c6ec1f258387957b754f0df60766ac23ed698b61941ba9acccd3284d1", + "sha256:de0b6eceb46141984671802d412568d22c6bacc9b230174f9e55fc72ef4f57de", + "sha256:e07e5dbf8a83c66783a9fe2d4566968ea8c161199680e8ad38d53e075df5f0d0", + "sha256:e564d2238512c5ef5e9d79338ab77f1cbbda6c2d541ad41b2af445fb200385e3", + "sha256:ed89861ee8c8c47d6beb742a602f912b1bb64f598b1e2f3d758948721d44d468", + "sha256:ef1f08f2a924837e112cba2953e15aacfccbbfcd773b4b9b4723f8f2ddded08e", + "sha256:f411330a6376fb50e5b7a3e66894e4a39e60ca2e17dce258d53768fea06a37bd", + "sha256:f68996a3b3dc9335037f82754f9cdbe3a95db42bde571d8c3be26cc6245f2324", + "sha256:f7fdf55283ad38c33e35e2855565361f4bf0abd02470b8ab28d499c663bc5d7c", + "sha256:f963c6b1218b96db85fc37a9f0851eaf8b9040aa46dec112611697a7023da535", + "sha256:fa2818759aba55df50592ecbc95ebcdc99917fa7b55cc6796235b04193eb3c55", + "sha256:fae5cb554b604b3f9e2c608241b5d8d303e410d7dfb6d397c335f983495ce7f6", + "sha256:fb39aca7a64ad0c9490adfa719dbeeb87d13be137ca189d2564e596f8ba32c07" + ], + "markers": "python_version >= '3.8'", + "version": "==0.9.2" + }, + "rsa": { + "hashes": [ + "sha256:78f9a9bf4e7be0c5ded4583326e7461e3a3c5aae24073648b4bdfa797d78c9d2", + "sha256:9d689e6ca1b3038bc82bf8d23e944b6b6037bc02301a574935b2dd946e0353b9" + ], + "markers": "python_version >= '3.5' and python_version < '4'", + "version": "==4.7.2" + }, + "s3transfer": { + "hashes": [ + "sha256:3c0da2d074bf35d6870ef157158641178a4204a6e689e82546083e31e0311346", + "sha256:640bb492711f4c0c0905e1f62b6aaeb771881935ad27884852411f8e9cacbca9" + ], + "markers": "python_version >= '3.7'", + "version": "==0.6.1" + }, + "sentry-sdk": { + "hashes": [ + "sha256:6bdb25bd9092478d3a817cb0d01fa99e296aea34d404eac3ca0037faa5c2aa0a", + "sha256:dcd88c68aa64dae715311b5ede6502fd684f70d00a7cd4858118f0ba3153a3ae" + ], + "index": "pypi", + "version": "==1.28.1" + }, + "six": { + "hashes": [ + "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", + "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.16.0" + }, + "soupsieve": { + "hashes": [ + "sha256:1c1bfee6819544a3447586c889157365a27e10d88cde3ad3da0cf0ddf646feb8", + "sha256:89d12b2d5dfcd2c9e8c22326da9d9aa9cb3dfab0a83a024f05704076ee8d35ea" + ], + "markers": "python_version >= '3.7'", + "version": "==2.4.1" + }, + "sqlparse": { + "hashes": [ + "sha256:5430a4fe2ac7d0f93e66f1efc6e1338a41884b7ddf2a350cedd20ccc4d9d28f3", + "sha256:d446183e84b8349fa3061f0fe7f06ca94ba65b426946ffebe6e3e8295332420c" + ], + "markers": "python_version >= '3.5'", + "version": "==0.4.4" + }, + "tqdm": { + "hashes": [ + "sha256:1871fb68a86b8fb3b59ca4cdd3dcccbc7e6d613eeed31f4c332531977b89beb5", + "sha256:c4f53a17fe37e132815abceec022631be8ffe1b9381c2e6e30aa70edc99e9671" + ], + "index": "pypi", + "version": "==4.65.0" + }, + "tzdata": { + "hashes": [ + "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a", + "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda" + ], + "markers": "python_version >= '2'", + "version": "==2023.3" + }, + "uritemplate": { + "hashes": [ + "sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0", + "sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e" + ], + "index": "pypi", + "version": "==4.1.1" + }, + "urllib3": { + "hashes": [ + "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f", + "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==1.26.16" + }, + "vine": { + "hashes": [ + "sha256:4c9dceab6f76ed92105027c49c823800dd33cacce13bdedc5b914e3514b7fb30", + "sha256:7d3b1624a953da82ef63462013bbd271d3eb75751489f9807598e8f340bd637e" + ], + "markers": "python_version >= '3.6'", + "version": "==5.0.0" + }, + "wcwidth": { + "hashes": [ + "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e", + "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0" + ], + "version": "==0.2.6" + }, + "webencodings": { + "hashes": [ + "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", + "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923" + ], + "version": "==0.5.1" + } + }, + "develop": { + "asttokens": { + "hashes": [ + "sha256:4622110b2a6f30b77e1473affaa97e711bc2f07d3f10848420ff1898edbe94f3", + "sha256:6b0ac9e93fb0335014d382b8fa9b3afa7df546984258005da0b9e7095b3deb1c" + ], + "version": "==2.2.1" + }, + "backcall": { + "hashes": [ + "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e", + "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255" + ], + "version": "==0.2.0" + }, + "black": { + "hashes": [ + "sha256:01ede61aac8c154b55f35301fac3e730baf0c9cf8120f65a9cd61a81cfb4a0c3", + "sha256:022a582720b0d9480ed82576c920a8c1dde97cc38ff11d8d8859b3bd6ca9eedb", + "sha256:25cc308838fe71f7065df53aedd20327969d05671bac95b38fdf37ebe70ac087", + "sha256:27eb7a0c71604d5de083757fbdb245b1a4fae60e9596514c6ec497eb63f95320", + "sha256:327a8c2550ddc573b51e2c352adb88143464bb9d92c10416feb86b0f5aee5ff6", + "sha256:47e56d83aad53ca140da0af87678fb38e44fd6bc0af71eebab2d1f59b1acf1d3", + "sha256:501387a9edcb75d7ae8a4412bb8749900386eaef258f1aefab18adddea1936bc", + "sha256:552513d5cd5694590d7ef6f46e1767a4df9af168d449ff767b13b084c020e63f", + "sha256:5c4bc552ab52f6c1c506ccae05681fab58c3f72d59ae6e6639e8885e94fe2587", + "sha256:642496b675095d423f9b8448243336f8ec71c9d4d57ec17bf795b67f08132a91", + "sha256:6d1c6022b86f83b632d06f2b02774134def5d4d4f1dac8bef16d90cda18ba28a", + "sha256:7f3bf2dec7d541b4619b8ce526bda74a6b0bffc480a163fed32eb8b3c9aed8ad", + "sha256:831d8f54c3a8c8cf55f64d0422ee875eecac26f5f649fb6c1df65316b67c8926", + "sha256:8417dbd2f57b5701492cd46edcecc4f9208dc75529bcf76c514864e48da867d9", + "sha256:86cee259349b4448adb4ef9b204bb4467aae74a386bce85d56ba4f5dc0da27be", + "sha256:893695a76b140881531062d48476ebe4a48f5d1e9388177e175d76234ca247cd", + "sha256:9fd59d418c60c0348505f2ddf9609c1e1de8e7493eab96198fc89d9f865e7a96", + "sha256:ad0014efc7acf0bd745792bd0d8857413652979200ab924fbf239062adc12491", + "sha256:b5b0ee6d96b345a8b420100b7d71ebfdd19fab5e8301aff48ec270042cd40ac2", + "sha256:c333286dc3ddca6fdff74670b911cccedacb4ef0a60b34e491b8a67c833b343a", + "sha256:f9062af71c59c004cd519e2fb8f5d25d39e46d3af011b41ab43b9c74e27e236f", + "sha256:fb074d8b213749fa1d077d630db0d5f8cc3b2ae63587ad4116e8a436e9bbe995" + ], + "index": "pypi", + "version": "==23.7.0" + }, + "cfgv": { + "hashes": [ + "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426", + "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736" + ], + "markers": "python_full_version >= '3.6.1'", + "version": "==3.3.1" + }, + "click": { + "hashes": [ + "sha256:48ee849951919527a045bfe3bf7baa8a959c423134e1a5b98c05c20ba75a1cbd", + "sha256:fa244bb30b3b5ee2cae3da8f55c9e5e0c0e86093306301fb418eb9dc40fbded5" + ], + "markers": "python_version >= '3.7'", + "version": "==8.1.6" + }, + "coverage": { + "extras": [ + "toml" + ], + "hashes": [ + "sha256:06a9a2be0b5b576c3f18f1a241f0473575c4a26021b52b2a85263a00f034d51f", + "sha256:06fb182e69f33f6cd1d39a6c597294cff3143554b64b9825d1dc69d18cc2fff2", + "sha256:0a5f9e1dbd7fbe30196578ca36f3fba75376fb99888c395c5880b355e2875f8a", + "sha256:0e1f928eaf5469c11e886fe0885ad2bf1ec606434e79842a879277895a50942a", + "sha256:171717c7cb6b453aebac9a2ef603699da237f341b38eebfee9be75d27dc38e01", + "sha256:1e9d683426464e4a252bf70c3498756055016f99ddaec3774bf368e76bbe02b6", + "sha256:201e7389591af40950a6480bd9edfa8ed04346ff80002cec1a66cac4549c1ad7", + "sha256:245167dd26180ab4c91d5e1496a30be4cd721a5cf2abf52974f965f10f11419f", + "sha256:2aee274c46590717f38ae5e4650988d1af340fe06167546cc32fe2f58ed05b02", + "sha256:2e07b54284e381531c87f785f613b833569c14ecacdcb85d56b25c4622c16c3c", + "sha256:31563e97dae5598556600466ad9beea39fb04e0229e61c12eaa206e0aa202063", + "sha256:33d6d3ea29d5b3a1a632b3c4e4f4ecae24ef170b0b9ee493883f2df10039959a", + "sha256:3d376df58cc111dc8e21e3b6e24606b5bb5dee6024f46a5abca99124b2229ef5", + "sha256:419bfd2caae268623dd469eff96d510a920c90928b60f2073d79f8fe2bbc5959", + "sha256:48c19d2159d433ccc99e729ceae7d5293fbffa0bdb94952d3579983d1c8c9d97", + "sha256:49969a9f7ffa086d973d91cec8d2e31080436ef0fb4a359cae927e742abfaaa6", + "sha256:52edc1a60c0d34afa421c9c37078817b2e67a392cab17d97283b64c5833f427f", + "sha256:537891ae8ce59ef63d0123f7ac9e2ae0fc8b72c7ccbe5296fec45fd68967b6c9", + "sha256:54b896376ab563bd38453cecb813c295cf347cf5906e8b41d340b0321a5433e5", + "sha256:58c2ccc2f00ecb51253cbe5d8d7122a34590fac9646a960d1430d5b15321d95f", + "sha256:5b7540161790b2f28143191f5f8ec02fb132660ff175b7747b95dcb77ac26562", + "sha256:5baa06420f837184130752b7c5ea0808762083bf3487b5038d68b012e5937dbe", + "sha256:5e330fc79bd7207e46c7d7fd2bb4af2963f5f635703925543a70b99574b0fea9", + "sha256:61b9a528fb348373c433e8966535074b802c7a5d7f23c4f421e6c6e2f1697a6f", + "sha256:63426706118b7f5cf6bb6c895dc215d8a418d5952544042c8a2d9fe87fcf09cb", + "sha256:6d040ef7c9859bb11dfeb056ff5b3872436e3b5e401817d87a31e1750b9ae2fb", + "sha256:6f48351d66575f535669306aa7d6d6f71bc43372473b54a832222803eb956fd1", + "sha256:7ee7d9d4822c8acc74a5e26c50604dff824710bc8de424904c0982e25c39c6cb", + "sha256:81c13a1fc7468c40f13420732805a4c38a105d89848b7c10af65a90beff25250", + "sha256:8d13c64ee2d33eccf7437961b6ea7ad8673e2be040b4f7fd4fd4d4d28d9ccb1e", + "sha256:8de8bb0e5ad103888d65abef8bca41ab93721647590a3f740100cd65c3b00511", + "sha256:8fa03bce9bfbeeef9f3b160a8bed39a221d82308b4152b27d82d8daa7041fee5", + "sha256:924d94291ca674905fe9481f12294eb11f2d3d3fd1adb20314ba89e94f44ed59", + "sha256:975d70ab7e3c80a3fe86001d8751f6778905ec723f5b110aed1e450da9d4b7f2", + "sha256:976b9c42fb2a43ebf304fa7d4a310e5f16cc99992f33eced91ef6f908bd8f33d", + "sha256:9e31cb64d7de6b6f09702bb27c02d1904b3aebfca610c12772452c4e6c21a0d3", + "sha256:a342242fe22407f3c17f4b499276a02b01e80f861f1682ad1d95b04018e0c0d4", + "sha256:a3d33a6b3eae87ceaefa91ffdc130b5e8536182cd6dfdbfc1aa56b46ff8c86de", + "sha256:a895fcc7b15c3fc72beb43cdcbdf0ddb7d2ebc959edac9cef390b0d14f39f8a9", + "sha256:afb17f84d56068a7c29f5fa37bfd38d5aba69e3304af08ee94da8ed5b0865833", + "sha256:b1c546aca0ca4d028901d825015dc8e4d56aac4b541877690eb76490f1dc8ed0", + "sha256:b29019c76039dc3c0fd815c41392a044ce555d9bcdd38b0fb60fb4cd8e475ba9", + "sha256:b46517c02ccd08092f4fa99f24c3b83d8f92f739b4657b0f146246a0ca6a831d", + "sha256:b7aa5f8a41217360e600da646004f878250a0d6738bcdc11a0a39928d7dc2050", + "sha256:b7b4c971f05e6ae490fef852c218b0e79d4e52f79ef0c8475566584a8fb3e01d", + "sha256:ba90a9563ba44a72fda2e85302c3abc71c5589cea608ca16c22b9804262aaeb6", + "sha256:cb017fd1b2603ef59e374ba2063f593abe0fc45f2ad9abdde5b4d83bd922a353", + "sha256:d22656368f0e6189e24722214ed8d66b8022db19d182927b9a248a2a8a2f67eb", + "sha256:d2c2db7fd82e9b72937969bceac4d6ca89660db0a0967614ce2481e81a0b771e", + "sha256:d39b5b4f2a66ccae8b7263ac3c8170994b65266797fb96cbbfd3fb5b23921db8", + "sha256:d62a5c7dad11015c66fbb9d881bc4caa5b12f16292f857842d9d1871595f4495", + "sha256:e7d9405291c6928619403db1d10bd07888888ec1abcbd9748fdaa971d7d661b2", + "sha256:e84606b74eb7de6ff581a7915e2dab7a28a0517fbe1c9239eb227e1354064dcd", + "sha256:eb393e5ebc85245347950143969b241d08b52b88a3dc39479822e073a1a8eb27", + "sha256:ebba1cd308ef115925421d3e6a586e655ca5a77b5bf41e02eb0e4562a111f2d1", + "sha256:ee57190f24fba796e36bb6d3aa8a8783c643d8fa9760c89f7a98ab5455fbf818", + "sha256:f2f67fe12b22cd130d34d0ef79206061bfb5eda52feb6ce0dba0644e20a03cf4", + "sha256:f6951407391b639504e3b3be51b7ba5f3528adbf1a8ac3302b687ecababf929e", + "sha256:f75f7168ab25dd93110c8a8117a22450c19976afbc44234cbf71481094c1b850", + "sha256:fdec9e8cbf13a5bf63290fc6013d216a4c7232efb51548594ca3631a7f13c3a3" + ], + "markers": "python_version >= '3.7'", + "version": "==7.2.7" + }, + "decorator": { + "hashes": [ + "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330", + "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186" + ], + "markers": "python_version >= '3.5'", + "version": "==5.1.1" + }, + "distlib": { + "hashes": [ + "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057", + "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8" + ], + "version": "==0.3.7" + }, + "executing": { + "hashes": [ + "sha256:0314a69e37426e3608aada02473b4161d4caf5a4b244d1d0c48072b8fee7bacc", + "sha256:19da64c18d2d851112f09c287f8d3dbbdf725ab0e569077efb6cdcbd3497c107" + ], + "version": "==1.2.0" + }, + "filelock": { + "hashes": [ + "sha256:002740518d8aa59a26b0c76e10fb8c6e15eae825d34b6fdf670333fd7b938d81", + "sha256:cbb791cdea2a72f23da6ac5b5269ab0a0d161e9ef0100e653b69049a7706d1ec" + ], + "markers": "python_version >= '3.7'", + "version": "==3.12.2" + }, + "identify": { + "hashes": [ + "sha256:9df2489842707d431b38ce3410ef8df40da5b10a3e28a3fcac1a42523e956409", + "sha256:db4de0e758c0db8f81996816cd2f3f2f8c5c8d49a7fd02f3b4109aac6fd80e29" + ], + "markers": "python_version >= '3.8'", + "version": "==2.5.25" + }, + "iniconfig": { + "hashes": [ + "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", + "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374" + ], + "markers": "python_version >= '3.7'", + "version": "==2.0.0" + }, + "ipython": { + "hashes": [ + "sha256:1d197b907b6ba441b692c48cf2a3a2de280dc0ac91a3405b39349a50272ca0a1", + "sha256:248aca623f5c99a6635bc3857677b7320b9b8039f99f070ee0d20a5ca5a8e6bf" + ], + "index": "pypi", + "version": "==8.14.0" + }, + "isort": { + "hashes": [ + "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504", + "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6" + ], + "index": "pypi", + "version": "==5.12.0" + }, + "jedi": { + "hashes": [ + "sha256:203c1fd9d969ab8f2119ec0a3342e0b49910045abe6af0a3ae83a5764d54639e", + "sha256:bae794c30d07f6d910d32a7048af09b5a39ed740918da923c6b780790ebac612" + ], + "markers": "python_version >= '3.6'", + "version": "==0.18.2" + }, + "matplotlib-inline": { + "hashes": [ + "sha256:f1f41aab5328aa5aaea9b16d083b128102f8712542f819fe7e6a420ff581b311", + "sha256:f887e5f10ba98e8d2b150ddcf4702c1e5f8b3a20005eb0f74bfdbd360ee6f304" + ], + "markers": "python_version >= '3.5'", + "version": "==0.1.6" + }, + "mypy-extensions": { + "hashes": [ + "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", + "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.0" + }, + "nodeenv": { + "hashes": [ + "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2", + "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", + "version": "==1.8.0" + }, + "packaging": { + "hashes": [ + "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61", + "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f" + ], + "markers": "python_version >= '3.7'", + "version": "==23.1" + }, + "parso": { + "hashes": [ + "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0", + "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75" + ], + "markers": "python_version >= '3.6'", + "version": "==0.8.3" + }, + "pathspec": { + "hashes": [ + "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687", + "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293" + ], + "markers": "python_version >= '3.7'", + "version": "==0.11.1" + }, + "pexpect": { + "hashes": [ + "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937", + "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c" + ], + "markers": "sys_platform != 'win32'", + "version": "==4.8.0" + }, + "pickleshare": { + "hashes": [ + "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca", + "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56" + ], + "version": "==0.7.5" + }, + "platformdirs": { + "hashes": [ + "sha256:1b42b450ad933e981d56e59f1b97495428c9bd60698baab9f3eb3d00d5822421", + "sha256:ad8291ae0ae5072f66c16945166cb11c63394c7a3ad1b1bc9828ca3162da8c2f" + ], + "markers": "python_version >= '3.7'", + "version": "==3.9.1" + }, + "pluggy": { + "hashes": [ + "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849", + "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3" + ], + "markers": "python_version >= '3.7'", + "version": "==1.2.0" + }, + "pre-commit": { + "hashes": [ + "sha256:10badb65d6a38caff29703362271d7dca483d01da88f9d7e05d0b97171c136cb", + "sha256:a2256f489cd913d575c145132ae196fe335da32d91a8294b7afe6622335dd023" + ], + "index": "pypi", + "version": "==3.3.3" + }, + "prompt-toolkit": { + "hashes": [ + "sha256:04505ade687dc26dc4284b1ad19a83be2f2afe83e7a828ace0c72f3a1df72aac", + "sha256:9dffbe1d8acf91e3de75f3b544e4842382fc06c6babe903ac9acb74dc6e08d88" + ], + "markers": "python_full_version >= '3.7.0'", + "version": "==3.0.39" + }, + "ptyprocess": { + "hashes": [ + "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", + "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220" + ], + "version": "==0.7.0" + }, + "pure-eval": { + "hashes": [ + "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350", + "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3" + ], + "version": "==0.2.2" + }, + "pygments": { + "hashes": [ + "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c", + "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1" + ], + "markers": "python_version >= '3.7'", + "version": "==2.15.1" + }, + "pytest": { + "hashes": [ + "sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32", + "sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a" + ], + "index": "pypi", + "version": "==7.4.0" + }, + "pytest-cov": { + "hashes": [ + "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6", + "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a" + ], + "index": "pypi", + "version": "==4.1.0" + }, + "pyyaml": { + "hashes": [ + "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97", + "sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76", + "sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2", + "sha256:6034f55dab5fea9e53f436aa68fa3ace2634918e8b5994d82f3621c04ff5ed2e", + "sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648", + "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf", + "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f", + "sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2", + "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee", + "sha256:ad9c67312c84def58f3c04504727ca879cb0013b2517c85a9a253f0cb6380c0a", + "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d", + "sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c", + "sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a" + ], + "index": "pypi", + "version": "==5.3.1" + }, + "setuptools": { + "hashes": [ + "sha256:11e52c67415a381d10d6b462ced9cfb97066179f0e871399e006c4ab101fc85f", + "sha256:baf1fdb41c6da4cd2eae722e135500da913332ab3f2f5c7d33af9b492acb5235" + ], + "markers": "python_version >= '3.7'", + "version": "==68.0.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'", + "version": "==1.16.0" + }, + "stack-data": { + "hashes": [ + "sha256:32d2dd0376772d01b6cb9fc996f3c8b57a357089dec328ed4b6553d037eaf815", + "sha256:cbb2a53eb64e5785878201a97ed7c7b94883f48b87bfb0bbe8b623c74679e4a8" + ], + "version": "==0.6.2" + }, + "traitlets": { + "hashes": [ + "sha256:9e6ec080259b9a5940c797d58b613b5e31441c2257b87c2e795c5228ae80d2d8", + "sha256:f6cde21a9c68cf756af02035f72d5a723bf607e862e7be33ece505abf4a3bad9" + ], + "markers": "python_version >= '3.7'", + "version": "==5.9.0" + }, + "virtualenv": { + "hashes": [ + "sha256:01aacf8decd346cf9a865ae85c0cdc7f64c8caa07ff0d8b1dfc1733d10677442", + "sha256:2ef6a237c31629da6442b0bcaa3999748108c7166318d1f55cc9f8d7294e97bd" + ], + "markers": "python_version >= '3.7'", + "version": "==20.24.1" + }, + "wcwidth": { + "hashes": [ + "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e", + "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0" + ], + "version": "==0.2.6" + } + } +} diff --git a/README.md b/README.md index 14f2c22f..0a0c6731 100644 --- a/README.md +++ b/README.md @@ -42,15 +42,14 @@ ### Create & Activate Virtual Environment ```bash -python3 -m venv env # should be python 3.8 -source env/bin/activate +python3 -m pip install pipenv # It must be Python 3.11 +pipenv shell ``` ### Install Requirements ```bash -pip install poetry -poetry install # in production - $ poetry install --no-dev +pipenv install --dev # `--dev` flag for development pre-commit install ``` @@ -175,22 +174,21 @@ For managing docker images, we are using AWS ECR, `newara` repository. ### Interpreter -- `Python 3.7` -- `poetry` is used as package manager +- `Python 3.11` +- `Pipenv` is used as package manager - When adding libraries to the virtual environment, you should not use `pip`. - Rather, use `poetry add` command. Refer to [this link](https://python-poetry.org/docs/cli/) - for poetry commands. + Rather, use `pipenv` command. Refer to [this link](https://pipenv.pypa.io/en/latest/commands/) + for pipenv commands. ### Framework -- `Django 3.2` +- `Django 4.2` - `djangorestframework 3.14` ### Database -- MySQL (default) -- `mysqlclient 2.1` -- `django-mysql 3.12` +- MySQL 8.0 +- `mysqlclient 2.2` Works with MySQL for Linux & macOS, not tested in Windows. Timezone is automatically adjusted. It is strongly recommended to set default charset of @@ -199,7 +197,7 @@ database or MySQL server to `utf8mb4`. ### Storage - AWS S3 -- `django-s3-storage 0.13` +- `django-s3-storage 0.14` Two buckets are used - one for storing static files, one for media files that users upload. Go to django-s3-storage documentation for required permissions. @@ -211,7 +209,7 @@ users upload. Go to django-s3-storage documentation for required permissions. ### API Documentation -- `drf-yasg 1.21` +- `drf-spectacular 0.26` --- diff --git a/apps/core/admin.py b/apps/core/admin.py index d6d29883..d6f4415e 100644 --- a/apps/core/admin.py +++ b/apps/core/admin.py @@ -10,6 +10,7 @@ BestComment, BestSearch, Board, + BoardGroup, Comment, CommentDeleteLog, CommunicationArticle, @@ -17,7 +18,6 @@ Topic, ) from ara.classes.admin import MetaDataModelAdmin -from ara.settings import MIN_TIME class HiddenContentListFilter(admin.SimpleListFilter): @@ -42,14 +42,22 @@ class BoardAdmin(MetaDataModelAdmin): list_display = ( "ko_name", "en_name", + "group", "is_readonly", "is_hidden", ) search_fields = ( "ko_name", "en_name", - "ko_description", - "en_description", + ) + + +@admin.register(BoardGroup) +class BoardGroupAdmin(admin.ModelAdmin): + list_display = ( + "slug", + "ko_name", + "en_name", ) @@ -63,8 +71,6 @@ class TopicAdmin(MetaDataModelAdmin): search_fields = ( "ko_name", "en_name", - "ko_description", - "en_description", ) list_filter = ("parent_board",) @@ -123,7 +129,7 @@ class ArticleAdmin(MetaDataModelAdmin): "content_updated_at", "commented_at", "url", - "hidden_at", + ("hidden_at", "topped_at"), ) readonly_fields = ( "hit_count", diff --git a/apps/core/filters/article.py b/apps/core/filters/article.py index f680fb99..9364617e 100644 --- a/apps/core/filters/article.py +++ b/apps/core/filters/article.py @@ -1,11 +1,12 @@ -import rest_framework_filters as filters -from django.db import models +from django_filters.rest_framework import CharFilter, FilterSet from apps.core.documents import ArticleDocument from apps.core.models import Article -class ArticleFilter(filters.FilterSet): +class ArticleFilter(FilterSet): + board = CharFilter(field_name="parent_board__slug", lookup_expr="exact") + class Meta: model = Article fields = { @@ -46,10 +47,13 @@ class Meta: "in", "exact", ], - "communication_article__school_response_status": ["exact", "lt"], + "communication_article__school_response_status": [ + "exact", + "lt", + ], } - main_search__contains = filters.CharFilter( + main_search__contains = CharFilter( field_name="main_search", label="메인 검색 (제목포함, 본문포함, 닉네임일치)", method="get_main_search__contains", diff --git a/apps/core/filters/comment.py b/apps/core/filters/comment.py index a4a28af0..1e96cdd8 100644 --- a/apps/core/filters/comment.py +++ b/apps/core/filters/comment.py @@ -1,9 +1,9 @@ -import rest_framework_filters as filters +from django_filters.rest_framework import FilterSet from apps.core.models import Comment -class CommentFilter(filters.FilterSet): +class CommentFilter(FilterSet): class Meta: model = Comment fields = { diff --git a/apps/core/filters/notification.py b/apps/core/filters/notification.py index 56e0eab8..9042dbe6 100644 --- a/apps/core/filters/notification.py +++ b/apps/core/filters/notification.py @@ -1,9 +1,9 @@ -import rest_framework_filters as filters +from django_filters.rest_framework import BooleanFilter, FilterSet from apps.core.models import Notification -class NotificationFilter(filters.FilterSet): +class NotificationFilter(FilterSet): class Meta: model = Notification fields = { @@ -27,7 +27,7 @@ class Meta: ], } - is_read = filters.BooleanFilter( + is_read = BooleanFilter( field_name="is_read", label="조회 여부", method="get_is_read", diff --git a/apps/core/management/scripts/portal_crawler.py b/apps/core/management/scripts/portal_crawler.py index c2913351..70a5a000 100644 --- a/apps/core/management/scripts/portal_crawler.py +++ b/apps/core/management/scripts/portal_crawler.py @@ -2,9 +2,9 @@ import re import uuid from datetime import datetime +from pytz import timezone as pytz_timezone import boto3 -import pyotp import requests from bs4 import BeautifulSoup as bs from django.contrib.auth import get_user_model @@ -17,7 +17,6 @@ from apps.user.models import UserProfile from ara.settings import ( AWS_S3_BUCKET_NAME, - PORTAL_2FA_KEY, PORTAL_ID, PORTAL_JSESSIONID, PORTAL_PASSWORD, @@ -40,10 +39,7 @@ BASE_URL = "https://portal.kaist.ac.kr" - -def _make_2fa_token(): - totp = pyotp.TOTP(PORTAL_2FA_KEY) - return totp.now() +KST = pytz_timezone("Asia/Seoul") def _login_kaist_portal(): @@ -139,8 +135,10 @@ def _save_portal_image(html, session): .strip() .split("(")[0] ) - created_at = timezone.get_current_timezone().localize( + created_at = ( datetime.strptime(created_at_str, "%Y.%m.%d %H:%M:%S") + .astimezone(KST) + .astimezone(timezone.utc) ) title = soup.select("table > tbody > tr > td.req_first")[0].contents[0] @@ -356,7 +354,7 @@ def _get_board(page_num): user = get_user_model().objects.create( username=str(uuid.uuid1()), is_active=False ) - user_profile = UserProfile.objects.create( + UserProfile.objects.create( is_newara=False, user=user, nickname=info["writer"], diff --git a/apps/core/migrations/0001_initial.py b/apps/core/migrations/0001_initial.py index 31d346c7..4bbca362 100644 --- a/apps/core/migrations/0001_initial.py +++ b/apps/core/migrations/0001_initial.py @@ -6,13 +6,11 @@ import django.db.models.deletion import django_extensions.db.fields -import django_mysql.models from django.conf import settings from django.db import migrations, models class Migration(migrations.Migration): - initial = True dependencies = [ @@ -230,7 +228,7 @@ class Migration(migrations.Migration): default=datetime.datetime(1, 1, 1, 0, 0), verbose_name="삭제 시간" ), ), - ("data", django_mysql.models.JSONField(default=dict)), + ("data", models.JSONField(default=dict)), ( "article", models.ForeignKey( @@ -705,7 +703,7 @@ class Migration(migrations.Migration): default=datetime.datetime(1, 1, 1, 0, 0), verbose_name="삭제 시간" ), ), - ("data", django_mysql.models.JSONField(default=dict)), + ("data", models.JSONField(default=dict)), ( "comment", models.ForeignKey( diff --git a/apps/core/migrations/0013_set_minimum_datetime_timezone.py b/apps/core/migrations/0013_set_minimum_datetime_timezone.py index fb15cd30..981893c0 100644 --- a/apps/core/migrations/0013_set_minimum_datetime_timezone.py +++ b/apps/core/migrations/0013_set_minimum_datetime_timezone.py @@ -3,11 +3,9 @@ import datetime from django.db import migrations, models -from django.utils.timezone import utc class Migration(migrations.Migration): - dependencies = [ ("core", "0012_auto_add_updated_at"), ] @@ -18,7 +16,7 @@ class Migration(migrations.Migration): name="deleted_at", field=models.DateTimeField( db_index=True, - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="삭제 시간", ), ), @@ -27,7 +25,7 @@ class Migration(migrations.Migration): name="deleted_at", field=models.DateTimeField( db_index=True, - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="삭제 시간", ), ), @@ -36,7 +34,7 @@ class Migration(migrations.Migration): name="deleted_at", field=models.DateTimeField( db_index=True, - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="삭제 시간", ), ), @@ -45,7 +43,7 @@ class Migration(migrations.Migration): name="deleted_at", field=models.DateTimeField( db_index=True, - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="삭제 시간", ), ), @@ -54,7 +52,7 @@ class Migration(migrations.Migration): name="deleted_at", field=models.DateTimeField( db_index=True, - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="삭제 시간", ), ), @@ -63,7 +61,7 @@ class Migration(migrations.Migration): name="deleted_at", field=models.DateTimeField( db_index=True, - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="삭제 시간", ), ), @@ -72,7 +70,7 @@ class Migration(migrations.Migration): name="deleted_at", field=models.DateTimeField( db_index=True, - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="삭제 시간", ), ), @@ -81,7 +79,7 @@ class Migration(migrations.Migration): name="deleted_at", field=models.DateTimeField( db_index=True, - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="삭제 시간", ), ), @@ -90,7 +88,7 @@ class Migration(migrations.Migration): name="deleted_at", field=models.DateTimeField( db_index=True, - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="삭제 시간", ), ), @@ -99,7 +97,7 @@ class Migration(migrations.Migration): name="deleted_at", field=models.DateTimeField( db_index=True, - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="삭제 시간", ), ), @@ -108,7 +106,7 @@ class Migration(migrations.Migration): name="deleted_at", field=models.DateTimeField( db_index=True, - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="삭제 시간", ), ), @@ -117,7 +115,7 @@ class Migration(migrations.Migration): name="deleted_at", field=models.DateTimeField( db_index=True, - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="삭제 시간", ), ), @@ -126,7 +124,7 @@ class Migration(migrations.Migration): name="deleted_at", field=models.DateTimeField( db_index=True, - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="삭제 시간", ), ), @@ -135,7 +133,7 @@ class Migration(migrations.Migration): name="deleted_at", field=models.DateTimeField( db_index=True, - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="삭제 시간", ), ), @@ -144,7 +142,7 @@ class Migration(migrations.Migration): name="deleted_at", field=models.DateTimeField( db_index=True, - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="삭제 시간", ), ), @@ -153,7 +151,7 @@ class Migration(migrations.Migration): name="deleted_at", field=models.DateTimeField( db_index=True, - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="삭제 시간", ), ), @@ -162,7 +160,7 @@ class Migration(migrations.Migration): name="deleted_at", field=models.DateTimeField( db_index=True, - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="삭제 시간", ), ), @@ -171,7 +169,7 @@ class Migration(migrations.Migration): name="deleted_at", field=models.DateTimeField( db_index=True, - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="삭제 시간", ), ), @@ -180,7 +178,7 @@ class Migration(migrations.Migration): name="deleted_at", field=models.DateTimeField( db_index=True, - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="삭제 시간", ), ), diff --git a/apps/core/migrations/0020_bestsearch.py b/apps/core/migrations/0020_bestsearch.py index a12cb3bc..c071a180 100644 --- a/apps/core/migrations/0020_bestsearch.py +++ b/apps/core/migrations/0020_bestsearch.py @@ -3,7 +3,6 @@ import datetime from django.db import migrations, models -from django.utils.timezone import utc class Migration(migrations.Migration): @@ -41,7 +40,7 @@ class Migration(migrations.Migration): "deleted_at", models.DateTimeField( db_index=True, - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="삭제 시간", ), ), diff --git a/apps/core/migrations/0028_add_report_counts.py b/apps/core/migrations/0028_add_report_counts.py index 7256b51c..23269d23 100644 --- a/apps/core/migrations/0028_add_report_counts.py +++ b/apps/core/migrations/0028_add_report_counts.py @@ -3,7 +3,6 @@ import datetime from django.db import migrations, models -from django.utils.timezone import utc class Migration(migrations.Migration): @@ -18,7 +17,7 @@ class Migration(migrations.Migration): name="hidden_at", field=models.DateTimeField( db_index=True, - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="임시 삭제 시간", ), ), @@ -32,7 +31,7 @@ class Migration(migrations.Migration): name="hidden_at", field=models.DateTimeField( db_index=True, - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="임시 삭제 시간", ), ), diff --git a/apps/core/migrations/0029_delete_db_index_hidden_at.py b/apps/core/migrations/0029_delete_db_index_hidden_at.py index a03310ca..1fca9282 100644 --- a/apps/core/migrations/0029_delete_db_index_hidden_at.py +++ b/apps/core/migrations/0029_delete_db_index_hidden_at.py @@ -3,7 +3,6 @@ import datetime from django.db import migrations, models -from django.utils.timezone import utc class Migration(migrations.Migration): @@ -17,7 +16,7 @@ class Migration(migrations.Migration): model_name="article", name="hidden_at", field=models.DateTimeField( - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="숨김 시간", ), ), @@ -25,7 +24,7 @@ class Migration(migrations.Migration): model_name="comment", name="hidden_at", field=models.DateTimeField( - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="숨김 시간", ), ), diff --git a/apps/core/migrations/0038_rename_is_anonymous_to_name_type.py b/apps/core/migrations/0038_rename_is_anonymous_to_name_type.py index 9149d8bf..6a86f840 100644 --- a/apps/core/migrations/0038_rename_is_anonymous_to_name_type.py +++ b/apps/core/migrations/0038_rename_is_anonymous_to_name_type.py @@ -2,11 +2,10 @@ from django.db import migrations, models -import apps.core.models.board +from apps.core.models.board import NameType class Migration(migrations.Migration): - dependencies = [ ("core", "0037_board_banner_url"), ] @@ -21,7 +20,7 @@ class Migration(migrations.Migration): model_name="article", name="name_type", field=models.SmallIntegerField( - default=apps.core.models.board.BoardNameType["REGULAR"], + default=NameType["REGULAR"], verbose_name="익명 혹은 실명 여부", ), ), @@ -35,7 +34,7 @@ class Migration(migrations.Migration): name="name_type", field=models.SmallIntegerField( db_index=True, - default=apps.core.models.board.BoardNameType["REGULAR"], + default=NameType["REGULAR"], help_text="게시판의 글과 댓글들이 익명 혹은 실명이도록 합니다.", verbose_name="익명/실명 게시판", ), @@ -49,7 +48,7 @@ class Migration(migrations.Migration): model_name="comment", name="name_type", field=models.SmallIntegerField( - default=apps.core.models.board.BoardNameType["REGULAR"], + default=NameType["REGULAR"], verbose_name="익명 혹은 실명", ), ), diff --git a/apps/core/migrations/0039_add_communication_article.py b/apps/core/migrations/0039_add_communication_article.py index c76e0e5d..397cb209 100644 --- a/apps/core/migrations/0039_add_communication_article.py +++ b/apps/core/migrations/0039_add_communication_article.py @@ -5,7 +5,6 @@ import django.db.models.deletion import django.utils.timezone from django.db import migrations, models -from django.utils.timezone import utc import apps.core.models.communication_article @@ -57,28 +56,28 @@ class Migration(migrations.Migration): "deleted_at", models.DateTimeField( db_index=True, - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="삭제 시간", ), ), ( "response_deadline", models.DateTimeField( - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="답변 요청 기한", ), ), ( "confirmed_by_school_at", models.DateTimeField( - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="학교측 문의 확인 시각", ), ), ( "answered_at", models.DateTimeField( - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="학교측 답변을 받은 시각", ), ), diff --git a/apps/core/migrations/0047_alter_board_name_type.py b/apps/core/migrations/0047_alter_board_name_type.py new file mode 100644 index 00000000..0e305e1e --- /dev/null +++ b/apps/core/migrations/0047_alter_board_name_type.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.16 on 2023-05-09 13:57 + +import apps.core.models.board +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("core", "0046_update_hidden_at_min_time_to_null"), + ] + + operations = [ + migrations.AlterField( + model_name="board", + name="name_type", + field=models.SmallIntegerField( + db_index=True, + default=apps.core.models.board.NameType["REGULAR"], + help_text="글과 댓글을 어떤 이름 설정(닉네임/익명/실명)으로 작성할 수 있는지 정의합니다.", + verbose_name="닉네임/익명/실명글 허용 여부 설정", + ), + ), + ] diff --git a/apps/core/migrations/0048_update_board_name_type_flag.py b/apps/core/migrations/0048_update_board_name_type_flag.py new file mode 100644 index 00000000..f065d30b --- /dev/null +++ b/apps/core/migrations/0048_update_board_name_type_flag.py @@ -0,0 +1,43 @@ +# Generated by retro on 2023-05-09 14:03 + +from django.db import migrations + +from apps.core.models.board import Board, NameType +from apps.core.models.article import Article +from apps.core.models.comment import Comment +from django.db import transaction + + +@transaction.atomic +def update_nametypes(apps, schema_editor): + regular_boards = Board.objects.filter(name_type=0).values() + anonymous_boards = Board.objects.filter(name_type=1).values() + realname_boards = Board.objects.filter(name_type=2).values() + + realname_boards.update(name_type=NameType.REALNAME) + anonymous_boards.update(name_type=NameType.ANONYMOUS) + regular_boards.update(name_type=NameType.REGULAR) + + regular_articles = Article.objects.filter(name_type=0).values() + anonymous_articles = Article.objects.filter(name_type=1).values() + realname_articles = Article.objects.filter(name_type=2).values() + + realname_articles.update(name_type=NameType.REALNAME) + anonymous_articles.update(name_type=NameType.ANONYMOUS) + regular_articles.update(name_type=NameType.REGULAR) + + regular_comments = Comment.objects.filter(name_type=0).values() + anonymous_comments = Comment.objects.filter(name_type=1).values() + realname_comments = Comment.objects.filter(name_type=2).values() + + realname_comments.update(name_type=NameType.REALNAME) + anonymous_comments.update(name_type=NameType.ANONYMOUS) + regular_comments.update(name_type=NameType.REGULAR) + + +class Migration(migrations.Migration): + dependencies = [ + ("core", "0047_alter_board_name_type"), + ] + + operations = [migrations.RunPython(update_nametypes)] diff --git a/apps/core/migrations/0049_article_topped_at.py b/apps/core/migrations/0049_article_topped_at.py new file mode 100644 index 00000000..e16feeac --- /dev/null +++ b/apps/core/migrations/0049_article_topped_at.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.16 on 2023-05-11 11:29 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("core", "0048_update_board_name_type_flag"), + ] + + operations = [ + migrations.AddField( + model_name="article", + name="topped_at", + field=models.DateTimeField( + blank=True, default=None, null=True, verbose_name="인기글 달성 시각" + ), + ), + ] diff --git a/apps/core/migrations/0050_board_top_threshold.py b/apps/core/migrations/0050_board_top_threshold.py new file mode 100644 index 00000000..7d1fb418 --- /dev/null +++ b/apps/core/migrations/0050_board_top_threshold.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.16 on 2023-05-11 13:23 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("core", "0049_article_topped_at"), + ] + + operations = [ + migrations.AddField( + model_name="board", + name="top_threshold", + field=models.SmallIntegerField(default=10, verbose_name="인기글 달성 기준 좋아요 개수"), + ), + ] diff --git a/apps/core/migrations/0051_remove_board_en_description_and_more.py b/apps/core/migrations/0051_remove_board_en_description_and_more.py new file mode 100644 index 00000000..952cfdb1 --- /dev/null +++ b/apps/core/migrations/0051_remove_board_en_description_and_more.py @@ -0,0 +1,28 @@ +# Generated by Django 4.2.3 on 2023-07-17 12:52 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("core", "0050_board_top_threshold"), + ] + + operations = [ + migrations.RemoveField( + model_name="board", + name="en_description", + ), + migrations.RemoveField( + model_name="board", + name="ko_description", + ), + migrations.RemoveField( + model_name="topic", + name="en_description", + ), + migrations.RemoveField( + model_name="topic", + name="ko_description", + ), + ] diff --git a/apps/core/migrations/0052_alter_board_slug.py b/apps/core/migrations/0052_alter_board_slug.py new file mode 100644 index 00000000..ef653604 --- /dev/null +++ b/apps/core/migrations/0052_alter_board_slug.py @@ -0,0 +1,20 @@ +# Generated by Django 4.2.3 on 2023-07-21 04:48 + +from django.db import migrations +import django_extensions.db.fields + + +class Migration(migrations.Migration): + dependencies = [ + ("core", "0051_remove_board_en_description_and_more"), + ] + + operations = [ + migrations.AlterField( + model_name="board", + name="slug", + field=django_extensions.db.fields.AutoSlugField( + blank=True, editable=False, populate_from=["en_name"], unique=True + ), + ), + ] diff --git a/apps/core/migrations/0053_remove_board_banner_url_and_more.py b/apps/core/migrations/0053_remove_board_banner_url_and_more.py new file mode 100644 index 00000000..4deb1456 --- /dev/null +++ b/apps/core/migrations/0053_remove_board_banner_url_and_more.py @@ -0,0 +1,30 @@ +# Generated by Django 4.2.3 on 2023-07-21 12:04 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("core", "0052_alter_board_slug"), + ] + + operations = [ + migrations.RemoveField( + model_name="board", + name="banner_url", + ), + migrations.AlterField( + model_name="board", + name="en_banner_description", + field=models.TextField( + blank=True, default="", verbose_name="게시판 배너에 삽입되는 영문 소개" + ), + ), + migrations.AlterField( + model_name="board", + name="ko_banner_description", + field=models.TextField( + blank=True, default="", verbose_name="게시판 배너에 삽입되는 국문 소개" + ), + ), + ] diff --git a/apps/core/migrations/0054_boardgroup.py b/apps/core/migrations/0054_boardgroup.py new file mode 100644 index 00000000..c656e44b --- /dev/null +++ b/apps/core/migrations/0054_boardgroup.py @@ -0,0 +1,42 @@ +# Generated by Django 4.2.3 on 2023-07-21 12:40 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("core", "0053_remove_board_banner_url_and_more"), + ] + + operations = [ + migrations.CreateModel( + name="BoardGroup", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "ko_name", + models.CharField(max_length=64, verbose_name="게시판 그룹 국문 이름"), + ), + ( + "en_name", + models.CharField(max_length=64, verbose_name="게시판 그룹 영문 이름"), + ), + ( + "slug", + models.SlugField(max_length=32, unique=True, verbose_name="슬러그"), + ), + ], + options={ + "verbose_name": "게시판 그룹", + "verbose_name_plural": "게시판 그룹 목록", + }, + ), + ] diff --git a/apps/core/migrations/0055_remove_board_group_id_board_group.py b/apps/core/migrations/0055_remove_board_group_id_board_group.py new file mode 100644 index 00000000..dbb1a20a --- /dev/null +++ b/apps/core/migrations/0055_remove_board_group_id_board_group.py @@ -0,0 +1,29 @@ +# Generated by Django 4.2.3 on 2023-07-22 14:30 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + dependencies = [ + ("core", "0054_boardgroup"), + ] + + operations = [ + migrations.RemoveField( + model_name="board", + name="group_id", + ), + migrations.AddField( + model_name="board", + name="group", + field=models.ForeignKey( + default=None, + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="boards", + to="core.boardgroup", + verbose_name="게시판 그룹", + ), + ), + ] diff --git a/apps/core/models/__init__.py b/apps/core/models/__init__.py index 5d99a686..52eaaa10 100644 --- a/apps/core/models/__init__.py +++ b/apps/core/models/__init__.py @@ -6,6 +6,7 @@ from .best_search import * from .block import * from .board import * +from .board_group import * from .comment import * from .comment_log import * from .communication_article import * diff --git a/apps/core/models/article.py b/apps/core/models/article.py index c80b4de3..d5f33c53 100644 --- a/apps/core/models/article.py +++ b/apps/core/models/article.py @@ -1,9 +1,8 @@ -import typing from enum import Enum -from typing import Dict, Union import bs4 from django.conf import settings +from django.contrib.auth import get_user_model from django.core.files.storage import default_storage from django.db import IntegrityError, models, transaction from django.utils import timezone @@ -22,11 +21,13 @@ ) from .block import Block -from .board import BoardAccessPermissionType, BoardNameType +from .board import NameType, BoardAccessPermissionType from .comment import Comment from .communication_article import SchoolResponseStatus from .report import Report +User = get_user_model() + class ArticleHiddenReason(str, Enum): ADULT_CONTENT = "ADULT_CONTENT" @@ -37,128 +38,125 @@ class ArticleHiddenReason(str, Enum): class Article(MetaDataModel): - class Meta(MetaDataModel.Meta): - verbose_name = "게시물" - verbose_name_plural = "게시물 목록" - title = models.CharField( - max_length=256, verbose_name="제목", + max_length=256, ) content = models.TextField( verbose_name="본문", ) content_text = models.TextField( - editable=False, verbose_name="text 형식 본문", + editable=False, ) - name_type = models.SmallIntegerField( - default=BoardNameType.REGULAR, verbose_name="익명 혹은 실명 여부", + default=NameType.REGULAR, ) is_content_sexual = models.BooleanField( - default=False, verbose_name="성인/음란성 내용", + default=False, ) is_content_social = models.BooleanField( - default=False, verbose_name="정치/사회성 내용", + default=False, ) - hit_count = models.IntegerField( - default=0, verbose_name="조회수", + default=0, ) comment_count = models.IntegerField( - default=0, verbose_name="댓글 수", + default=0, ) report_count = models.IntegerField( - default=0, verbose_name="신고 수", + default=0, ) positive_vote_count = models.IntegerField( - default=0, verbose_name="좋아요 수", + default=0, ) negative_vote_count = models.IntegerField( - default=0, verbose_name="싫어요 수", + default=0, ) - migrated_hit_count = models.IntegerField( - default=0, verbose_name="이전된 조회수", + default=0, ) migrated_positive_vote_count = models.IntegerField( - default=0, verbose_name="이전된 좋아요 수", + default=0, ) migrated_negative_vote_count = models.IntegerField( - default=0, verbose_name="이전된 싫어요 수", + default=0, ) - created_by = models.ForeignKey( - on_delete=models.CASCADE, + verbose_name="작성자", to=settings.AUTH_USER_MODEL, - db_index=True, + on_delete=models.CASCADE, related_name="article_set", - verbose_name="작성자", + db_index=True, ) parent_topic = models.ForeignKey( - on_delete=models.CASCADE, + verbose_name="말머리", to="core.Topic", - null=True, + on_delete=models.CASCADE, + related_name="article_set", blank=True, - default=None, + null=True, db_index=True, - related_name="article_set", - verbose_name="말머리", + default=None, ) parent_board = models.ForeignKey( - on_delete=models.CASCADE, + verbose_name="게시판", to="core.Board", - db_index=True, + on_delete=models.CASCADE, related_name="article_set", - verbose_name="게시판", + db_index=True, ) - attachments = models.ManyToManyField( + verbose_name="첨부 파일(들)", to="core.Attachment", blank=True, db_index=True, - verbose_name="첨부 파일(들)", ) - commented_at = models.DateTimeField( + verbose_name="마지막 댓글 시간", null=True, default=None, - verbose_name="마지막 댓글 시간", ) - url = models.URLField( - null=True, + verbose_name="포탈 링크", max_length=200, blank=True, + null=True, default=None, - verbose_name="포탈 링크", ) - content_updated_at = models.DateTimeField( + verbose_name="제목/본문/첨부파일 수정 시간", null=True, default=None, - verbose_name="제목/본문/첨부파일 수정 시간", ) - hidden_at = models.DateTimeField( + verbose_name="숨김 시간", + blank=True, null=True, + default=None, + ) + topped_at = models.DateTimeField( + verbose_name="인기글 달성 시각", blank=True, + null=True, default=None, - verbose_name="숨김 시간", ) + class Meta(MetaDataModel.Meta): + verbose_name = "게시물" + verbose_name_plural = "게시물 목록" + def __str__(self): return self.title @@ -178,7 +176,7 @@ def save( self.content = sanitize(self.content) self.content_text = " ".join( - bs4.BeautifulSoup(self.content, features="html5lib").find_all(text=True) + bs4.BeautifulSoup(self.content, features="html5lib").find_all(string=True) ) super().save( @@ -223,7 +221,7 @@ def update_report_count(self): self.save() - def update_vote_status(self): + def update_vote_status(self) -> None: self.positive_vote_count = ( self.vote_set.filter(is_positive=True).count() + self.migrated_positive_vote_count @@ -233,6 +231,12 @@ def update_vote_status(self): + self.migrated_negative_vote_count ) + if ( + self.topped_at is None + and self.positive_vote_count >= self.parent_board.top_threshold + ): + self.topped_at = timezone.now() + if ( self.parent_board.is_school_communication and self.positive_vote_count >= SCHOOL_RESPONSE_VOTE_THRESHOLD @@ -258,8 +262,8 @@ def created_by_nickname(self): # API 상에서 보이는 사용자 (익명일 경우 익명화된 글쓴이, 그 외는 그냥 글쓴이) @cached_property - def postprocessed_created_by(self) -> Union[settings.AUTH_USER_MODEL, Dict]: - if self.name_type == BoardNameType.REGULAR: + def postprocessed_created_by(self) -> User | dict: + if self.name_type == NameType.REGULAR: return self.created_by user_unique_num = self.created_by.id + self.id + HASH_SECRET_VALUE @@ -268,7 +272,7 @@ def postprocessed_created_by(self) -> Union[settings.AUTH_USER_MODEL, Dict]: user_hash_int = int(user_hash[-4:], 16) user_profile_picture = get_profile_picture(user_hash_int) - if self.name_type == BoardNameType.ANONYMOUS: + if self.name_type == NameType.ANONYMOUS: return { "id": user_hash, "username": gettext("anonymous"), @@ -279,7 +283,7 @@ def postprocessed_created_by(self) -> Union[settings.AUTH_USER_MODEL, Dict]: }, } - if self.name_type == BoardNameType.REALNAME: + if self.name_type == NameType.REALNAME: user_realname = self.created_by.profile.realname return { "id": user_unique_num, @@ -292,7 +296,7 @@ def postprocessed_created_by(self) -> Union[settings.AUTH_USER_MODEL, Dict]: } @cache_by_user - def hidden_reasons(self, user: settings.AUTH_USER_MODEL) -> typing.List: + def hidden_reasons(self, user: User) -> list: reasons = [] if self.is_hidden_by_reported(): reasons.append(ArticleHiddenReason.REPORTED_CONTENT) diff --git a/apps/core/models/article_log.py b/apps/core/models/article_log.py index 3716588b..9a3fe31b 100644 --- a/apps/core/models/article_log.py +++ b/apps/core/models/article_log.py @@ -1,6 +1,5 @@ from django.conf import settings from django.db import models -from django_mysql.models import JSONField from ara.db.models import MetaDataManager, MetaDataModel, MetaDataQuerySet @@ -62,7 +61,7 @@ class Meta(MetaDataModel.Meta): queryset_class=ArticleUpdateLogQuerySet )() - data = JSONField() + data = models.JSONField(default=dict) updated_by = models.ForeignKey( on_delete=models.CASCADE, diff --git a/apps/core/models/board.py b/apps/core/models/board.py index e42766ad..1fdb4716 100644 --- a/apps/core/models/board.py +++ b/apps/core/models/board.py @@ -1,15 +1,16 @@ -from enum import IntEnum +from enum import IntEnum, IntFlag, auto from django.db import models from django_extensions.db.fields import AutoSlugField from ara.db.models import MetaDataModel +from .board_group import BoardGroup -class BoardNameType(IntEnum): - REGULAR = 0 - ANONYMOUS = 1 - REALNAME = 2 +class NameType(IntFlag): + REGULAR = auto() + ANONYMOUS = auto() + REALNAME = auto() class BoardAccessPermissionType(IntEnum): @@ -19,102 +20,96 @@ class BoardAccessPermissionType(IntEnum): class Board(MetaDataModel): - class Meta(MetaDataModel.Meta): - verbose_name = "게시판" - verbose_name_plural = "게시판 목록" - unique_together = ( - ("ko_name", "deleted_at"), - ("en_name", "deleted_at"), - ) - slug = AutoSlugField( - populate_from=[ - "en_name", - ], + populate_from=["en_name"], + unique=True, ) ko_name = models.CharField( - max_length=32, verbose_name="게시판 국문 이름", + max_length=32, ) en_name = models.CharField( - max_length=32, verbose_name="게시판 영문 이름", - ) - ko_description = models.TextField( - verbose_name="게시판 국문 소개", - ) - en_description = models.TextField( - verbose_name="게시판 영문 소개", + max_length=32, ) # 사용자 그룹에 대해 접근 권한을 제어하는 bit mask 입니다. # access_mask & (1 << user.group) > 0 일 때 접근이 가능합니다. # 사용자 그룹의 값들은 `UserGroup`을 참고하세요. read_access_mask = models.SmallIntegerField( # UNAUTHORIZED, EXTERNAL_ORG 제외 모든 사용자 읽기 권한 부여 - default=0b011011110, - null=False, verbose_name="읽기 권한", + default=0b011011110, ) write_access_mask = models.SmallIntegerField( # UNAUTHORIZED, STORE_EMPLOYEE, EXTERNAL_ORG 제외 모든 사용자 쓰기 권한 부여 - default=0b011011010, - null=False, verbose_name="쓰기 권한", + default=0b011011010, ) comment_access_mask = models.SmallIntegerField( # UNAUTHORIZED 제외 모든 사용자 댓글 권한 부여 - default=0b011111110, - null=False, verbose_name="댓글 권한", + default=0b011111110, ) is_readonly = models.BooleanField( verbose_name="읽기 전용 게시판", - help_text="활성화했을 때 관리자만 글을 쓸 수 있습니다. (ex. 포탈공지)", default=False, + help_text="활성화했을 때 관리자만 글을 쓸 수 있습니다. (ex. 포탈공지)", ) is_hidden = models.BooleanField( verbose_name="리스트 숨김 게시판", - help_text="활성화했을 때 메인페이지 상단바 리스트에 나타나지 않습니다. (ex. 뉴아라공지)", - default=False, db_index=True, + default=False, + help_text="활성화했을 때 메인페이지 상단바 리스트에 나타나지 않습니다. (ex. 뉴아라공지)", ) + name_type = models.SmallIntegerField( - verbose_name="익명/실명 게시판", - help_text="게시판의 글과 댓글들이 익명 혹은 실명이도록 합니다.", - default=BoardNameType.REGULAR, + verbose_name="닉네임/익명/실명글 허용 여부 설정", db_index=True, + default=NameType.REGULAR, + help_text="글과 댓글을 어떤 이름 설정(닉네임/익명/실명)으로 작성할 수 있는지 정의합니다.", ) is_school_communication = models.BooleanField( verbose_name="학교와의 소통 게시판", - help_text="학교 소통 게시판 글임을 표시", - default=False, db_index=True, + default=False, + help_text="학교 소통 게시판 글임을 표시", + ) + group: BoardGroup = models.ForeignKey( + to="core.BoardGroup", + on_delete=models.SET_NULL, + related_name="boards", + verbose_name="게시판 그룹", + null=True, + default=None, ) - group_id = models.IntegerField(verbose_name="그룹 ID", default=1) banner_image = models.ImageField( - default="default_banner.png", - upload_to="board_banner_images", verbose_name="게시판 배너 이미지", + upload_to="board_banner_images", + default="default_banner.png", ) ko_banner_description = models.TextField( - null=True, - blank=True, - default=None, verbose_name="게시판 배너에 삽입되는 국문 소개", + blank=True, + default="", ) en_banner_description = models.TextField( - null=True, - blank=True, - default=None, verbose_name="게시판 배너에 삽입되는 영문 소개", - ) - banner_url = models.TextField( - null=True, blank=True, - default=None, - verbose_name="게시판 배너를 클릭 시에 이동하는 링크", + default="", + ) + top_threshold = models.SmallIntegerField( + verbose_name="인기글 달성 기준 좋아요 개수", + default=10, ) + class Meta(MetaDataModel.Meta): + verbose_name = "게시판" + verbose_name_plural = "게시판 목록" + unique_together = ( + ("ko_name", "deleted_at"), + ("en_name", "deleted_at"), + ) + def __str__(self) -> str: return self.ko_name diff --git a/apps/core/models/board_group.py b/apps/core/models/board_group.py new file mode 100644 index 00000000..3f78fc04 --- /dev/null +++ b/apps/core/models/board_group.py @@ -0,0 +1,24 @@ +from django.db import models + + +class BoardGroup(models.Model): + ko_name = models.CharField( + verbose_name="게시판 그룹 국문 이름", + max_length=64, + ) + en_name = models.CharField( + verbose_name="게시판 그룹 영문 이름", + max_length=64, + ) + slug = models.SlugField( + verbose_name="슬러그", + max_length=32, + unique=True, + ) + + class Meta: + verbose_name = "게시판 그룹" + verbose_name_plural = "게시판 그룹 목록" + + def __str__(self) -> str: + return self.ko_name diff --git a/apps/core/models/comment.py b/apps/core/models/comment.py index e08cbc78..cc2c84b3 100644 --- a/apps/core/models/comment.py +++ b/apps/core/models/comment.py @@ -1,9 +1,8 @@ import hashlib -import typing from enum import Enum -from typing import Dict, Union from django.conf import settings +from django.contrib.auth import get_user_model from django.core.files.storage import default_storage from django.db import IntegrityError, models, transaction from django.utils import timezone @@ -17,9 +16,11 @@ from ara.settings import HASH_SECRET_VALUE, MIN_TIME from .block import Block -from .board import BoardNameType +from .board import NameType from .report import Report +User = get_user_model() + class CommentHiddenReason(Enum): REPORTED_CONTENT = "REPORTED_CONTENT" @@ -40,7 +41,7 @@ class Meta(MetaDataModel.Meta): ) name_type = models.SmallIntegerField( - default=BoardNameType.REGULAR, + default=NameType.REGULAR, verbose_name="익명 혹은 실명", ) @@ -166,8 +167,8 @@ def update_report_count(self): # API 상에서 보이는 사용자 (익명일 경우 익명화된 글쓴이, 그 외는 그냥 글쓴이) @cached_property - def postprocessed_created_by(self) -> Union[settings.AUTH_USER_MODEL, Dict]: - if self.name_type == BoardNameType.REGULAR: + def postprocessed_created_by(self) -> User | dict: + if self.name_type == NameType.REGULAR: return self.created_by parent_article = self.get_parent_article() @@ -182,7 +183,7 @@ def postprocessed_created_by(self) -> Union[settings.AUTH_USER_MODEL, Dict]: user_hash_int = int(user_hash[-4:], 16) user_profile_picture = get_profile_picture(user_hash_int) - if self.name_type == BoardNameType.ANONYMOUS: + if self.name_type == NameType.ANONYMOUS: if parent_article_created_by_id == comment_created_by_id: user_name = gettext("author") else: @@ -200,7 +201,7 @@ def postprocessed_created_by(self) -> Union[settings.AUTH_USER_MODEL, Dict]: }, } - if self.name_type == BoardNameType.REALNAME: + if self.name_type == NameType.REALNAME: if parent_article_created_by_id == comment_created_by_id: user_realname = gettext("author") else: @@ -221,8 +222,8 @@ def postprocessed_created_by(self) -> Union[settings.AUTH_USER_MODEL, Dict]: } @cache_by_user - def hidden_reasons(self, user: settings.AUTH_USER_MODEL) -> typing.List: - reasons: typing.List[CommentHiddenReason] = [] + def hidden_reasons(self, user: User) -> list[CommentHiddenReason]: + reasons: list[CommentHiddenReason] = [] if self.is_deleted(): reasons.append(CommentHiddenReason.DELETED_CONTENT) diff --git a/apps/core/models/comment_log.py b/apps/core/models/comment_log.py index 2378d9ff..9bbd886e 100644 --- a/apps/core/models/comment_log.py +++ b/apps/core/models/comment_log.py @@ -1,6 +1,5 @@ from django.conf import settings from django.db import models -from django_mysql.models import JSONField from ara.db.models import MetaDataManager, MetaDataModel, MetaDataQuerySet @@ -31,7 +30,7 @@ class Meta(MetaDataModel.Meta): queryset_class=CommentUpdateLogQuerySet )() - data = JSONField() + data = models.JSONField(default=dict) updated_by = models.ForeignKey( on_delete=models.CASCADE, diff --git a/apps/core/models/communication_article.py b/apps/core/models/communication_article.py index 28d38208..e976bc92 100644 --- a/apps/core/models/communication_article.py +++ b/apps/core/models/communication_article.py @@ -1,10 +1,10 @@ import sys from enum import IntEnum -from cached_property import cached_property from django.contrib import admin from django.db import models from django.utils import timezone +from django.utils.functional import cached_property from ara.db.models import MetaDataModel from ara.settings import MIN_TIME diff --git a/apps/core/models/notification.py b/apps/core/models/notification.py index a2076155..22b91c92 100644 --- a/apps/core/models/notification.py +++ b/apps/core/models/notification.py @@ -1,5 +1,5 @@ -from cached_property import cached_property from django.db import models +from django.utils.functional import cached_property from ara.db.models import MetaDataModel from ara.firebase import fcm_notify_comment diff --git a/apps/core/models/report.py b/apps/core/models/report.py index f457c3fb..3614dd99 100644 --- a/apps/core/models/report.py +++ b/apps/core/models/report.py @@ -1,6 +1,6 @@ -from cached_property import cached_property from django.conf import settings from django.db import IntegrityError, models +from django.utils.functional import cached_property from ara.db.models import MetaDataModel diff --git a/apps/core/models/topic.py b/apps/core/models/topic.py index 2c4a1ba6..c1650ab9 100644 --- a/apps/core/models/topic.py +++ b/apps/core/models/topic.py @@ -26,13 +26,6 @@ class Meta(MetaDataModel.Meta): max_length=32, verbose_name="말머리 영문 이름", ) - ko_description = models.TextField( - verbose_name="말머리 국문 소개", - ) - en_description = models.TextField( - verbose_name="말머리 영문 소개", - ) - parent_board = models.ForeignKey( on_delete=models.CASCADE, to="core.Board", diff --git a/apps/core/models/vote.py b/apps/core/models/vote.py index 338bb79e..d9705ee0 100644 --- a/apps/core/models/vote.py +++ b/apps/core/models/vote.py @@ -1,6 +1,6 @@ -from cached_property import cached_property from django.conf import settings from django.db import IntegrityError, models +from django.utils.functional import cached_property from ara.db.models import MetaDataModel diff --git a/apps/core/serializers/article.py b/apps/core/serializers/article.py index de87fef7..5850ffdf 100644 --- a/apps/core/serializers/article.py +++ b/apps/core/serializers/article.py @@ -1,17 +1,18 @@ -import typing from enum import Enum from django.utils.translation import gettext from rest_framework import exceptions, serializers +from rest_framework.utils.serializer_helpers import ReturnDict from apps.core.documents import ArticleDocument from apps.core.models import Article, ArticleHiddenReason, Block, Board, Comment, Scrap -from apps.core.models.board import BoardAccessPermissionType, BoardNameType +from apps.core.models.board import BoardAccessPermissionType, NameType from apps.core.serializers.board import BoardSerializer from apps.core.serializers.mixins.hidden import ( HiddenSerializerFieldMixin, HiddenSerializerMixin, ) +from apps.core.serializers.attachment import AttachmentSerializer from apps.core.serializers.topic import TopicSerializer from apps.user.serializers.user import PublicUserSerializer from ara.classes.serializers import MetaDataModelSerializer @@ -37,7 +38,7 @@ class Meta: "migrated_negative_vote_count", ) - def get_my_vote(self, obj) -> typing.Optional[bool]: + def get_my_vote(self, obj) -> bool | None: request = self.context["request"] if not obj.vote_set.filter(voted_by=request.user).exists(): return None @@ -47,7 +48,7 @@ def get_my_vote(self, obj) -> typing.Optional[bool]: return my_vote.is_positive @staticmethod - def get_my_scrap(obj) -> typing.Optional[dict]: + def get_my_scrap(obj) -> dict | None: from apps.core.serializers.scrap import BaseScrapSerializer if not obj.scrap_set.exists(): @@ -57,18 +58,18 @@ def get_my_scrap(obj) -> typing.Optional[dict]: return BaseScrapSerializer(my_scrap).data - def get_title(self, obj) -> typing.Optional[str]: + def get_title(self, obj) -> str | None: if self.visible_verdict(obj): return obj.title return None - def get_content(self, obj) -> typing.Optional[str]: + def get_content(self, obj) -> str | None: if self.visible_verdict(obj): return obj.content return None def get_created_by(self, obj) -> dict: - if obj.name_type in (BoardNameType.ANONYMOUS, BoardNameType.REALNAME): + if obj.name_type in (NameType.ANONYMOUS, NameType.REALNAME): return obj.postprocessed_created_by else: data = PublicUserSerializer(obj.postprocessed_created_by).data @@ -99,7 +100,7 @@ def get_read_status(obj) -> str: return "-" # TODO: article_current_page property must be cached - def get_article_current_page(self, obj) -> typing.Optional[int]: + def get_article_current_page(self, obj) -> int | None: view = self.context.get("view") if view: @@ -316,9 +317,11 @@ def get_side_articles_of_recent_article(self, obj, request): after = None if len(after) == 0 else after[0] return after, before - def get_attachments(self, obj): # -> typing.Optional[list]: + def get_attachments(self, obj: Article) -> ReturnDict | None: if self.visible_verdict(obj): - return obj.attachments.all().values_list("id") + attachments = obj.attachments.all() + serializer = AttachmentSerializer(attachments, many=True) + return serializer.data return None def get_my_comment_profile(self, obj): @@ -329,14 +332,17 @@ def get_my_comment_profile(self, obj): obj.parent_board.is_school_communication and created_by.profile.is_school_admin ): - name_type = BoardNameType.REGULAR + name_type = NameType.REGULAR fake_comment = Comment( created_by=created_by, name_type=name_type, parent_article=obj, ) - if fake_comment.name_type in (BoardNameType.ANONYMOUS, BoardNameType.REALNAME): + if fake_comment.name_type in ( + NameType.ANONYMOUS, + NameType.REALNAME, + ): return fake_comment.postprocessed_created_by else: data = PublicUserSerializer(fake_comment.postprocessed_created_by).data diff --git a/apps/core/serializers/board.py b/apps/core/serializers/board.py index a8631e31..7415e5fd 100644 --- a/apps/core/serializers/board.py +++ b/apps/core/serializers/board.py @@ -7,7 +7,26 @@ class BaseBoardSerializer(MetaDataModelSerializer): class Meta: model = Board - fields = "__all__" + fields = [ + "id", + "slug", + "ko_name", + "en_name", + "is_readonly", + "name_type", + "group", + "banner_image", + "ko_banner_description", + "en_banner_description", + "top_threshold", + ] + depth = 1 + + +class SimpleBoardSerializer(serializers.ModelSerializer): + class Meta: + model = Board + fields = ["id", "slug", "ko_name", "en_name"] class BoardSerializer(BaseBoardSerializer): @@ -25,6 +44,13 @@ class BoardDetailActionSerializer(BaseBoardSerializer): user_readable = serializers.SerializerMethodField() user_writable = serializers.SerializerMethodField() + class Meta(BaseBoardSerializer.Meta): + fields = BaseBoardSerializer.Meta.fields + [ + "topics", + "user_readable", + "user_writable", + ] + def get_user_readable(self, obj): user = self.context["request"].user return obj.group_has_access_permission( diff --git a/apps/core/serializers/board_group.py b/apps/core/serializers/board_group.py new file mode 100644 index 00000000..0634b93b --- /dev/null +++ b/apps/core/serializers/board_group.py @@ -0,0 +1,13 @@ +from rest_framework import serializers + +from apps.core.models.board_group import BoardGroup +from apps.core.serializers.board import SimpleBoardSerializer + + +class BoardGroupSerializer(serializers.ModelSerializer): + boards = SimpleBoardSerializer(many=True, read_only=True) + + class Meta: + model = BoardGroup + fields = ["id", "slug", "ko_name", "en_name", "boards"] + depth = 1 diff --git a/apps/core/serializers/comment.py b/apps/core/serializers/comment.py index 126e0d88..51fc3d70 100644 --- a/apps/core/serializers/comment.py +++ b/apps/core/serializers/comment.py @@ -1,9 +1,7 @@ -import typing - from rest_framework import serializers from apps.core.models import Block, Comment, CommentHiddenReason -from apps.core.models.board import BoardNameType +from apps.core.models.board import NameType from apps.core.serializers.mixins.hidden import ( HiddenSerializerFieldMixin, HiddenSerializerMixin, @@ -22,7 +20,7 @@ class Meta: exclude = ("attachment",) @staticmethod - def get_my_vote(obj) -> typing.Optional[bool]: + def get_my_vote(obj) -> bool | None: if not obj.vote_set.exists(): return None @@ -30,13 +28,13 @@ def get_my_vote(obj) -> typing.Optional[bool]: return my_vote.is_positive - def get_content(self, obj) -> typing.Optional[str]: + def get_content(self, obj) -> str | None: if self.visible_verdict(obj): return obj.content return None def get_created_by(self, obj) -> dict: - if obj.name_type in (BoardNameType.ANONYMOUS, BoardNameType.REALNAME): + if obj.name_type in (NameType.ANONYMOUS, NameType.REALNAME): return obj.postprocessed_created_by else: data = PublicUserSerializer(obj.postprocessed_created_by).data diff --git a/apps/core/serializers/mixins/hidden.py b/apps/core/serializers/mixins/hidden.py index 477ea823..1ccdb5de 100644 --- a/apps/core/serializers/mixins/hidden.py +++ b/apps/core/serializers/mixins/hidden.py @@ -1,5 +1,3 @@ -import typing - from rest_framework import serializers @@ -12,11 +10,11 @@ def get_is_mine(self, obj) -> bool: def get_is_hidden(self, obj) -> bool: return not self.visible_verdict(obj) - def get_why_hidden(self, obj) -> typing.List[str]: + def get_why_hidden(self, obj) -> list[str]: _, _, reasons = self.hidden_info(obj) return [reason.value for reason in reasons] - def get_can_override_hidden(self, obj) -> typing.Optional[bool]: + def get_can_override_hidden(self, obj) -> bool | None: hidden, can_override, _ = self.hidden_info(obj) if not hidden: return @@ -33,7 +31,7 @@ def requested_override_hidden(self): and self.context["override_hidden"] is True ) - def hidden_info(self, obj) -> typing.Tuple[bool, bool, typing.List]: + def hidden_info(self, obj) -> tuple[bool, bool, list]: user = self.context["request"].user reasons = obj.hidden_reasons(user) cannot_override_reasons = [ diff --git a/apps/core/serializers/notification.py b/apps/core/serializers/notification.py index 3f6c550a..4bb1df89 100644 --- a/apps/core/serializers/notification.py +++ b/apps/core/serializers/notification.py @@ -1,5 +1,3 @@ -import typing - from rest_framework import serializers from apps.core.models import Notification @@ -11,7 +9,7 @@ class Meta: model = Notification fields = "__all__" - def get_is_read(self, obj) -> typing.Optional[bool]: + def get_is_read(self, obj) -> bool | None: if not obj.notification_read_log_set.exists(): return None diff --git a/apps/core/serializers/topic.py b/apps/core/serializers/topic.py index 9d6e625a..87ce6e64 100644 --- a/apps/core/serializers/topic.py +++ b/apps/core/serializers/topic.py @@ -5,7 +5,7 @@ class BaseTopicSerializer(MetaDataModelSerializer): class Meta: model = Topic - fields = "__all__" + fields = ["id", "slug", "ko_name", "en_name"] class TopicSerializer(BaseTopicSerializer): diff --git a/apps/core/views/router.py b/apps/core/views/router.py index bcd4c375..7d83076a 100644 --- a/apps/core/views/router.py +++ b/apps/core/views/router.py @@ -10,6 +10,11 @@ viewset=viewsets.BoardViewSet, ) +router.register( + prefix=r"board_groups", + viewset=viewsets.BoardGroupViewSet, +) + # ArticleViewSet router.register( prefix=r"articles", diff --git a/apps/core/views/viewsets/__init__.py b/apps/core/views/viewsets/__init__.py index 429cc1fe..0a079b8f 100644 --- a/apps/core/views/viewsets/__init__.py +++ b/apps/core/views/viewsets/__init__.py @@ -3,6 +3,7 @@ from .best_search import * from .block import * from .board import * +from .board_group import * from .comment import * from .faq import * from .notification import * diff --git a/apps/core/views/viewsets/article.py b/apps/core/views/viewsets/article.py index 37b11fdb..a5a0bd59 100644 --- a/apps/core/views/viewsets/article.py +++ b/apps/core/views/viewsets/article.py @@ -26,7 +26,7 @@ Scrap, Vote, ) -from apps.core.models.board import BoardNameType +from apps.core.models.board import NameType from apps.core.permissions.article import ArticlePermission, ArticleReadPermission from apps.core.serializers.article import ( ArticleCreateActionSerializer, @@ -88,18 +88,18 @@ def filter_queryset(self, queryset): created_by = self.request.query_params.get("created_by") if created_by and int(created_by) != self.request.user.id: # exclude someone's anonymous or realname article in one's profile - exclude_list = [BoardNameType.ANONYMOUS, BoardNameType.REALNAME] + exclude_list = [NameType.ANONYMOUS, NameType.REALNAME] queryset = queryset.exclude(name_type__in=exclude_list) # exclude article written by blocked users in anonymous board queryset = queryset.exclude( created_by__id__in=self.request.user.block_set.values("user"), - name_type=BoardNameType.ANONYMOUS, + name_type=NameType.ANONYMOUS, ) queryset = queryset.prefetch_related( - 'attachments', - 'communication_article', + "attachments", + "communication_article", ) # optimizing queryset for list action @@ -154,16 +154,39 @@ def filter_queryset(self, queryset): return queryset + def create(self, request, *args, **kwargs): + def _get_name_type(name_type_name: str): + for name_type in NameType: + if name_type.name == name_type_name: + return name_type + + return None + + parent_board = Board.objects.get(pk=self.request.data["parent_board"]) + name_type_name = self.request.data["name_type"] + name_type = _get_name_type(name_type_name) + + if name_type is None or name_type not in NameType(parent_board.name_type): + return response.Response( + { + "message": gettext( + f"Cannot set name type as {name_type_name} in board {parent_board}" + ) + }, + status=status.HTTP_400_BAD_REQUEST, + ) + + request.data["name_type"] = name_type.value + return super().create(request, *args, **kwargs) + def perform_create(self, serializer): + parent_board = Board.objects.get(pk=self.request.data["parent_board"]) serializer.save( created_by=self.request.user, - name_type=Board.objects.get(pk=self.request.data["parent_board"]).name_type, ) instance = serializer.instance - if Board.objects.get( - pk=self.request.data["parent_board"] - ).is_school_communication: + if parent_board.is_school_communication: communication_article = CommunicationArticle.objects.create( article=instance, ) @@ -258,7 +281,7 @@ def vote_cancel(self, request, *args, **kwargs): ) if ( - article.name_type == BoardNameType.REALNAME + article.name_type == NameType.REALNAME and article.positive_vote_count >= SCHOOL_RESPONSE_VOTE_THRESHOLD ): return response.Response( @@ -360,7 +383,6 @@ def vote_negative(self, request, *args, **kwargs): @decorators.action(detail=False, methods=["get"]) def recent(self, request, *args, **kwargs): - search_keyword = request.query_params.get("main_search__contains") search_restriction_sql = "" if search_keyword: @@ -406,12 +428,12 @@ def recent(self, request, *args, **kwargs): """, query_params, ).prefetch_related( - 'created_by', - 'created_by__profile', - 'parent_board', - 'parent_topic', - 'attachments', - 'communication_article', + "created_by", + "created_by__profile", + "parent_board", + "parent_topic", + "attachments", + "communication_article", ArticleReadLog.prefetch_my_article_read_log(self.request.user), ) @@ -419,3 +441,17 @@ def recent(self, request, *args, **kwargs): [v for v in queryset], many=True, context={"request": request} ) return self.paginator.get_paginated_response(serializer.data) + + @decorators.action(detail=False, methods=["get"]) + def top(self, request): + # The most recent article at the top + top_articles = Article.objects.exclude(topped_at__isnull=True).order_by( + "-topped_at", "-pk" + ) + page = self.paginate_queryset(top_articles) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.get_serializer(top_articles, many=True) + return response.Response(data=serializer.data, status=status.HTTP_200_OK) diff --git a/apps/core/views/viewsets/board.py b/apps/core/views/viewsets/board.py index c59a8083..a8121f02 100644 --- a/apps/core/views/viewsets/board.py +++ b/apps/core/views/viewsets/board.py @@ -12,5 +12,7 @@ class BoardViewSet(viewsets.ReadOnlyModelViewSet, ActionAPIViewSet): serializer_class = BoardSerializer permission_classes = (permissions.IsAuthenticated,) action_serializer_class = { + "retrieve": BoardDetailActionSerializer, "list": BoardDetailActionSerializer, } + lookup_field = "slug" diff --git a/apps/core/views/viewsets/board_group.py b/apps/core/views/viewsets/board_group.py new file mode 100644 index 00000000..31b31429 --- /dev/null +++ b/apps/core/views/viewsets/board_group.py @@ -0,0 +1,12 @@ +from rest_framework import permissions, viewsets + +from apps.core.models import BoardGroup +from apps.core.serializers.board_group import BoardGroupSerializer + + +class BoardGroupViewSet(viewsets.ReadOnlyModelViewSet): + queryset = BoardGroup.objects.all() + serializer_class = BoardGroupSerializer + permission_classes = [permissions.IsAuthenticated] + lookup_field = "slug" + pagination_class = None diff --git a/apps/core/views/viewsets/comment.py b/apps/core/views/viewsets/comment.py index 39be49a6..75f4eedb 100644 --- a/apps/core/views/viewsets/comment.py +++ b/apps/core/views/viewsets/comment.py @@ -11,7 +11,7 @@ from apps.core.filters.comment import CommentFilter from apps.core.models import Article, Comment, CommentDeleteLog, UserProfile, Vote -from apps.core.models.board import BoardAccessPermissionType, BoardNameType +from apps.core.models.board import BoardAccessPermissionType, NameType from apps.core.permissions.comment import CommentPermission from apps.core.serializers.comment import ( CommentCreateActionSerializer, @@ -74,10 +74,20 @@ def create(self, request, *args, **kwargs): ) def perform_create(self, serializer): - parent_article_id = self.request.data.get("parent_article") - parent_article = parent_article_id and Article.objects.get(id=parent_article_id) - parent_comment_id = self.request.data.get("parent_comment") - parent_comment = parent_comment_id and Comment.objects.get(id=parent_comment_id) + parent_article_id: int | None = self.request.data.get("parent_article") + + if parent_article_id is not None: + parent_article: Article = parent_article_id and Article.objects.get( + id=parent_article_id + ) + else: + parent_comment_id: int = self.request.data.get("parent_comment") + parent_comment: Comment = parent_comment_id and Comment.objects.get( + id=parent_comment_id + ) + parent_article = parent_comment.parent_article + + print(parent_article) created_by = self.request.user is_school_admin = ( @@ -85,12 +95,10 @@ def perform_create(self, serializer): == UserProfile.UserGroup.COMMUNICATION_BOARD_ADMIN ) - if is_school_admin: - name_type = BoardNameType.REGULAR - elif parent_article: - name_type = parent_article.name_type + if is_school_admin and parent_article.name_type != NameType.ANONYMOUS: + name_type = NameType.REGULAR else: - name_type = parent_comment.parent_article.name_type + name_type = parent_article.name_type serializer.save( created_by=created_by, diff --git a/apps/user/migrations/0001_initial.py b/apps/user/migrations/0001_initial.py index b6bdecb2..0ce9dd5f 100644 --- a/apps/user/migrations/0001_initial.py +++ b/apps/user/migrations/0001_initial.py @@ -3,13 +3,11 @@ import datetime import django.db.models.deletion -import django_mysql.models from django.conf import settings from django.db import migrations, models class Migration(migrations.Migration): - initial = True dependencies = [ @@ -64,7 +62,7 @@ class Migration(migrations.Migration): ), ( "sso_user_info", - django_mysql.models.JSONField( + models.JSONField( default=dict, editable=False, verbose_name="Sparcs SSO 정보" ), ), @@ -99,7 +97,7 @@ class Migration(migrations.Migration): ), ( "extra_preferences", - django_mysql.models.JSONField( + models.JSONField( default=dict, editable=False, verbose_name="기타 설정" ), ), diff --git a/apps/user/migrations/0006_set_minimum_datetime_timezone.py b/apps/user/migrations/0006_set_minimum_datetime_timezone.py index 9f46d76f..3f92ecae 100644 --- a/apps/user/migrations/0006_set_minimum_datetime_timezone.py +++ b/apps/user/migrations/0006_set_minimum_datetime_timezone.py @@ -3,11 +3,9 @@ import datetime from django.db import migrations, models -from django.utils.timezone import utc class Migration(migrations.Migration): - dependencies = [ ("user", "0005_auto_add_updated_at"), ] @@ -18,7 +16,7 @@ class Migration(migrations.Migration): name="deleted_at", field=models.DateTimeField( db_index=True, - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="삭제 시간", ), ), @@ -26,7 +24,7 @@ class Migration(migrations.Migration): model_name="userprofile", name="nickname_updated_at", field=models.DateTimeField( - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="최근 닉네임 변경일시", ), ), diff --git a/apps/user/migrations/0010_manualuser.py b/apps/user/migrations/0010_manualuser.py index 818d0772..2805f280 100644 --- a/apps/user/migrations/0010_manualuser.py +++ b/apps/user/migrations/0010_manualuser.py @@ -5,7 +5,6 @@ import django.db.models.deletion from django.conf import settings from django.db import migrations, models -from django.utils.timezone import utc class Migration(migrations.Migration): @@ -44,7 +43,7 @@ class Migration(migrations.Migration): "deleted_at", models.DateTimeField( db_index=True, - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="삭제 시간", ), ), diff --git a/apps/user/migrations/0018_fcmtoken.py b/apps/user/migrations/0018_fcmtoken.py index 039b48b3..7e307970 100644 --- a/apps/user/migrations/0018_fcmtoken.py +++ b/apps/user/migrations/0018_fcmtoken.py @@ -6,7 +6,6 @@ import django.utils.timezone from django.conf import settings from django.db import migrations, models -from django.utils.timezone import utc class Migration(migrations.Migration): @@ -38,7 +37,7 @@ class Migration(migrations.Migration): "deleted_at", models.DateTimeField( db_index=True, - default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=utc), + default=datetime.datetime(1, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), verbose_name="삭제 시간", ), ), diff --git a/apps/user/migrations/0021_remove_userprofile_extra_preferences.py b/apps/user/migrations/0021_remove_userprofile_extra_preferences.py new file mode 100644 index 00000000..a443621b --- /dev/null +++ b/apps/user/migrations/0021_remove_userprofile_extra_preferences.py @@ -0,0 +1,16 @@ +# Generated by Django 4.2.3 on 2023-07-12 02:14 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("user", "0020_after_fcmtoken_is_web"), + ] + + operations = [ + migrations.RemoveField( + model_name="userprofile", + name="extra_preferences", + ), + ] diff --git a/apps/user/models/fcm_token.py b/apps/user/models/fcm_token.py index 711dd590..eff5ca23 100644 --- a/apps/user/models/fcm_token.py +++ b/apps/user/models/fcm_token.py @@ -1,4 +1,3 @@ -from cached_property import cached_property from django.conf import settings from django.db import models from django.utils import timezone diff --git a/apps/user/models/user_profile.py b/apps/user/models/user_profile.py index 70bdfdf8..37b25d46 100644 --- a/apps/user/models/user_profile.py +++ b/apps/user/models/user_profile.py @@ -1,12 +1,11 @@ import json -from cached_property import cached_property from dateutil.relativedelta import relativedelta from django.conf import settings from django.db import models from django.utils import timezone -from django.utils.translation import ugettext_lazy -from django_mysql.models import JSONField +from django.utils.functional import cached_property +from django.utils.translation import gettext_lazy from ara.db.models import MetaDataModel from ara.settings import MIN_TIME @@ -24,21 +23,21 @@ class Meta(MetaDataModel.Meta): class UserGroup(models.IntegerChoices): # 뉴아라 계정을 만들지 않은 사람들 - UNAUTHORIZED = 0, ugettext_lazy("Unauthorized user") + UNAUTHORIZED = 0, gettext_lazy("Unauthorized user") # 카이스트 메일을 가진 사람 (학생, 교직원) - KAIST_MEMBER = 1, ugettext_lazy("KAIST member") + KAIST_MEMBER = 1, gettext_lazy("KAIST member") # 교내 입주 업체 직원 - STORE_EMPLOYEE = 2, ugettext_lazy("Store employee") + STORE_EMPLOYEE = 2, gettext_lazy("Store employee") # 카이스트 메일이 없는 개인 (특수한 관련자 등) - OTHER_MEMBER = 3, ugettext_lazy("Other member") + OTHER_MEMBER = 3, gettext_lazy("Other member") # 교내 학생 단체들 - KAIST_ORG = 4, ugettext_lazy("KAIST organization") + KAIST_ORG = 4, gettext_lazy("KAIST organization") # 외부인 (홍보 계정 등) - EXTERNAL_ORG = 5, ugettext_lazy("External organization") + EXTERNAL_ORG = 5, gettext_lazy("External organization") # 소통게시판 관리인 - COMMUNICATION_BOARD_ADMIN = 6, ugettext_lazy("Communication board admin") + COMMUNICATION_BOARD_ADMIN = 6, gettext_lazy("Communication board admin") # 뉴스게시판 관리인 - NEWS_BOARD_ADMIN = 7, ugettext_lazy("News board admin") + NEWS_BOARD_ADMIN = 7, gettext_lazy("News board admin") OFFICIAL_GROUPS = [UserGroup.STORE_EMPLOYEE, UserGroup.KAIST_ORG] @@ -56,7 +55,8 @@ class UserGroup(models.IntegerChoices): max_length=30, verbose_name="Sparcs SSO sid", ) - sso_user_info = JSONField( + sso_user_info = models.JSONField( + default=dict, editable=False, verbose_name="Sparcs SSO 정보", ) @@ -84,10 +84,6 @@ class UserGroup(models.IntegerChoices): default=False, verbose_name="정치/사회성 보기", ) - extra_preferences = JSONField( - editable=False, - verbose_name="기타 설정", - ) group = models.IntegerField( choices=UserGroup.choices, default=UserGroup.UNAUTHORIZED ) @@ -132,14 +128,13 @@ def email(self) -> str: @cached_property def realname(self) -> str: - sso_info = self.sso_user_info - user_realname = ( - json.loads(sso_info["kaist_info"])["ku_kname"] - if sso_info["kaist_info"] - else sso_info["last_name"] + sso_info["first_name"] - ) + if not self.sso_user_info: + return self.nickname # Portal crawled users - return user_realname + kaist_info = self.sso_user_info["kaist_info"] + if kaist_info: + return json.loads(kaist_info)["ku_kname"] + return self.sso_user_info["last_name"] + self.sso_user_info["first_name"] @cached_property def is_official(self) -> bool: diff --git a/apps/user/serializers/user.py b/apps/user/serializers/user.py index e2d1fe70..bd180721 100644 --- a/apps/user/serializers/user.py +++ b/apps/user/serializers/user.py @@ -8,29 +8,6 @@ class Meta: fields = "__all__" -class UserSerializer(BaseUserSerializer): - from apps.user.serializers.user_profile import UserProfileSerializer - - profile = UserProfileSerializer( - read_only=True, - ) - - -class UserDetailActionSerializer(BaseUserSerializer): - class Meta(BaseUserSerializer.Meta): - fields = ( - "id", - "username", - "profile", - ) - - from apps.user.serializers.user_profile import UserProfileSerializer - - profile = UserProfileSerializer( - read_only=True, - ) - - class PublicUserSerializer(BaseUserSerializer): class Meta(BaseUserSerializer.Meta): fields = ( diff --git a/apps/user/serializers/user_profile.py b/apps/user/serializers/user_profile.py index 40b8fc3e..40dff639 100644 --- a/apps/user/serializers/user_profile.py +++ b/apps/user/serializers/user_profile.py @@ -1,5 +1,3 @@ -import typing - from dateutil.relativedelta import relativedelta from django.utils import timezone from django.utils.translation import gettext @@ -18,7 +16,7 @@ class Meta: fields = "__all__" @staticmethod - def get_email(obj) -> typing.Optional[str]: + def get_email(obj) -> str | None: if obj.email.endswith("@sso.sparcs.org"): return None return obj.email @@ -29,9 +27,7 @@ def get_is_official(obj) -> bool: class UserProfileSerializer(BaseUserProfileSerializer): - extra_preferences = serializers.JSONField( - read_only=True, - ) + ... class UserProfileUpdateActionSerializer(BaseUserProfileSerializer): @@ -62,8 +58,6 @@ def update(self, instance, validated_data): validated_data["nickname_updated_at"] = timezone.now() return super(BaseUserProfileSerializer, self).update(instance, validated_data) - extra_preferences = serializers.JSONField() - class PublicUserProfileSerializer(BaseUserProfileSerializer): class Meta(BaseUserProfileSerializer.Meta): diff --git a/apps/user/views/viewsets/user.py b/apps/user/views/viewsets/user.py index f36a3afc..0bbeef0d 100644 --- a/apps/user/views/viewsets/user.py +++ b/apps/user/views/viewsets/user.py @@ -5,12 +5,12 @@ from urllib.parse import urlparse import requests -from cached_property import cached_property from django.conf import settings from django.contrib.auth import get_user_model, login, logout from django.db import transaction from django.shortcuts import redirect, reverse from django.utils import timezone +from django.utils.functional import cached_property from rest_framework import decorators, permissions, response, status from apps.user.models import UserProfile diff --git a/ara/sanitizer.py b/ara/sanitizer.py index 3a55f099..49a46282 100644 --- a/ara/sanitizer.py +++ b/ara/sanitizer.py @@ -44,9 +44,9 @@ def _allowed_attributes(tag, name, value): allowed_tags = ( bleach.ALLOWED_TAGS - + ["p", "pre", "span", "h1", "h2", "h3", "br", "hr", "s", "u", "ol"] - + ["img", "iframe", "video", "audio", "source"] - + [ + | {"p", "pre", "span", "h1", "h2", "h3", "br", "hr", "s", "u", "ol"} + | {"img", "iframe", "video", "audio", "source"} + | { "sub", "sup", "table", @@ -59,7 +59,7 @@ def _allowed_attributes(tag, name, value): "tt", "u", "ul", - ] + } ) return bleach.linkify( diff --git a/ara/settings/__init__.py b/ara/settings/__init__.py index 8948acb2..716c7e57 100644 --- a/ara/settings/__init__.py +++ b/ara/settings/__init__.py @@ -9,6 +9,7 @@ from .redis import * from .scheduler import * from .sentry import * +from .spectacular import * from .sso import * if env("DJANGO_ENV") == "development": diff --git a/ara/settings/aws.py b/ara/settings/aws.py index 17f0f7dd..c1d5a17c 100644 --- a/ara/settings/aws.py +++ b/ara/settings/aws.py @@ -20,9 +20,10 @@ # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/1.11/howto/static-files/ -DEFAULT_FILE_STORAGE = "django_s3_storage.storage.S3Storage" - -STATICFILES_STORAGE = "django_s3_storage.storage.StaticS3Storage" +STORAGES = { + "default": {"BACKEND": "django_s3_storage.storage.S3Storage"}, + "staticfiles": {"BACKEND": "django_s3_storage.storage.StaticS3Storage"}, +} AWS_SES_REGION_NAME = "ap-northeast-2" diff --git a/ara/settings/dev/__init__.py b/ara/settings/dev/__init__.py index d0a9d8a7..95599b31 100644 --- a/ara/settings/dev/__init__.py +++ b/ara/settings/dev/__init__.py @@ -1,4 +1,4 @@ -from django.utils import timezone +from datetime import datetime, timezone from ara.settings import INSTALLED_APPS, LOGGING, MIDDLEWARE @@ -7,6 +7,10 @@ DEBUG = True ALLOWED_HOSTS = ["*"] +CSRF_TRUSTED_ORIGINS = [ + "https://*.sparcs.org", + "http://localhost", +] CORS_ORIGIN_ALLOW_ALL = True @@ -35,7 +39,7 @@ REPORT_THRESHOLD = 4 SCHOOL_RESPONSE_VOTE_THRESHOLD = 3 ANSWER_PERIOD = 14 -MIN_TIME = timezone.datetime.min.replace(tzinfo=timezone.utc) +MIN_TIME = datetime.min.replace(tzinfo=timezone.utc) try: from .local_settings import * diff --git a/ara/settings/django.py b/ara/settings/django.py index 05e43bf5..d6772dc3 100644 --- a/ara/settings/django.py +++ b/ara/settings/django.py @@ -1,7 +1,7 @@ import os from os import environ as os_environ -from django.utils.translation import ugettext_lazy +from django.utils.translation import gettext_lazy from .env import env, root @@ -20,12 +20,11 @@ "django.contrib.staticfiles", "rest_framework", "rest_framework.authtoken", - "rest_framework_filters", "django_extensions", "django_s3_storage", "django_celery_beat", "django_celery_results", - "drf_yasg", + "drf_spectacular", "cacheops", "django_elasticsearch_dsl", "django_filters", @@ -89,15 +88,13 @@ # https://docs.djangoproject.com/en/2.2/topics/i18n/ LANGUAGE_CODE = "ko-kr" -LANGUAGES = [("ko", ugettext_lazy("Korean")), ("en", ugettext_lazy("English"))] +LANGUAGES = [("ko", gettext_lazy("Korean")), ("en", gettext_lazy("English"))] LOCALE_PATHS = [os.path.join(BASE_DIR, "ara/locale")] TIME_ZONE = "Asia/Seoul" USE_I18N = True -USE_L10N = True - USE_TZ = True SECRET_KEY = env("SECRET_KEY") @@ -126,6 +123,9 @@ INTERNAL_IPS = ("127.0.0.1",) +if env("DJANGO_ENV") == "development": + INTERNAL_IPS = type(str("c"), (), {"__contains__": lambda *a: True})() + SESSION_ENGINE = "django.contrib.sessions.backends.db" SESSION_COOKIE_HTTPONLY = True diff --git a/ara/settings/djangorestframework.py b/ara/settings/djangorestframework.py index c0add792..2034855d 100644 --- a/ara/settings/djangorestframework.py +++ b/ara/settings/djangorestframework.py @@ -2,13 +2,14 @@ REST_FRAMEWORK = { "DEFAULT_PAGINATION_CLASS": "ara.classes.pagination.PageNumberPagination", - "DEFAULT_FILTER_BACKENDS": ( - "rest_framework_filters.backends.RestFrameworkFilterBackend", + "DEFAULT_FILTER_BACKENDS": [ + "django_filters.rest_framework.DjangoFilterBackend", "rest_framework.filters.OrderingFilter", - ), + ], "DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.AllowAny",), "PAGE_SIZE": 15, "SERIALIZER_EXTENSIONS": { "AUTO_OPTIMIZE": True, }, + "DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema", } diff --git a/ara/settings/prod/__init__.py b/ara/settings/prod/__init__.py index 4f1122e5..8ba9fc30 100644 --- a/ara/settings/prod/__init__.py +++ b/ara/settings/prod/__init__.py @@ -1,4 +1,4 @@ -from django.utils import timezone +from datetime import datetime, timezone from ara.settings import MIDDLEWARE, REST_FRAMEWORK @@ -9,6 +9,11 @@ "ara.sparcs.org", ] +CSRF_TRUSTED_ORIGINS = [ + "https://newara.sparcs.org", + "https://ara.sparcs.org", +] + SSO_IS_BETA = False SESSION_COOKIE_SAMESITE = "Lax" @@ -28,4 +33,4 @@ REPORT_THRESHOLD = 4 SCHOOL_RESPONSE_VOTE_THRESHOLD = 20 ANSWER_PERIOD = 14 -MIN_TIME = timezone.datetime.min.replace(tzinfo=timezone.utc) +MIN_TIME = datetime.min.replace(tzinfo=timezone.utc) diff --git a/ara/settings/spectacular.py b/ara/settings/spectacular.py new file mode 100644 index 00000000..bf6460fb --- /dev/null +++ b/ara/settings/spectacular.py @@ -0,0 +1,9 @@ +SPECTACULAR_SETTINGS = { + "TITLE": "Ara API", + "DESCRIPTION": "Restful API for Ara, KAIST's official community service", + "VERSION": "2.1.0", + "LICENSE": { + "name": "MIT", + "url": "https://opensource.org/license/mit/", + }, +} diff --git a/ara/urls.py b/ara/urls.py index cc8962f2..ea27cf64 100644 --- a/ara/urls.py +++ b/ara/urls.py @@ -15,42 +15,28 @@ """ from django.conf import settings from django.contrib import admin -from django.urls import include, path, re_path -from drf_yasg import openapi -from drf_yasg.views import get_schema_view -from rest_framework import permissions - -# drf-yasg - -schema_view = get_schema_view( - openapi.Info( - title="Snippets API", - default_version="v1", - description="Test description", - terms_of_service="https://google.com/policies/terms", - contact=openapi.Contact(email="contact@snippets.local"), - license=openapi.License(name="BSD Licence"), - ), - public=True, - permission_classes=(permissions.AllowAny,), +from django.urls import include, path +from drf_spectacular.views import ( + SpectacularAPIView, + SpectacularRedocView, + SpectacularSwaggerView, ) urlpatterns = [ path("api/admin/", admin.site.urls), path("", include(("apps.core.urls", "core"))), path("", include(("apps.user.urls", "user"))), -] - -# drf-yasg - -urlpatterns += [ - re_path( - r"swagger(?P\.json|\.yaml)$", - schema_view.without_ui(), - name="schema-json", + path("api/schema/", SpectacularAPIView.as_view(), name="schema"), + path( + "api/schema/swagger/", + SpectacularSwaggerView.as_view(url_name="schema"), + name="swagger", + ), + path( + "api/schema/redoc/", + SpectacularRedocView.as_view(url_name="schema"), + name="redoc", ), - path("swagger/", schema_view.with_ui("swagger"), name="schema-swagger-ui"), - path("redoc/", schema_view.with_ui("redoc"), name="schema-redoc"), ] # installed apps (test environment) diff --git a/buildspec.yml b/buildspec.yml deleted file mode 100644 index cb972a2b..00000000 --- a/buildspec.yml +++ /dev/null @@ -1,26 +0,0 @@ -version: 0.2 - -env: - variables: - ECR: 666583083672.dkr.ecr.ap-northeast-2.amazonaws.com - PROJECT_NAME: newara - -phases: - install: - commands: - - docker login -u $DOCKERHUB_USERNAME -p $DOCKERHUB_PASSWORD - - chmod +x ./.docker/codebuild.sh - - . ./.docker/codebuild.sh - - aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin $ECR - - docker pull $ECR/$PROJECT_NAME:$CACHE_DOCKER_TAG || true - - build: - commands: - - echo $CODEBUILD_SOURCE_VERSION > version - - docker build --build-arg AWS_ACCESS_KEY_ID=$(echo $AWS_ACCESS_KEY_ID) --build-arg AWS_SECRET_ACCESS_KEY=$(echo $AWS_SECRET_ACCESS_KEY) --cache-from $ECR/$PROJECT_NAME:$CACHE_DOCKER_TAG -t $PROJECT_NAME . - - post_build: - commands: - - docker-compose -f docker-compose.test.yml run api test - - docker-compose -f docker-compose.test.yml down - - if [ $PUSH = true ]; then docker tag $PROJECT_NAME $ECR/$PROJECT_NAME:$DOCKER_TAG && docker push $ECR/$PROJECT_NAME:$DOCKER_TAG ; fi diff --git a/docker-compose.example.yml b/docker-compose.example.yml index 534900b7..15aec7c1 100644 --- a/docker-compose.example.yml +++ b/docker-compose.example.yml @@ -75,7 +75,7 @@ services: db: container_name: db - image: mysql:5.7 + image: mysql:8.0 expose: - 3306 ports: diff --git a/docker-compose.test.yml b/docker-compose.test.yml index c2dc97df..7878c848 100644 --- a/docker-compose.test.yml +++ b/docker-compose.test.yml @@ -10,7 +10,7 @@ services: - elasticsearch environment: - DJANGO_SETTINGS_MODULE=ara.settings.test - - DJANGO_ENV=development + - DJANGO_ENV=${DJANGO_ENV} - SECRET_KEY=${SECRET_KEY} - AWS_BUCKET_NAME=sparcs-newara-dev - AWS_BUCKET_NAME_STATIC=sparcs-kaist-ara-beta-static @@ -39,7 +39,7 @@ services: - elasticsearch environment: - DJANGO_SETTINGS_MODULE=main.settings.test - - DJANGO_ENV=development + - DJANGO_ENV=${DJANGO_ENV} - SECRET_KEY=${SECRET_KEY} - AWS_BUCKET_NAME=sparcs-newara-dev - AWS_BUCKET_NAME_STATIC=sparcs-kaist-ara-beta-static @@ -61,7 +61,7 @@ services: db: container_name: db - image: mysql:5.7 + image: mysql:8.0 expose: - 3306 environment: diff --git a/manage.py b/manage.py index 3e48d45b..5af95a5a 100755 --- a/manage.py +++ b/manage.py @@ -6,7 +6,7 @@ def main() -> None: - dotenv.read_dotenv() + dotenv.load_dotenv() os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ara.settings") try: from django.core.management import execute_from_command_line diff --git a/poetry.lock b/poetry.lock deleted file mode 100644 index d41befbc..00000000 --- a/poetry.lock +++ /dev/null @@ -1,3281 +0,0 @@ -[[package]] -name = "amqp" -version = "2.6.1" -description = "Low-level AMQP client for Python (fork of amqplib)." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[package.dependencies] -vine = ">=1.1.3,<5.0.0a1" - -[[package]] -name = "ansicon" -version = "1.89.0" -description = "Python wrapper for loading Jason Hood's ANSICON" -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "asgiref" -version = "3.6.0" -description = "ASGI specs, helper code, and adapters" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -typing-extensions = {version = "*", markers = "python_version < \"3.8\""} - -[package.extras] -tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] - -[[package]] -name = "astroid" -version = "2.11.7" -description = "An abstract syntax tree for Python with inference support." -category = "dev" -optional = false -python-versions = ">=3.6.2" - -[package.dependencies] -lazy-object-proxy = ">=1.4.0" -setuptools = ">=20.0" -typed-ast = {version = ">=1.4.0,<2.0", markers = "implementation_name == \"cpython\" and python_version < \"3.8\""} -typing-extensions = {version = ">=3.10", markers = "python_version < \"3.10\""} -wrapt = ">=1.11,<2" - -[[package]] -name = "atomicwrites" -version = "1.4.1" -description = "Atomic file writes." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[[package]] -name = "attrs" -version = "22.2.0" -description = "Classes Without Boilerplate" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.extras] -cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] -dev = ["attrs[docs,tests]"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"] -tests = ["attrs[tests-no-zope]", "zope.interface"] -tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"] - -[[package]] -name = "autopep8" -version = "1.7.0" -description = "A tool that automatically formats Python code to conform to the PEP 8 style guide" -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -pycodestyle = ">=2.9.1" -toml = "*" - -[[package]] -name = "backports-cached-property" -version = "1.0.2" -description = "cached_property() - computed once per instance, cached as attribute" -category = "main" -optional = false -python-versions = ">=3.6.0" - -[[package]] -name = "beautifulsoup4" -version = "4.11.1" -description = "Screen-scraping library" -category = "main" -optional = false -python-versions = ">=3.6.0" - -[package.dependencies] -soupsieve = ">1.2" - -[package.extras] -html5lib = ["html5lib"] -lxml = ["lxml"] - -[[package]] -name = "billiard" -version = "3.6.4.0" -description = "Python multiprocessing fork with improvements and bugfixes" -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "black" -version = "22.12.0" -description = "The uncompromising code formatter." -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -pathspec = ">=0.9.0" -platformdirs = ">=2" -tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""} -typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\" and implementation_name == \"cpython\""} -typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - -[[package]] -name = "bleach" -version = "3.3.1" -description = "An easy safelist-based HTML-sanitizing tool." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[package.dependencies] -packaging = "*" -six = ">=1.9.0" -webencodings = "*" - -[[package]] -name = "blessed" -version = "1.19.1" -description = "Easy, practical library for making terminal apps, by providing an elegant, well-documented interface to Colors, Keyboard input, and screen Positioning capabilities." -category = "main" -optional = false -python-versions = ">=2.7" - -[package.dependencies] -jinxed = {version = ">=1.1.0", markers = "platform_system == \"Windows\""} -six = ">=1.9.0" -wcwidth = ">=0.1.4" - -[[package]] -name = "blessings" -version = "1.7" -description = "A thin, practical wrapper around terminal coloring, styling, and positioning" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[package.dependencies] -six = "*" - -[[package]] -name = "boto3" -version = "1.26.43" -description = "The AWS SDK for Python" -category = "main" -optional = false -python-versions = ">= 3.7" - -[package.dependencies] -botocore = ">=1.29.43,<1.30.0" -jmespath = ">=0.7.1,<2.0.0" -s3transfer = ">=0.6.0,<0.7.0" - -[package.extras] -crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] - -[[package]] -name = "botocore" -version = "1.29.43" -description = "Low-level, data-driven core of boto 3." -category = "main" -optional = false -python-versions = ">= 3.7" - -[package.dependencies] -jmespath = ">=0.7.1,<2.0.0" -python-dateutil = ">=2.1,<3.0.0" -urllib3 = ">=1.25.4,<1.27" - -[package.extras] -crt = ["awscrt (==0.15.3)"] - -[[package]] -name = "bpython" -version = "0.19" -description = "Fancy Interface to the Python Interpreter" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -curtsies = ">=0.1.18" -greenlet = "*" -pygments = "*" -requests = "*" -six = ">=1.5" - -[package.extras] -jedi = ["jedi"] -urwid = ["urwid"] -watch = ["watchdog"] - -[[package]] -name = "cachecontrol" -version = "0.12.11" -description = "httplib2 caching for requests" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -msgpack = ">=0.5.2" -requests = "*" - -[package.extras] -filecache = ["lockfile (>=0.9)"] -redis = ["redis (>=2.10.5)"] - -[[package]] -name = "cached-property" -version = "1.5.2" -description = "A decorator for caching properties in classes." -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "cachetools" -version = "5.2.0" -description = "Extensible memoizing collections and decorators" -category = "main" -optional = false -python-versions = "~=3.7" - -[[package]] -name = "celery" -version = "4.4.7" -description = "Distributed Task Queue." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[package.dependencies] -billiard = ">=3.6.3.0,<4.0" -kombu = ">=4.6.10,<4.7" -pytz = ">0.0-dev" -redis = {version = ">=3.2.0", optional = true, markers = "extra == \"redis\""} -vine = "1.3.0" - -[package.extras] -arangodb = ["pyArango (>=1.3.2)"] -auth = ["cryptography"] -azureblockblob = ["azure-common (==1.1.5)", "azure-storage (==0.36.0)", "azure-storage-common (==1.1.0)"] -brotli = ["brotli (>=1.0.0)", "brotlipy (>=0.7.0)"] -cassandra = ["cassandra-driver (<3.21.0)"] -consul = ["python-consul"] -cosmosdbsql = ["pydocumentdb (==2.3.2)"] -couchbase = ["couchbase (<3.0.0)", "couchbase-cffi (<3.0.0)"] -couchdb = ["pycouchdb"] -django = ["Django (>=1.11)"] -dynamodb = ["boto3 (>=1.9.178)"] -elasticsearch = ["elasticsearch"] -eventlet = ["eventlet (>=0.24.1)"] -gevent = ["gevent"] -librabbitmq = ["librabbitmq (>=1.5.0)"] -lzma = ["backports.lzma"] -memcache = ["pylibmc"] -mongodb = ["pymongo[srv] (>=3.3.0)"] -msgpack = ["msgpack"] -pymemcache = ["python-memcached"] -pyro = ["pyro4"] -redis = ["redis (>=3.2.0)"] -riak = ["riak (>=2.0)"] -s3 = ["boto3 (>=1.9.125)"] -slmq = ["softlayer-messaging (>=1.0.3)"] -solar = ["ephem"] -sqlalchemy = ["sqlalchemy"] -sqs = ["boto3 (>=1.9.125)", "pycurl (==7.43.0.5)"] -tblib = ["tblib (>=1.3.0)", "tblib (>=1.5.0)"] -yaml = ["PyYAML (>=3.10)"] -zookeeper = ["kazoo (>=1.3.1)"] -zstd = ["zstandard"] - -[[package]] -name = "certifi" -version = "2022.12.7" -description = "Python package for providing Mozilla's CA Bundle." -category = "main" -optional = false -python-versions = ">=3.6" - -[[package]] -name = "cffi" -version = "1.15.1" -description = "Foreign Function Interface for Python calling C code." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -pycparser = "*" - -[[package]] -name = "cfgv" -version = "3.3.1" -description = "Validate configuration and produce human readable error messages." -category = "dev" -optional = false -python-versions = ">=3.6.1" - -[[package]] -name = "charset-normalizer" -version = "2.1.1" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" -optional = false -python-versions = ">=3.6.0" - -[package.extras] -unicode-backport = ["unicodedata2"] - -[[package]] -name = "click" -version = "8.1.3" -description = "Composable command line interface toolkit" -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -category = "main" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" - -[[package]] -name = "coreapi" -version = "2.3.3" -description = "Python client library for Core API." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -coreschema = "*" -itypes = "*" -requests = "*" -uritemplate = "*" - -[[package]] -name = "coreschema" -version = "0.0.4" -description = "Core Schema." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -jinja2 = "*" - -[[package]] -name = "coverage" -version = "7.0.3" -description = "Code coverage measurement for Python" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.extras] -toml = ["tomli"] - -[[package]] -name = "cryptography" -version = "39.0.0" -description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -cffi = ">=1.12" - -[package.extras] -docs = ["sphinx (>=1.6.5,!=1.8.0,!=3.1.0,!=3.1.1,!=5.2.0,!=5.2.0.post0)", "sphinx-rtd-theme"] -docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"] -pep8test = ["black", "ruff"] -sdist = ["setuptools-rust (>=0.11.4)"] -ssh = ["bcrypt (>=3.1.5)"] -test = ["hypothesis (>=1.11.4,!=3.79.2)", "iso8601", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-subtests", "pytest-xdist", "pytz"] - -[[package]] -name = "curtsies" -version = "0.4.1" -description = "Curses-like terminal wrapper, with colored strings!" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -"backports.cached-property" = {version = "*", markers = "python_version < \"3.8\""} -blessed = ">=1.5" -cwcwidth = "*" - -[[package]] -name = "cwcwidth" -version = "0.1.8" -description = "Python bindings for wc(s)width" -category = "main" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "dill" -version = "0.3.6" -description = "serialize all of python" -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.extras] -graph = ["objgraph (>=1.7.2)"] - -[[package]] -name = "distlib" -version = "0.3.6" -description = "Distribution utilities" -category = "dev" -optional = false -python-versions = "*" - -[[package]] -name = "django" -version = "3.2.16" -description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -asgiref = ">=3.3.2,<4" -pytz = "*" -sqlparse = ">=0.2.2" - -[package.extras] -argon2 = ["argon2-cffi (>=19.1.0)"] -bcrypt = ["bcrypt"] - -[[package]] -name = "django-cacheops" -version = "5.1" -description = "A slick ORM cache with automatic granular event-driven invalidation for Django." -category = "main" -optional = false -python-versions = ">=3.5" - -[package.dependencies] -django = ">=2.1" -funcy = ">=1.8,<2.0" -redis = ">=3.0.0" -six = ">=1.4.0" - -[[package]] -name = "django-celery-beat" -version = "2.2.0" -description = "Database-backed Periodic Tasks." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -celery = ">=4.4,<6.0" -Django = ">=2.2,<4.0" -django-timezone-field = ">=4.1.0,<5.0" -python-crontab = ">=2.3.4" - -[[package]] -name = "django-celery-results" -version = "1.2.1" -description = "Celery result backends for Django." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -celery = ">=4.4,<5.0" - -[[package]] -name = "django-cors-headers" -version = "3.13.0" -description = "django-cors-headers is a Django application for handling the server headers required for Cross-Origin Resource Sharing (CORS)." -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -Django = ">=3.2" - -[[package]] -name = "django-crontab" -version = "0.7.1" -description = "dead simple crontab powered job scheduling for django" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -Django = ">=1.8" - -[[package]] -name = "django-debug-toolbar" -version = "2.2.1" -description = "A configurable set of panels that display various debug information about the current request/response." -category = "dev" -optional = false -python-versions = ">=3.5" - -[package.dependencies] -Django = ">=1.11" -sqlparse = ">=0.2.0" - -[[package]] -name = "django-debug-toolbar-force" -version = "0.1.8" -description = "Force debugging of partial- or non-HTML views in django-debug-toolbar." -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -django-nine = ">=0.2.3" -six = ">=1.4.1" - -[[package]] -name = "django-dotenv" -version = "1.4.2" -description = "foreman reads from .env. manage.py doesn't. Let's fix that." -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "django-elasticsearch-dsl" -version = "7.2.2" -description = "Wrapper around elasticsearch-dsl-py for django models" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -six = "*" - -[[package]] -name = "django-environ" -version = "0.4.5" -description = "Django-environ allows you to utilize 12factor inspired environment variables to configure your Django application." -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "django-extensions" -version = "2.2.9" -description = "Extensions for Django" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -six = ">=1.2" - -[[package]] -name = "django-filter" -version = "22.1" -description = "Django-filter is a reusable Django application for allowing users to filter querysets dynamically." -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -Django = ">=3.2" - -[[package]] -name = "django-mysql" -version = "3.12.0" -description = "Django-MySQL extends Django's built-in MySQL and MariaDB support their specific features not available on other databases." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -Django = ">=2.2" - -[[package]] -name = "django-nine" -version = "0.2.7" -description = "Version checking library." -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -Django = "*" -packaging = "*" - -[[package]] -name = "django-redis" -version = "4.12.1" -description = "Full featured redis cache backend for Django." -category = "main" -optional = false -python-versions = ">=3.5" - -[package.dependencies] -Django = ">=2.2" -redis = ">=3.0.0" - -[[package]] -name = "django-s3-storage" -version = "0.13.3" -description = "Django Amazon S3 file storage." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -boto3 = ">=1.4.4,<2" -django = ">=1.11" - -[[package]] -name = "django-ses" -version = "1.0.3" -description = "A Django email backend for Amazon's Simple Email Service" -category = "main" -optional = false -python-versions = ">=2.7" - -[package.dependencies] -boto3 = ">=1.0.0" -django = ">1.10" -future = ">=0.16.0" -pytz = ">=2016.10" - -[package.extras] -bounce = ["M2Crypto", "requests (<3)"] - -[[package]] -name = "django-silk" -version = "4.4.1" -description = "Silky smooth profiling for the Django Framework" -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -autopep8 = "*" -Django = ">=2.2" -gprof2dot = ">=2017.09.19" -Jinja2 = "*" -python-dateutil = "*" -pytz = "*" -requests = "*" -sqlparse = "*" - -[[package]] -name = "django-timezone-field" -version = "4.2.3" -description = "A Django app providing database and form fields for pytz timezone objects." -category = "main" -optional = false -python-versions = ">=3.5" - -[package.dependencies] -django = ">=2.2" -pytz = "*" - -[package.extras] -rest-framework = ["djangorestframework (>=3.0.0)"] - -[[package]] -name = "djangorestframework" -version = "3.14.0" -description = "Web APIs for Django, made easy." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -django = ">=3.0" -pytz = "*" - -[[package]] -name = "djangorestframework-filters" -version = "1.0.0.dev2" -description = "Better filtering for Django REST Framework" -category = "main" -optional = false -python-versions = ">=3.5" - -[package.dependencies] -django-filter = ">=2.0" -djangorestframework = "*" - -[[package]] -name = "drf-yasg" -version = "1.21.4" -description = "Automated generation of real Swagger/OpenAPI 2.0 schemas from Django Rest Framework code." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -coreapi = ">=2.3.3" -coreschema = ">=0.0.4" -django = ">=2.2.16" -djangorestframework = ">=3.10.3" -inflection = ">=0.3.1" -packaging = ">=21.0" -pytz = ">=2021.1" -"ruamel.yaml" = ">=0.16.13" -uritemplate = ">=3.0.0" - -[package.extras] -validation = ["swagger-spec-validator (>=2.1.0)"] - -[[package]] -name = "elasticsearch" -version = "7.17.8" -description = "Python client for Elasticsearch" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4" - -[package.dependencies] -certifi = "*" -urllib3 = ">=1.21.1,<2" - -[package.extras] -async = ["aiohttp (>=3,<4)"] -develop = ["black", "coverage", "jinja2", "mock", "pytest", "pytest-cov", "pyyaml", "requests (>=2.0.0,<3.0.0)", "sphinx (<1.7)", "sphinx-rtd-theme"] -docs = ["sphinx (<1.7)", "sphinx-rtd-theme"] -requests = ["requests (>=2.4.0,<3.0.0)"] - -[[package]] -name = "elasticsearch-dsl" -version = "7.4.0" -description = "Python client for Elasticsearch" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[package.dependencies] -elasticsearch = ">=7.0.0,<8.0.0" -python-dateutil = "*" -six = "*" - -[package.extras] -develop = ["coverage (<5.0.0)", "mock", "pytest (>=3.0.0)", "pytest-cov", "pytest-mock (<3.0.0)", "pytz", "sphinx", "sphinx-rtd-theme"] - -[[package]] -name = "fake-useragent" -version = "0.1.14" -description = "Up-to-date simple useragent faker with real world database" -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "filelock" -version = "3.9.0" -description = "A platform independent file lock." -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.extras] -docs = ["furo (>=2022.12.7)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.5)"] -testing = ["covdefaults (>=2.2.2)", "coverage (>=7.0.1)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-timeout (>=2.1)"] - -[[package]] -name = "firebase-admin" -version = "6.0.1" -description = "Firebase Admin Python SDK" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -cachecontrol = ">=0.12.6" -google-api-core = {version = ">=1.22.1,<3.0.0dev", extras = ["grpc"], markers = "platform_python_implementation != \"PyPy\""} -google-api-python-client = ">=1.7.8" -google-cloud-firestore = {version = ">=2.1.0", markers = "platform_python_implementation != \"PyPy\""} -google-cloud-storage = ">=1.37.1" -pyjwt = {version = ">=2.5.0", extras = ["crypto"]} - -[[package]] -name = "funcy" -version = "1.17" -description = "A fancy and practical functional tools" -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "future" -version = "0.18.2" -description = "Clean single-source support for Python 3 and 2" -category = "main" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" - -[[package]] -name = "google-api-core" -version = "2.11.0" -description = "Google API client core library" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -google-auth = ">=2.14.1,<3.0dev" -googleapis-common-protos = ">=1.56.2,<2.0dev" -grpcio = [ - {version = ">=1.33.2,<2.0dev", optional = true, markers = "extra == \"grpc\""}, - {version = ">=1.49.1,<2.0dev", optional = true, markers = "python_version >= \"3.11\""}, -] -grpcio-status = [ - {version = ">=1.33.2,<2.0dev", optional = true, markers = "extra == \"grpc\""}, - {version = ">=1.49.1,<2.0dev", optional = true, markers = "python_version >= \"3.11\""}, -] -protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0dev" -requests = ">=2.18.0,<3.0.0dev" - -[package.extras] -grpc = ["grpcio (>=1.33.2,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "grpcio-status (>=1.33.2,<2.0dev)", "grpcio-status (>=1.49.1,<2.0dev)"] -grpcgcp = ["grpcio-gcp (>=0.2.2,<1.0dev)"] -grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0dev)"] - -[[package]] -name = "google-api-python-client" -version = "2.71.0" -description = "Google API Client Library for Python" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -google-api-core = ">=1.31.5,<2.0.0 || >2.3.0,<3.0.0dev" -google-auth = ">=1.19.0,<3.0.0dev" -google-auth-httplib2 = ">=0.1.0" -httplib2 = ">=0.15.0,<1dev" -uritemplate = ">=3.0.1,<5" - -[[package]] -name = "google-auth" -version = "2.15.0" -description = "Google Authentication Library" -category = "main" -optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*" - -[package.dependencies] -cachetools = ">=2.0.0,<6.0" -pyasn1-modules = ">=0.2.1" -rsa = {version = ">=3.1.4,<5", markers = "python_version >= \"3.6\""} -six = ">=1.9.0" - -[package.extras] -aiohttp = ["aiohttp (>=3.6.2,<4.0.0dev)", "requests (>=2.20.0,<3.0.0dev)"] -enterprise-cert = ["cryptography (==36.0.2)", "pyopenssl (==22.0.0)"] -pyopenssl = ["cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] -reauth = ["pyu2f (>=0.1.5)"] - -[[package]] -name = "google-auth-httplib2" -version = "0.1.0" -description = "Google Authentication Library: httplib2 transport" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -google-auth = "*" -httplib2 = ">=0.15.0" -six = "*" - -[[package]] -name = "google-cloud-core" -version = "2.3.2" -description = "Google Cloud API client core library" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -google-api-core = ">=1.31.6,<2.0.0 || >2.3.0,<3.0.0dev" -google-auth = ">=1.25.0,<3.0dev" - -[package.extras] -grpc = ["grpcio (>=1.38.0,<2.0dev)"] - -[[package]] -name = "google-cloud-firestore" -version = "2.7.3" -description = "Google Cloud Firestore API client library" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -google-api-core = {version = ">=1.34.0,<2.0.0 || >=2.11.0,<3.0.0dev", extras = ["grpc"]} -google-cloud-core = ">=1.4.1,<3.0.0dev" -proto-plus = ">=1.22.0,<2.0.0dev" -protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0dev" - -[[package]] -name = "google-cloud-storage" -version = "2.7.0" -description = "Google Cloud Storage API client library" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -google-api-core = ">=1.31.5,<2.0.0 || >2.3.0,<3.0.0dev" -google-auth = ">=1.25.0,<3.0dev" -google-cloud-core = ">=2.3.0,<3.0dev" -google-resumable-media = ">=2.3.2" -requests = ">=2.18.0,<3.0.0dev" - -[package.extras] -protobuf = ["protobuf (<5.0.0dev)"] - -[[package]] -name = "google-crc32c" -version = "1.5.0" -description = "A python wrapper of the C library 'Google CRC32C'" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.extras] -testing = ["pytest"] - -[[package]] -name = "google-resumable-media" -version = "2.4.0" -description = "Utilities for Google Media Downloads and Resumable Uploads" -category = "main" -optional = false -python-versions = ">= 3.7" - -[package.dependencies] -google-crc32c = ">=1.0,<2.0dev" - -[package.extras] -aiohttp = ["aiohttp (>=3.6.2,<4.0.0dev)"] -requests = ["requests (>=2.18.0,<3.0.0dev)"] - -[[package]] -name = "googleapis-common-protos" -version = "1.57.1" -description = "Common protobufs used in Google APIs" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0dev" - -[package.extras] -grpc = ["grpcio (>=1.44.0,<2.0.0dev)"] - -[[package]] -name = "gprof2dot" -version = "2022.7.29" -description = "Generate a dot graph from the output of several profilers." -category = "dev" -optional = false -python-versions = ">=2.7" - -[[package]] -name = "greenlet" -version = "2.0.1" -description = "Lightweight in-process concurrent programming" -category = "main" -optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" - -[package.extras] -docs = ["Sphinx", "docutils (<0.18)"] -test = ["faulthandler", "objgraph", "psutil"] - -[[package]] -name = "grpcio" -version = "1.51.1" -description = "HTTP/2-based RPC framework" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.extras] -protobuf = ["grpcio-tools (>=1.51.1)"] - -[[package]] -name = "grpcio-status" -version = "1.51.1" -description = "Status proto mapping for gRPC" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -googleapis-common-protos = ">=1.5.5" -grpcio = ">=1.51.1" -protobuf = ">=4.21.6" - -[[package]] -name = "gunicorn" -version = "19.10.0" -description = "WSGI HTTP Server for UNIX" -category = "main" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*" - -[package.extras] -eventlet = ["eventlet (>=0.9.7)"] -gevent = ["gevent (>=0.13)"] -tornado = ["tornado (>=0.2)"] - -[[package]] -name = "html5lib" -version = "1.1" -description = "HTML parser based on the WHATWG HTML specification" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[package.dependencies] -six = ">=1.9" -webencodings = "*" - -[package.extras] -all = ["chardet (>=2.2)", "genshi", "lxml"] -chardet = ["chardet (>=2.2)"] -genshi = ["genshi"] -lxml = ["lxml"] - -[[package]] -name = "httplib2" -version = "0.21.0" -description = "A comprehensive HTTP client library." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[package.dependencies] -pyparsing = {version = ">=2.4.2,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.0.2 || >3.0.2,<3.0.3 || >3.0.3,<4", markers = "python_version > \"3.0\""} - -[[package]] -name = "identify" -version = "2.5.12" -description = "File identification library for Python" -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.extras] -license = ["ukkonen"] - -[[package]] -name = "idna" -version = "3.4" -description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" -optional = false -python-versions = ">=3.5" - -[[package]] -name = "importlib-metadata" -version = "4.8.1" -description = "Read metadata from Python packages" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} -zipp = ">=0.5" - -[package.extras] -docs = ["jaraco.packaging (>=8.2)", "rst.linker (>=1.9)", "sphinx"] -perf = ["ipython"] -testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pep517", "pyfakefs", "pytest (>=4.6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy", "pytest-perf (>=0.9.2)"] - -[[package]] -name = "inflection" -version = "0.5.1" -description = "A port of Ruby on Rails inflector to Python" -category = "main" -optional = false -python-versions = ">=3.5" - -[[package]] -name = "isort" -version = "5.11.4" -description = "A Python utility / library to sort Python imports." -category = "dev" -optional = false -python-versions = ">=3.7.0" - -[package.extras] -colors = ["colorama (>=0.4.3,<0.5.0)"] -pipfile-deprecated-finder = ["pipreqs", "requirementslib"] -plugins = ["setuptools"] -requirements-deprecated-finder = ["pip-api", "pipreqs"] - -[[package]] -name = "itypes" -version = "1.2.0" -description = "Simple immutable types for python." -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "jinja2" -version = "3.1.2" -description = "A very fast and expressive template engine." -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -MarkupSafe = ">=2.0" - -[package.extras] -i18n = ["Babel (>=2.7)"] - -[[package]] -name = "jinxed" -version = "1.2.0" -description = "Jinxed Terminal Library" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -ansicon = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "jmespath" -version = "1.0.1" -description = "JSON Matching Expressions" -category = "main" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "kombu" -version = "4.6.11" -description = "Messaging library for Python." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[package.dependencies] -amqp = ">=2.6.0,<2.7" -importlib-metadata = {version = ">=0.18", markers = "python_version < \"3.8\""} - -[package.extras] -azureservicebus = ["azure-servicebus (>=0.21.1)"] -azurestoragequeues = ["azure-storage-queue"] -consul = ["python-consul (>=0.6.0)"] -librabbitmq = ["librabbitmq (>=1.5.2)"] -mongodb = ["pymongo (>=3.3.0)"] -msgpack = ["msgpack"] -pyro = ["pyro4"] -qpid = ["qpid-python (>=0.26)", "qpid-tools (>=0.26)"] -redis = ["redis (>=3.3.11)"] -slmq = ["softlayer-messaging (>=1.0.3)"] -sqlalchemy = ["sqlalchemy"] -sqs = ["boto3 (>=1.4.4)", "pycurl (==7.43.0.2)"] -yaml = ["PyYAML (>=3.10)"] -zookeeper = ["kazoo (>=1.3.1)"] - -[[package]] -name = "lazy-object-proxy" -version = "1.9.0" -description = "A fast and thorough lazy object proxy." -category = "dev" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "lxml" -version = "4.9.2" -description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*" - -[package.extras] -cssselect = ["cssselect (>=0.7)"] -html5 = ["html5lib"] -htmlsoup = ["BeautifulSoup4"] -source = ["Cython (>=0.29.7)"] - -[[package]] -name = "markupsafe" -version = "2.1.1" -description = "Safely add untrusted strings to HTML/XML markup." -category = "main" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "mccabe" -version = "0.7.0" -description = "McCabe checker, plugin for flake8" -category = "dev" -optional = false -python-versions = ">=3.6" - -[[package]] -name = "more-itertools" -version = "9.0.0" -description = "More routines for operating on iterables, beyond itertools" -category = "main" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "msgpack" -version = "1.0.4" -description = "MessagePack serializer" -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "mypy-extensions" -version = "0.4.3" -description = "Experimental type system extensions for programs checked with the mypy typechecker." -category = "dev" -optional = false -python-versions = "*" - -[[package]] -name = "mysqlclient" -version = "2.1.1" -description = "Python interface to MySQL" -category = "main" -optional = false -python-versions = ">=3.5" - -[[package]] -name = "nodeenv" -version = "1.7.0" -description = "Node.js virtual environment builder" -category = "dev" -optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" - -[package.dependencies] -setuptools = "*" - -[[package]] -name = "packaging" -version = "22.0" -description = "Core utilities for Python packages" -category = "main" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "pathspec" -version = "0.10.3" -description = "Utility library for gitignore style pattern matching of file paths." -category = "dev" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "pillow" -version = "9.4.0" -description = "Python Imaging Library (Fork)" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.extras] -docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-issues (>=3.0.1)", "sphinx-removed-in", "sphinxext-opengraph"] -tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] - -[[package]] -name = "platformdirs" -version = "2.6.2" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -typing-extensions = {version = ">=4.4", markers = "python_version < \"3.8\""} - -[package.extras] -docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.5)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] - -[[package]] -name = "pluggy" -version = "0.13.1" -description = "plugin and hook calling mechanisms for python" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[package.dependencies] -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} - -[package.extras] -dev = ["pre-commit", "tox"] - -[[package]] -name = "pre-commit" -version = "2.21.0" -description = "A framework for managing and maintaining multi-language pre-commit hooks." -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -cfgv = ">=2.0.0" -identify = ">=1.0.0" -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} -nodeenv = ">=0.11.1" -pyyaml = ">=5.1" -virtualenv = ">=20.10.0" - -[[package]] -name = "proto-plus" -version = "1.22.1" -description = "Beautiful, Pythonic protocol buffers." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -protobuf = ">=3.19.0,<5.0.0dev" - -[package.extras] -testing = ["google-api-core[grpc] (>=1.31.5)"] - -[[package]] -name = "protobuf" -version = "4.21.12" -description = "" -category = "main" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "py" -version = "1.11.0" -description = "library with cross-python path, ini-parsing, io, code, log facilities" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[[package]] -name = "pyasn1" -version = "0.4.8" -description = "ASN.1 types and codecs" -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "pyasn1-modules" -version = "0.2.8" -description = "A collection of ASN.1-based protocols modules." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -pyasn1 = ">=0.4.6,<0.5.0" - -[[package]] -name = "pycodestyle" -version = "2.10.0" -description = "Python style guide checker" -category = "dev" -optional = false -python-versions = ">=3.6" - -[[package]] -name = "pycparser" -version = "2.21" -description = "C parser in Python" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[[package]] -name = "pygments" -version = "2.14.0" -description = "Pygments is a syntax highlighting package written in Python." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.extras] -plugins = ["importlib-metadata"] - -[[package]] -name = "pyjwt" -version = "2.6.0" -description = "JSON Web Token implementation in Python" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.dependencies] -cryptography = {version = ">=3.4.0", optional = true, markers = "extra == \"crypto\""} - -[package.extras] -crypto = ["cryptography (>=3.4.0)"] -dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] -docs = ["sphinx (>=4.5.0,<5.0.0)", "sphinx-rtd-theme", "zope.interface"] -tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] - -[[package]] -name = "pylint" -version = "2.13.9" -description = "python code static checker" -category = "dev" -optional = false -python-versions = ">=3.6.2" - -[package.dependencies] -astroid = ">=2.11.5,<=2.12.0-dev0" -colorama = {version = "*", markers = "sys_platform == \"win32\""} -dill = ">=0.2" -isort = ">=4.2.5,<6" -mccabe = ">=0.6,<0.8" -platformdirs = ">=2.2.0" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} - -[package.extras] -testutil = ["gitpython (>3)"] - -[[package]] -name = "pylint-django" -version = "2.5.3" -description = "A Pylint plugin to help Pylint understand the Django web framework" -category = "dev" -optional = false -python-versions = "*" - -[package.dependencies] -pylint = ">=2.0,<3" -pylint-plugin-utils = ">=0.7" - -[package.extras] -for-tests = ["coverage", "django-tables2", "django-tastypie", "factory-boy", "pylint (>=2.13)", "pytest", "wheel"] -with-django = ["Django"] - -[[package]] -name = "pylint-plugin-utils" -version = "0.7" -description = "Utilities and helpers for writing Pylint plugins" -category = "dev" -optional = false -python-versions = ">=3.6.2" - -[package.dependencies] -pylint = ">=1.7" - -[[package]] -name = "pyotp" -version = "2.8.0" -description = "Python One Time Password Library" -category = "main" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "pyparsing" -version = "3.0.9" -description = "pyparsing module - Classes and methods to define and execute parsing grammars" -category = "main" -optional = false -python-versions = ">=3.6.8" - -[package.extras] -diagrams = ["jinja2", "railroad-diagrams"] - -[[package]] -name = "pytest" -version = "5.4.3" -description = "pytest: simple powerful testing with Python" -category = "main" -optional = false -python-versions = ">=3.5" - -[package.dependencies] -atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} -attrs = ">=17.4.0" -colorama = {version = "*", markers = "sys_platform == \"win32\""} -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} -more-itertools = ">=4.0.0" -packaging = "*" -pluggy = ">=0.12,<1.0" -py = ">=1.5.0" -wcwidth = "*" - -[package.extras] -checkqa-mypy = ["mypy (==v0.761)"] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] - -[[package]] -name = "pytest-cov" -version = "2.12.1" -description = "Pytest plugin for measuring coverage." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[package.dependencies] -coverage = ">=5.2.1" -pytest = ">=4.6" -toml = "*" - -[package.extras] -testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] - -[[package]] -name = "pytest-django" -version = "3.10.0" -description = "A Django plugin for pytest." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[package.dependencies] -pytest = ">=3.6" - -[package.extras] -docs = ["sphinx", "sphinx-rtd-theme"] -testing = ["Django", "django-configurations (>=2.0)", "six"] - -[[package]] -name = "python-crontab" -version = "2.7.1" -description = "Python Crontab API" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -python-dateutil = "*" - -[package.extras] -cron-description = ["cron-descriptor"] -cron-schedule = ["croniter"] - -[[package]] -name = "python-dateutil" -version = "2.8.2" -description = "Extensions to the standard Python datetime module" -category = "main" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" - -[package.dependencies] -six = ">=1.5" - -[[package]] -name = "pytz" -version = "2022.7" -description = "World timezone definitions, modern and historical" -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "pyyaml" -version = "6.0" -description = "YAML parser and emitter for Python" -category = "dev" -optional = false -python-versions = ">=3.6" - -[[package]] -name = "redis" -version = "3.5.3" -description = "Python client for Redis key-value store" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[package.extras] -hiredis = ["hiredis (>=0.1.3)"] - -[[package]] -name = "requests" -version = "2.28.1" -description = "Python HTTP for Humans." -category = "main" -optional = false -python-versions = ">=3.7, <4" - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = ">=2,<3" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<1.27" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - -[[package]] -name = "rsa" -version = "4.9" -description = "Pure-Python RSA implementation" -category = "main" -optional = false -python-versions = ">=3.6,<4" - -[package.dependencies] -pyasn1 = ">=0.1.3" - -[[package]] -name = "ruamel-yaml" -version = "0.17.21" -description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" -category = "main" -optional = false -python-versions = ">=3" - -[package.dependencies] -"ruamel.yaml.clib" = {version = ">=0.2.6", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.11\""} - -[package.extras] -docs = ["ryd"] -jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] - -[[package]] -name = "ruamel-yaml-clib" -version = "0.2.7" -description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" -category = "main" -optional = false -python-versions = ">=3.5" - -[[package]] -name = "s3transfer" -version = "0.6.0" -description = "An Amazon S3 Transfer Manager" -category = "main" -optional = false -python-versions = ">= 3.7" - -[package.dependencies] -botocore = ">=1.12.36,<2.0a.0" - -[package.extras] -crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"] - -[[package]] -name = "sentry-sdk" -version = "0.19.4" -description = "Python client for Sentry (https://sentry.io)" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -certifi = "*" -urllib3 = ">=1.10.0" - -[package.extras] -aiohttp = ["aiohttp (>=3.5)"] -beam = ["apache-beam (>=2.12)"] -bottle = ["bottle (>=0.12.13)"] -celery = ["celery (>=3)"] -chalice = ["chalice (>=1.16.0)"] -django = ["django (>=1.8)"] -falcon = ["falcon (>=1.4)"] -flask = ["blinker (>=1.1)", "flask (>=0.11)"] -pure-eval = ["asttokens", "executing", "pure-eval"] -pyspark = ["pyspark (>=2.4.4)"] -rq = ["rq (>=0.6)"] -sanic = ["sanic (>=0.8)"] -sqlalchemy = ["sqlalchemy (>=1.2)"] -tornado = ["tornado (>=5)"] - -[[package]] -name = "setuptools" -version = "65.6.3" -description = "Easily download, build, install, upgrade, and uninstall Python packages" -category = "dev" -optional = false -python-versions = ">=3.7" - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] - -[[package]] -name = "six" -version = "1.16.0" -description = "Python 2 and 3 compatibility utilities" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" - -[[package]] -name = "soupsieve" -version = "2.3.2.post1" -description = "A modern CSS selector implementation for Beautiful Soup." -category = "main" -optional = false -python-versions = ">=3.6" - -[[package]] -name = "sqlparse" -version = "0.4.3" -description = "A non-validating SQL parser." -category = "main" -optional = false -python-versions = ">=3.5" - -[[package]] -name = "toml" -version = "0.10.2" -description = "Python Library for Tom's Obvious, Minimal Language" -category = "main" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" - -[[package]] -name = "tomli" -version = "2.0.1" -description = "A lil' TOML parser" -category = "dev" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "tqdm" -version = "4.64.1" -description = "Fast, Extensible Progress Meter" -category = "main" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[package.extras] -dev = ["py-make (>=0.1.0)", "twine", "wheel"] -notebook = ["ipywidgets (>=6)"] -slack = ["slack-sdk"] -telegram = ["requests"] - -[[package]] -name = "typed-ast" -version = "1.5.4" -description = "a fork of Python 2 and 3 ast modules with type comment support" -category = "dev" -optional = false -python-versions = ">=3.6" - -[[package]] -name = "typing-extensions" -version = "4.4.0" -description = "Backported and Experimental Type Hints for Python 3.7+" -category = "main" -optional = false -python-versions = ">=3.7" - -[[package]] -name = "uritemplate" -version = "4.1.1" -description = "Implementation of RFC 6570 URI Templates" -category = "main" -optional = false -python-versions = ">=3.6" - -[[package]] -name = "urllib3" -version = "1.26.13" -description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" - -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] - -[[package]] -name = "vine" -version = "1.3.0" -description = "Promises, promises, promises." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[[package]] -name = "virtualenv" -version = "20.16.2" -description = "Virtual Python Environment builder" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -distlib = ">=0.3.1,<1" -filelock = ">=3.2,<4" -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} -platformdirs = ">=2,<3" - -[package.extras] -docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"] -testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "packaging (>=20.0)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)"] - -[[package]] -name = "wcwidth" -version = "0.2.5" -description = "Measures the displayed width of unicode strings in a terminal" -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "webencodings" -version = "0.5.1" -description = "Character encoding aliases for legacy web content" -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "wrapt" -version = "1.14.1" -description = "Module for decorators, wrappers and monkey patching." -category = "dev" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" - -[[package]] -name = "zipp" -version = "3.11.0" -description = "Backport of pathlib-compatible object wrapper for zip files" -category = "main" -optional = false -python-versions = ">=3.7" - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"] -testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] - -[metadata] -lock-version = "1.1" -python-versions = "^3.7" -content-hash = "b773ef61d3e58021d5cb4853fb6a74c79df4e39a323025caf92b407c0a266610" - -[metadata.files] -amqp = [ - {file = "amqp-2.6.1-py2.py3-none-any.whl", hash = "sha256:aa7f313fb887c91f15474c1229907a04dac0b8135822d6603437803424c0aa59"}, - {file = "amqp-2.6.1.tar.gz", hash = "sha256:70cdb10628468ff14e57ec2f751c7aa9e48e7e3651cfd62d431213c0c4e58f21"}, -] -ansicon = [ - {file = "ansicon-1.89.0-py2.py3-none-any.whl", hash = "sha256:f1def52d17f65c2c9682cf8370c03f541f410c1752d6a14029f97318e4b9dfec"}, - {file = "ansicon-1.89.0.tar.gz", hash = "sha256:e4d039def5768a47e4afec8e89e83ec3ae5a26bf00ad851f914d1240b444d2b1"}, -] -asgiref = [ - {file = "asgiref-3.6.0-py3-none-any.whl", hash = "sha256:71e68008da809b957b7ee4b43dbccff33d1b23519fb8344e33f049897077afac"}, - {file = "asgiref-3.6.0.tar.gz", hash = "sha256:9567dfe7bd8d3c8c892227827c41cce860b368104c3431da67a0c5a65a949506"}, -] -astroid = [ - {file = "astroid-2.11.7-py3-none-any.whl", hash = "sha256:86b0a340a512c65abf4368b80252754cda17c02cdbbd3f587dddf98112233e7b"}, - {file = "astroid-2.11.7.tar.gz", hash = "sha256:bb24615c77f4837c707669d16907331374ae8a964650a66999da3f5ca68dc946"}, -] -atomicwrites = [ - {file = "atomicwrites-1.4.1.tar.gz", hash = "sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11"}, -] -attrs = [ - {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"}, - {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"}, -] -autopep8 = [ - {file = "autopep8-1.7.0-py2.py3-none-any.whl", hash = "sha256:6f09e90a2be784317e84dc1add17ebfc7abe3924239957a37e5040e27d812087"}, - {file = "autopep8-1.7.0.tar.gz", hash = "sha256:ca9b1a83e53a7fad65d731dc7a2a2d50aa48f43850407c59f6a1a306c4201142"}, -] -backports-cached-property = [ - {file = "backports.cached-property-1.0.2.tar.gz", hash = "sha256:9306f9eed6ec55fd156ace6bc1094e2c86fae5fb2bf07b6a9c00745c656e75dd"}, - {file = "backports.cached_property-1.0.2-py3-none-any.whl", hash = "sha256:baeb28e1cd619a3c9ab8941431fe34e8490861fb998c6c4590693d50171db0cc"}, -] -beautifulsoup4 = [ - {file = "beautifulsoup4-4.11.1-py3-none-any.whl", hash = "sha256:58d5c3d29f5a36ffeb94f02f0d786cd53014cf9b3b3951d42e0080d8a9498d30"}, - {file = "beautifulsoup4-4.11.1.tar.gz", hash = "sha256:ad9aa55b65ef2808eb405f46cf74df7fcb7044d5cbc26487f96eb2ef2e436693"}, -] -billiard = [ - {file = "billiard-3.6.4.0-py3-none-any.whl", hash = "sha256:87103ea78fa6ab4d5c751c4909bcff74617d985de7fa8b672cf8618afd5a875b"}, - {file = "billiard-3.6.4.0.tar.gz", hash = "sha256:299de5a8da28a783d51b197d496bef4f1595dd023a93a4f59dde1886ae905547"}, -] -black = [ - {file = "black-22.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d"}, - {file = "black-22.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351"}, - {file = "black-22.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f"}, - {file = "black-22.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4"}, - {file = "black-22.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2"}, - {file = "black-22.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350"}, - {file = "black-22.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d"}, - {file = "black-22.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc"}, - {file = "black-22.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320"}, - {file = "black-22.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148"}, - {file = "black-22.12.0-py3-none-any.whl", hash = "sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf"}, - {file = "black-22.12.0.tar.gz", hash = "sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f"}, -] -bleach = [ - {file = "bleach-3.3.1-py2.py3-none-any.whl", hash = "sha256:ae976d7174bba988c0b632def82fdc94235756edfb14e6558a9c5be555c9fb78"}, - {file = "bleach-3.3.1.tar.gz", hash = "sha256:306483a5a9795474160ad57fce3ddd1b50551e981eed8e15a582d34cef28aafa"}, -] -blessed = [ - {file = "blessed-1.19.1-py2.py3-none-any.whl", hash = "sha256:63b8554ae2e0e7f43749b6715c734cc8f3883010a809bf16790102563e6cf25b"}, - {file = "blessed-1.19.1.tar.gz", hash = "sha256:9a0d099695bf621d4680dd6c73f6ad547f6a3442fbdbe80c4b1daa1edbc492fc"}, -] -blessings = [ - {file = "blessings-1.7-py2-none-any.whl", hash = "sha256:caad5211e7ba5afe04367cdd4cfc68fa886e2e08f6f35e76b7387d2109ccea6e"}, - {file = "blessings-1.7-py3-none-any.whl", hash = "sha256:b1fdd7e7a675295630f9ae71527a8ebc10bfefa236b3d6aa4932ee4462c17ba3"}, - {file = "blessings-1.7.tar.gz", hash = "sha256:98e5854d805f50a5b58ac2333411b0482516a8210f23f43308baeb58d77c157d"}, -] -boto3 = [ - {file = "boto3-1.26.43-py3-none-any.whl", hash = "sha256:0335af7a6deee3538672a6c6b2718a513e62070e84c7addfb610ee1aa45e664a"}, - {file = "boto3-1.26.43.tar.gz", hash = "sha256:5c462ceddb3e51d1cd4239b4a84744b766a4f2db5afdc370f11d2d15f52a9a07"}, -] -botocore = [ - {file = "botocore-1.29.43-py3-none-any.whl", hash = "sha256:dc60385c56b960aa75ef05cdcf808e6c07ad04b1b392d1abd6fc405a16d85826"}, - {file = "botocore-1.29.43.tar.gz", hash = "sha256:a801e40f5f14c1b2fb3c0b2c438b546f07805d53d57d8dc135ebce4fdce901bd"}, -] -bpython = [ - {file = "bpython-0.19-py2.py3-none-any.whl", hash = "sha256:95d95783bfadfa0a25300a648de5aba4423b0ee76b034022a81dde2b5e853c00"}, - {file = "bpython-0.19.tar.gz", hash = "sha256:476ce09a896c4d34bf5e56aca64650c56fdcfce45781a20dc1521221df8cc49c"}, -] -cachecontrol = [ - {file = "CacheControl-0.12.11-py2.py3-none-any.whl", hash = "sha256:2c75d6a8938cb1933c75c50184549ad42728a27e9f6b92fd677c3151aa72555b"}, - {file = "CacheControl-0.12.11.tar.gz", hash = "sha256:a5b9fcc986b184db101aa280b42ecdcdfc524892596f606858e0b7a8b4d9e144"}, -] -cached-property = [ - {file = "cached-property-1.5.2.tar.gz", hash = "sha256:9fa5755838eecbb2d234c3aa390bd80fbd3ac6b6869109bfc1b499f7bd89a130"}, - {file = "cached_property-1.5.2-py2.py3-none-any.whl", hash = "sha256:df4f613cf7ad9a588cc381aaf4a512d26265ecebd5eb9e1ba12f1319eb85a6a0"}, -] -cachetools = [ - {file = "cachetools-5.2.0-py3-none-any.whl", hash = "sha256:f9f17d2aec496a9aa6b76f53e3b614c965223c061982d434d160f930c698a9db"}, - {file = "cachetools-5.2.0.tar.gz", hash = "sha256:6a94c6402995a99c3970cc7e4884bb60b4a8639938157eeed436098bf9831757"}, -] -celery = [ - {file = "celery-4.4.7-py2.py3-none-any.whl", hash = "sha256:a92e1d56e650781fb747032a3997d16236d037c8199eacd5217d1a72893bca45"}, - {file = "celery-4.4.7.tar.gz", hash = "sha256:d220b13a8ed57c78149acf82c006785356071844afe0b27012a4991d44026f9f"}, -] -certifi = [ - {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, - {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, -] -cffi = [ - {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"}, - {file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"}, - {file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"}, - {file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"}, - {file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"}, - {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"}, - {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"}, - {file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"}, - {file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"}, - {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"}, - {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"}, - {file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"}, - {file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"}, - {file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"}, - {file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"}, - {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"}, - {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"}, - {file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"}, - {file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"}, - {file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"}, - {file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"}, - {file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"}, - {file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"}, - {file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"}, - {file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"}, - {file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"}, - {file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"}, - {file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"}, - {file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"}, - {file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"}, - {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"}, - {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"}, - {file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"}, - {file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"}, - {file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"}, -] -cfgv = [ - {file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"}, - {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"}, -] -charset-normalizer = [ - {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, - {file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"}, -] -click = [ - {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, - {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, -] -colorama = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] -coreapi = [ - {file = "coreapi-2.3.3-py2.py3-none-any.whl", hash = "sha256:bf39d118d6d3e171f10df9ede5666f63ad80bba9a29a8ec17726a66cf52ee6f3"}, - {file = "coreapi-2.3.3.tar.gz", hash = "sha256:46145fcc1f7017c076a2ef684969b641d18a2991051fddec9458ad3f78ffc1cb"}, -] -coreschema = [ - {file = "coreschema-0.0.4-py2-none-any.whl", hash = "sha256:5e6ef7bf38c1525d5e55a895934ab4273548629f16aed5c0a6caa74ebf45551f"}, - {file = "coreschema-0.0.4.tar.gz", hash = "sha256:9503506007d482ab0867ba14724b93c18a33b22b6d19fb419ef2d239dd4a1607"}, -] -coverage = [ - {file = "coverage-7.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f7c51b6074a8a3063c341953dffe48fd6674f8e4b1d3c8aa8a91f58d6e716a8"}, - {file = "coverage-7.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:628f47eaf66727fc986d3b190d6fa32f5e6b7754a243919d28bc0fd7974c449f"}, - {file = "coverage-7.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e89d5abf86c104de808108a25d171ad646c07eda96ca76c8b237b94b9c71e518"}, - {file = "coverage-7.0.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:75e43c6f4ea4d122dac389aabdf9d4f0e160770a75e63372f88005d90f5bcc80"}, - {file = "coverage-7.0.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49da0ff241827ebb52d5d6d5a36d33b455fa5e721d44689c95df99fd8db82437"}, - {file = "coverage-7.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0bce4ad5bdd0b02e177a085d28d2cea5fc57bb4ba2cead395e763e34cf934eb1"}, - {file = "coverage-7.0.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:f79691335257d60951638dd43576b9bcd6f52baa5c1c2cd07a509bb003238372"}, - {file = "coverage-7.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5722269ed05fbdb94eef431787c66b66260ff3125d1a9afcc00facff8c45adf9"}, - {file = "coverage-7.0.3-cp310-cp310-win32.whl", hash = "sha256:bdbda870e0fda7dd0fe7db7135ca226ec4c1ade8aa76e96614829b56ca491012"}, - {file = "coverage-7.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:e56fae4292e216b8deeee38ace84557b9fa85b52db005368a275427cdabb8192"}, - {file = "coverage-7.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b82343a5bc51627b9d606f0b6b6b9551db7b6311a5dd920fa52a94beae2e8959"}, - {file = "coverage-7.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fd0a8aa431f9b7ad9eb8264f55ef83cbb254962af3775092fb6e93890dea9ca2"}, - {file = "coverage-7.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:112cfead1bd22eada8a8db9ed387bd3e8be5528debc42b5d3c1f7da4ffaf9fb5"}, - {file = "coverage-7.0.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:af87e906355fa42447be5c08c5d44e6e1c005bf142f303f726ddf5ed6e0c8a4d"}, - {file = "coverage-7.0.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f30090e22a301952c5abd0e493a1c8358b4f0b368b49fa3e4568ed3ed68b8d1f"}, - {file = "coverage-7.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ae871d09901911eedda1981ea6fd0f62a999107293cdc4c4fd612321c5b34745"}, - {file = "coverage-7.0.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ed7c9debf7bfc63c9b9f8b595409237774ff4b061bf29fba6f53b287a2fdeab9"}, - {file = "coverage-7.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:13121fa22dcd2c7b19c5161e3fd725692448f05377b788da4502a383573227b3"}, - {file = "coverage-7.0.3-cp311-cp311-win32.whl", hash = "sha256:037b51ee86bc600f99b3b957c20a172431c35c2ef9c1ca34bc813ab5b51fd9f5"}, - {file = "coverage-7.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:25fde928306034e8deecd5fc91a07432dcc282c8acb76749581a28963c9f4f3f"}, - {file = "coverage-7.0.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7e8b0642c38b3d3b3c01417643ccc645345b03c32a2e84ef93cdd6844d6fe530"}, - {file = "coverage-7.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18b09811f849cc958d23f733a350a66b54a8de3fed1e6128ba55a5c97ffb6f65"}, - {file = "coverage-7.0.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:349d0b545520e8516f7b4f12373afc705d17d901e1de6a37a20e4ec9332b61f7"}, - {file = "coverage-7.0.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b5b38813eee5b4739f505d94247604c72eae626d5088a16dd77b08b8b1724ab3"}, - {file = "coverage-7.0.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ba9af1218fa01b1f11c72271bc7290b701d11ad4dbc2ae97c445ecacf6858dba"}, - {file = "coverage-7.0.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c5648c7eec5cf1ba5db1cf2d6c10036a582d7f09e172990474a122e30c841361"}, - {file = "coverage-7.0.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d0df04495b76a885bfef009f45eebe8fe2fbf815ad7a83dabcf5aced62f33162"}, - {file = "coverage-7.0.3-cp37-cp37m-win32.whl", hash = "sha256:af6cef3796b8068713a48dd67d258dc9a6e2ebc3bd4645bfac03a09672fa5d20"}, - {file = "coverage-7.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:62ef3800c4058844e2e3fa35faa9dd0ccde8a8aba6c763aae50342e00d4479d4"}, - {file = "coverage-7.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:acef7f3a3825a2d218a03dd02f5f3cc7f27aa31d882dd780191d1ad101120d74"}, - {file = "coverage-7.0.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a530663a361eb27375cec28aea5cd282089b5e4b022ae451c4c3493b026a68a5"}, - {file = "coverage-7.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c58cd6bb46dcb922e0d5792850aab5964433d511b3a020867650f8d930dde4f4"}, - {file = "coverage-7.0.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f918e9ef4c98f477a5458238dde2a1643aed956c7213873ab6b6b82e32b8ef61"}, - {file = "coverage-7.0.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b865aa679bee7fbd1c55960940dbd3252621dd81468268786c67122bbd15343"}, - {file = "coverage-7.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c5d9b480ebae60fc2cbc8d6865194136bc690538fa542ba58726433bed6e04cc"}, - {file = "coverage-7.0.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:985ad2af5ec3dbb4fd75d5b0735752c527ad183455520055a08cf8d6794cabfc"}, - {file = "coverage-7.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ca15308ef722f120967af7474ba6a453e0f5b6f331251e20b8145497cf1bc14a"}, - {file = "coverage-7.0.3-cp38-cp38-win32.whl", hash = "sha256:c1cee10662c25c94415bbb987f2ec0e6ba9e8fce786334b10be7e6a7ab958f69"}, - {file = "coverage-7.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:44d6a556de4418f1f3bfd57094b8c49f0408df5a433cf0d253eeb3075261c762"}, - {file = "coverage-7.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e6dcc70a25cb95df0ae33dfc701de9b09c37f7dd9f00394d684a5b57257f8246"}, - {file = "coverage-7.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:bf76d79dfaea802f0f28f50153ffbc1a74ae1ee73e480baeda410b4f3e7ab25f"}, - {file = "coverage-7.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88834e5d56d01c141c29deedacba5773fe0bed900b1edc957595a8a6c0da1c3c"}, - {file = "coverage-7.0.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef001a60e888f8741e42e5aa79ae55c91be73761e4df5e806efca1ddd62fd400"}, - {file = "coverage-7.0.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4959dc506be74e4963bd2c42f7b87d8e4b289891201e19ec551e64c6aa5441f8"}, - {file = "coverage-7.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b791beb17b32ac019a78cfbe6184f992b6273fdca31145b928ad2099435e2fcb"}, - {file = "coverage-7.0.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b07651e3b9af8f1a092861d88b4c74d913634a7f1f2280fca0ad041ad84e9e96"}, - {file = "coverage-7.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:55e46fa4168ccb7497c9be78627fcb147e06f474f846a10d55feeb5108a24ef0"}, - {file = "coverage-7.0.3-cp39-cp39-win32.whl", hash = "sha256:e3f1cd1cd65695b1540b3cf7828d05b3515974a9d7c7530f762ac40f58a18161"}, - {file = "coverage-7.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:d8249666c23683f74f8f93aeaa8794ac87cc61c40ff70374a825f3352a4371dc"}, - {file = "coverage-7.0.3-pp37.pp38.pp39-none-any.whl", hash = "sha256:b1ffc8f58b81baed3f8962e28c30d99442079b82ce1ec836a1f67c0accad91c1"}, - {file = "coverage-7.0.3.tar.gz", hash = "sha256:d5be4e93acce64f516bf4fd239c0e6118fc913c93fa1a3f52d15bdcc60d97b2d"}, -] -cryptography = [ - {file = "cryptography-39.0.0-cp36-abi3-macosx_10_12_universal2.whl", hash = "sha256:c52a1a6f81e738d07f43dab57831c29e57d21c81a942f4602fac7ee21b27f288"}, - {file = "cryptography-39.0.0-cp36-abi3-macosx_10_12_x86_64.whl", hash = "sha256:80ee674c08aaef194bc4627b7f2956e5ba7ef29c3cc3ca488cf15854838a8f72"}, - {file = "cryptography-39.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:887cbc1ea60786e534b00ba8b04d1095f4272d380ebd5f7a7eb4cc274710fad9"}, - {file = "cryptography-39.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f97109336df5c178ee7c9c711b264c502b905c2d2a29ace99ed761533a3460f"}, - {file = "cryptography-39.0.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a6915075c6d3a5e1215eab5d99bcec0da26036ff2102a1038401d6ef5bef25b"}, - {file = "cryptography-39.0.0-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:76c24dd4fd196a80f9f2f5405a778a8ca132f16b10af113474005635fe7e066c"}, - {file = "cryptography-39.0.0-cp36-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:bae6c7f4a36a25291b619ad064a30a07110a805d08dc89984f4f441f6c1f3f96"}, - {file = "cryptography-39.0.0-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:875aea1039d78557c7c6b4db2fe0e9d2413439f4676310a5f269dd342ca7a717"}, - {file = "cryptography-39.0.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:f6c0db08d81ead9576c4d94bbb27aed8d7a430fa27890f39084c2d0e2ec6b0df"}, - {file = "cryptography-39.0.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f3ed2d864a2fa1666e749fe52fb8e23d8e06b8012e8bd8147c73797c506e86f1"}, - {file = "cryptography-39.0.0-cp36-abi3-win32.whl", hash = "sha256:f671c1bb0d6088e94d61d80c606d65baacc0d374e67bf895148883461cd848de"}, - {file = "cryptography-39.0.0-cp36-abi3-win_amd64.whl", hash = "sha256:e324de6972b151f99dc078defe8fb1b0a82c6498e37bff335f5bc6b1e3ab5a1e"}, - {file = "cryptography-39.0.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:754978da4d0457e7ca176f58c57b1f9de6556591c19b25b8bcce3c77d314f5eb"}, - {file = "cryptography-39.0.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ee1fd0de9851ff32dbbb9362a4d833b579b4a6cc96883e8e6d2ff2a6bc7104f"}, - {file = "cryptography-39.0.0-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:fec8b932f51ae245121c4671b4bbc030880f363354b2f0e0bd1366017d891458"}, - {file = "cryptography-39.0.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:407cec680e811b4fc829de966f88a7c62a596faa250fc1a4b520a0355b9bc190"}, - {file = "cryptography-39.0.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:7dacfdeee048814563eaaec7c4743c8aea529fe3dd53127313a792f0dadc1773"}, - {file = "cryptography-39.0.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ad04f413436b0781f20c52a661660f1e23bcd89a0e9bb1d6d20822d048cf2856"}, - {file = "cryptography-39.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50386acb40fbabbceeb2986332f0287f50f29ccf1497bae31cf5c3e7b4f4b34f"}, - {file = "cryptography-39.0.0-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:e5d71c5d5bd5b5c3eebcf7c5c2bb332d62ec68921a8c593bea8c394911a005ce"}, - {file = "cryptography-39.0.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:844ad4d7c3850081dffba91cdd91950038ee4ac525c575509a42d3fc806b83c8"}, - {file = "cryptography-39.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:e0a05aee6a82d944f9b4edd6a001178787d1546ec7c6223ee9a848a7ade92e39"}, - {file = "cryptography-39.0.0.tar.gz", hash = "sha256:f964c7dcf7802d133e8dbd1565914fa0194f9d683d82411989889ecd701e8adf"}, -] -curtsies = [ - {file = "curtsies-0.4.1.tar.gz", hash = "sha256:62d10f349c553845306556a7f2663ce96b098d8c5bbc40daec7a6eedde1622b0"}, -] -cwcwidth = [ - {file = "cwcwidth-0.1.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1a5256190f2fa081e9ce0a4e3031992e7c8b98868fc77e4c00bc9563b1fc3017"}, - {file = "cwcwidth-0.1.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0dbb6c6faa5899f71a3064843c528e9ed31881a2b0c83e33ee5109a71a1389cf"}, - {file = "cwcwidth-0.1.8-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5c9c9f6ee425d6d1bf5d09227304e10178755576b103d83457cc9884c7513f"}, - {file = "cwcwidth-0.1.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:79fea2acf7418f7b6398d43f47195b993fcefd4adf4c9a851d93b50914b0eceb"}, - {file = "cwcwidth-0.1.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:577a9394cba36339d41e633c9d82da0c67d26a3392ca64ac33e8379492206041"}, - {file = "cwcwidth-0.1.8-cp310-cp310-win32.whl", hash = "sha256:70f3dd71d935780657e91047389161188e2d121e01c4356746263d280e294fa9"}, - {file = "cwcwidth-0.1.8-cp310-cp310-win_amd64.whl", hash = "sha256:f83b063b93ac8581f11c6a1ebd9adc1c74942fb2f2d5dfd027f81d5217038cf2"}, - {file = "cwcwidth-0.1.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:62d4a203782b9eb677e5645517c6f2bfb033f07f9d3d112e994e37c1ac0d411c"}, - {file = "cwcwidth-0.1.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87a53489a715416b1c0e2b6a498061d9d395747ad4e05af34e4b6efdb68566b7"}, - {file = "cwcwidth-0.1.8-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a56f65342c9878bf243849ed9d4f262544de1590eb0d429821e30fed3f7333c4"}, - {file = "cwcwidth-0.1.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:72aed59f8cdb7a6b0fe3717be766bbdc41c8ac9ad43deb4b61e96e1c8a6f7f1b"}, - {file = "cwcwidth-0.1.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b85483ca46e7715b1d8c3e64a45d15413e33f2a7d5760022fe745135373dad7c"}, - {file = "cwcwidth-0.1.8-cp311-cp311-win32.whl", hash = "sha256:63ea84c5c3ac3f146ef091cded6a96cb9d421c28d8c4b40902adb1e28aeba52a"}, - {file = "cwcwidth-0.1.8-cp311-cp311-win_amd64.whl", hash = "sha256:1e156b9fa6068d32b14984fef9281cedfda114616d6f40cc21202756c04045fd"}, - {file = "cwcwidth-0.1.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:af597541e0c7af9db76f6189ebaae085b4a2649e91e87d0e8e93bf7b822f5a86"}, - {file = "cwcwidth-0.1.8-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c699a2a526b031b62dce4023194b99b0d7649ef042cfb1e18cca76b4a5e714f7"}, - {file = "cwcwidth-0.1.8-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5de08f1f55c255f9fdf6957bf4852d274f70f6cc39f2eff62c7be9342c6e8c6a"}, - {file = "cwcwidth-0.1.8-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:d8acab21c0485d18779fc05b55903dc40a66ce66d0c018edfec01a0ed0a5c469"}, - {file = "cwcwidth-0.1.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6858884314f58532e6c431564dae5fdf6e4f1aa6e461b421a1e431cbd6b40340"}, - {file = "cwcwidth-0.1.8-cp37-cp37m-win32.whl", hash = "sha256:ab47a6010833b017bca750ac4c0ccf3c0478c290d70fb6384f33c4ed238cc4b5"}, - {file = "cwcwidth-0.1.8-cp37-cp37m-win_amd64.whl", hash = "sha256:6f6b6abf1c375f394b2b1ed67237395082db9b3afd6fcb830bd7808ea36878d4"}, - {file = "cwcwidth-0.1.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1cb4768ff9f6dcebcfb9e3bcc06b2de4f7d24ab423b01b94740f6ac5c72eede6"}, - {file = "cwcwidth-0.1.8-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6569c91d787adb312d8d30608e83def6689d0756d39edc4e1d9f85a0512abeee"}, - {file = "cwcwidth-0.1.8-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d89448dfe4b9bde74b4a43fd359c892797262f3c77579027409fb4099f88670f"}, - {file = "cwcwidth-0.1.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5c75d262d3bbb7fda982b0b8ce234d8a9e6bec0920f20c7daad93f7a631b1396"}, - {file = "cwcwidth-0.1.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4dc6b7a86893cb8615f3ff9a29132e21e292d47a30ccb33f1e024d745f30f1f9"}, - {file = "cwcwidth-0.1.8-cp38-cp38-win32.whl", hash = "sha256:26875ee1ac234e4bd73e6b55c0d8e1f61ae51736f4b712a4f9dd147e559fb17f"}, - {file = "cwcwidth-0.1.8-cp38-cp38-win_amd64.whl", hash = "sha256:eaaea46c6895ed5dc2f6ff67a3d13400d8a5f5d0f4f243f487879c358b902099"}, - {file = "cwcwidth-0.1.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:add82ab289c8a9d98af50e711199da1784abbac25a17979dea05ba4e862694de"}, - {file = "cwcwidth-0.1.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f5130eabcab72efdf1eee614a9ed00d0f8da9f6d7e6f81537ce010cecaf3427"}, - {file = "cwcwidth-0.1.8-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9abc6c4616359c21862f3ba42630556102577897f474a9d00bb9cdfa5cb53757"}, - {file = "cwcwidth-0.1.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:058162c84ca54362f8af99a57feba5abe76075e16c7fe8a290f99f63a9b40bd9"}, - {file = "cwcwidth-0.1.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:275d89f102a966755e7b8482b96ad2efd8399853481b2a91d662da48fbcb8539"}, - {file = "cwcwidth-0.1.8-cp39-cp39-win32.whl", hash = "sha256:3e99cd2433ab37e35061057b6fddfd714d34e214bd2f2d9f708e422fe6c4eeb6"}, - {file = "cwcwidth-0.1.8-cp39-cp39-win_amd64.whl", hash = "sha256:02a2e8a7cf1aaa590c1c56624cf87b793b1ecb84850b9a965df78766843439a1"}, - {file = "cwcwidth-0.1.8.tar.gz", hash = "sha256:5adc034b7c90e6a8586bd046bcbf6004e35e16b0d7e31de395513a50d729bbf6"}, -] -dill = [ - {file = "dill-0.3.6-py3-none-any.whl", hash = "sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0"}, - {file = "dill-0.3.6.tar.gz", hash = "sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373"}, -] -distlib = [ - {file = "distlib-0.3.6-py2.py3-none-any.whl", hash = "sha256:f35c4b692542ca110de7ef0bea44d73981caeb34ca0b9b6b2e6d7790dda8f80e"}, - {file = "distlib-0.3.6.tar.gz", hash = "sha256:14bad2d9b04d3a36127ac97f30b12a19268f211063d8f8ee4f47108896e11b46"}, -] -django = [ - {file = "Django-3.2.16-py3-none-any.whl", hash = "sha256:18ba8efa36b69cfcd4b670d0fa187c6fe7506596f0ababe580e16909bcdec121"}, - {file = "Django-3.2.16.tar.gz", hash = "sha256:3adc285124244724a394fa9b9839cc8cd116faf7d159554c43ecdaa8cdf0b94d"}, -] -django-cacheops = [ - {file = "django-cacheops-5.1.tar.gz", hash = "sha256:d5851cd7bf3087384a1fcecfa8dddb8f55030eedfd6fdf127225b75bca0f99dd"}, - {file = "django_cacheops-5.1-py2.py3-none-any.whl", hash = "sha256:02320df37754c143477c5fbd54abf292bcd8b4ca40631e19ec15efa3cc085532"}, -] -django-celery-beat = [ - {file = "django-celery-beat-2.2.0.tar.gz", hash = "sha256:b8a13afb15e7c53fc04f4f847ac71a6d32088959aba701eb7c4a59f0c28ba543"}, - {file = "django_celery_beat-2.2.0-py2.py3-none-any.whl", hash = "sha256:c4c72a9579f20eff4c4ccf1b58ebdca5ef940f4210065057db1754ea5f8dffdc"}, -] -django-celery-results = [ - {file = "django_celery_results-1.2.1-py2.py3-none-any.whl", hash = "sha256:a29ab580f0e38c66c39f51cc426bbdbb2a391b8cc0867df9dea748db2c961db2"}, - {file = "django_celery_results-1.2.1.tar.gz", hash = "sha256:e390f70cc43bbc2cd7c8e4607dc29ab6211a2ab968f93677583f0160921f670c"}, -] -django-cors-headers = [ - {file = "django-cors-headers-3.13.0.tar.gz", hash = "sha256:f9dc6b4e3f611c3199700b3e5f3398c28757dcd559c2f82932687f3d0443cfdf"}, - {file = "django_cors_headers-3.13.0-py3-none-any.whl", hash = "sha256:37e42883b5f1f2295df6b4bba96eb2417a14a03270cb24b2a07f021cd4487cf4"}, -] -django-crontab = [ - {file = "django-crontab-0.7.1.tar.gz", hash = "sha256:1201810a212460aaaa48eb6a766738740daf42c1a4f6aafecfb1525036929236"}, -] -django-debug-toolbar = [ - {file = "django-debug-toolbar-2.2.1.tar.gz", hash = "sha256:7aadab5240796ffe8e93cc7dfbe2f87a204054746ff7ff93cd6d4a0c3747c853"}, - {file = "django_debug_toolbar-2.2.1-py3-none-any.whl", hash = "sha256:7feaee934608f5cdd95432154be832fe30fda6c1249018191e2c27bc0b6a965e"}, -] -django-debug-toolbar-force = [ - {file = "django-debug-toolbar-force-0.1.8.tar.gz", hash = "sha256:10f0ec9ebbc0dd872ac810eb7d2033abb78c385fc90d8cf45c3adcc21dce23fb"}, - {file = "django_debug_toolbar_force-0.1.8-py2.py3-none-any.whl", hash = "sha256:0a47451d910ec248c154d4efdf86ff001a04530f5b64daef73280b317364d09a"}, -] -django-dotenv = [ - {file = "django-dotenv-1.4.2.tar.gz", hash = "sha256:3812bb0f4876cf31f902aad140f0645e120e51ee30eb7c40c22050f58a0e4adb"}, - {file = "django_dotenv-1.4.2-py2.py3-none-any.whl", hash = "sha256:a9b1b40a70bd321acd231926acedb9bd2c5e873e33a1873b34a7276d196a765e"}, -] -django-elasticsearch-dsl = [ - {file = "django-elasticsearch-dsl-7.2.2.tar.gz", hash = "sha256:811d3909b3387fd55c19d9bbcf0e9a9b234f085df3f8422d59e7519a5f733e0e"}, - {file = "django_elasticsearch_dsl-7.2.2-py2.py3-none-any.whl", hash = "sha256:3c58a254a6318b169eb904d41d802924b99ea8e53ddc2c596ebba90506cf47fa"}, -] -django-environ = [ - {file = "django-environ-0.4.5.tar.gz", hash = "sha256:6c9d87660142608f63ec7d5ce5564c49b603ea8ff25da595fd6098f6dc82afde"}, - {file = "django_environ-0.4.5-py2.py3-none-any.whl", hash = "sha256:c57b3c11ec1f319d9474e3e5a79134f40174b17c7cc024bbb2fad84646b120c4"}, -] -django-extensions = [ - {file = "django-extensions-2.2.9.tar.gz", hash = "sha256:2f81b618ba4d1b0e58603e25012e5c74f88a4b706e0022a3b21f24f0322a6ce6"}, - {file = "django_extensions-2.2.9-py2.py3-none-any.whl", hash = "sha256:b19182d101a441fe001c5753553a901e2ef3ff60e8fbbe38881eb4a61fdd17c4"}, -] -django-filter = [ - {file = "django-filter-22.1.tar.gz", hash = "sha256:ed473b76e84f7e83b2511bb2050c3efb36d135207d0128dfe3ae4b36e3594ba5"}, - {file = "django_filter-22.1-py3-none-any.whl", hash = "sha256:ed429e34760127e3520a67f415bec4c905d4649fbe45d0d6da37e6ff5e0287eb"}, -] -django-mysql = [ - {file = "django-mysql-3.12.0.tar.gz", hash = "sha256:2747964a1eeba38f98035c442ac5d32ebb602c460697f2da111c0f6d30245c69"}, - {file = "django_mysql-3.12.0-py3-none-any.whl", hash = "sha256:a4ff093b3f45832f95224da164e04b99e844a2047bff423036bcd2422988ebe4"}, -] -django-nine = [ - {file = "django-nine-0.2.7.tar.gz", hash = "sha256:304e0f83cea5a35359375fc919d00f9917b655c1d388244cbfc7363f59489177"}, - {file = "django_nine-0.2.7-py2.py3-none-any.whl", hash = "sha256:4d93208ca5bb4a63bf65cf098a82ee469127b04ebde698d72fe12d258b73c291"}, -] -django-redis = [ - {file = "django-redis-4.12.1.tar.gz", hash = "sha256:306589c7021e6468b2656edc89f62b8ba67e8d5a1c8877e2688042263daa7a63"}, - {file = "django_redis-4.12.1-py3-none-any.whl", hash = "sha256:1133b26b75baa3664164c3f44b9d5d133d1b8de45d94d79f38d1adc5b1d502e5"}, -] -django-s3-storage = [ - {file = "django-s3-storage-0.13.3.tar.gz", hash = "sha256:94fa108b272366f883355b108e6b67fc4f9e0e786523d44ac77c75505a511453"}, -] -django-ses = [ - {file = "django-ses-1.0.3.tar.gz", hash = "sha256:9c0a3e59e1e2424093820fa7cd519aa35f9ba978c26917a97a30c682449f0df6"}, - {file = "django_ses-1.0.3-py2.py3-none-any.whl", hash = "sha256:45f041acb9f2f8df85f3fddd63b04f1d381982bdc7730a3dc1f88e5795758bdd"}, -] -django-silk = [ - {file = "django-silk-4.4.1.tar.gz", hash = "sha256:5d4d3f1d4e3454fb073be8928293bc8af33c61cb32987783c8f93243ebf9705e"}, - {file = "django_silk-4.4.1-py3-none-any.whl", hash = "sha256:72f20020177e929ca5733dfebf226b4ce8559c5a7bdb1517daf9aaf7916b188a"}, -] -django-timezone-field = [ - {file = "django-timezone-field-4.2.3.tar.gz", hash = "sha256:5dd5bd9249382bef8847d3e7e4c32b7be182a4b538f354130d1252ed228892f8"}, - {file = "django_timezone_field-4.2.3-py3-none-any.whl", hash = "sha256:7552d2b0f145684b7de3fb5046101c7efd600cc6ba951b15c630fa1e1b83558e"}, -] -djangorestframework = [ - {file = "djangorestframework-3.14.0-py3-none-any.whl", hash = "sha256:eb63f58c9f218e1a7d064d17a70751f528ed4e1d35547fdade9aaf4cd103fd08"}, - {file = "djangorestframework-3.14.0.tar.gz", hash = "sha256:579a333e6256b09489cbe0a067e66abe55c6595d8926be6b99423786334350c8"}, -] -djangorestframework-filters = [ - {file = "djangorestframework-filters-1.0.0.dev2.tar.gz", hash = "sha256:ef84527e3427434d54228825b53a35098c8633c1e77b71d06b79597b749ea3f2"}, - {file = "djangorestframework_filters-1.0.0.dev2-py3-none-any.whl", hash = "sha256:7369998968d656707e013da8c0c3ef1f858b99c4caaa8e9ea40861e5d6ddecff"}, -] -drf-yasg = [ - {file = "drf-yasg-1.21.4.tar.gz", hash = "sha256:887c9f79e64f46aa48974234e61029b1bea6b12ea628a8fc8a3697589add1d3e"}, - {file = "drf_yasg-1.21.4-py3-none-any.whl", hash = "sha256:4a156d195fdccc51b40a227955588d982ca43c2e327927c7713bf967f5589913"}, -] -elasticsearch = [ - {file = "elasticsearch-7.17.8-py2.py3-none-any.whl", hash = "sha256:f511ea92e96db09b0e96b0de5fbbb7aa5c3740b0c571a364a2c3a1cc7ec06203"}, - {file = "elasticsearch-7.17.8.tar.gz", hash = "sha256:840adeb45a5ec9102a83f3cf481aae83a3775b75d6dd83a7310b04e44a5d0308"}, -] -elasticsearch-dsl = [ - {file = "elasticsearch-dsl-7.4.0.tar.gz", hash = "sha256:c4a7b93882918a413b63bed54018a1685d7410ffd8facbc860ee7fd57f214a6d"}, - {file = "elasticsearch_dsl-7.4.0-py2.py3-none-any.whl", hash = "sha256:046ea10820b94c075081b528b4526c5bc776bda4226d702f269a5f203232064b"}, -] -fake-useragent = [ - {file = "fake-useragent-0.1.14.tar.gz", hash = "sha256:470c509fc645a4fb2799a6cdf35982c3d27e57af04f601b3f37ac0b5e46c0cc7"}, - {file = "fake_useragent-0.1.14-py3-none-any.whl", hash = "sha256:f51e7c58e3733be152f69e2d0751d19274f0d36dd7a75e6706e503163bc61d46"}, -] -filelock = [ - {file = "filelock-3.9.0-py3-none-any.whl", hash = "sha256:f58d535af89bb9ad5cd4df046f741f8553a418c01a7856bf0d173bbc9f6bd16d"}, - {file = "filelock-3.9.0.tar.gz", hash = "sha256:7b319f24340b51f55a2bf7a12ac0755a9b03e718311dac567a0f4f7fabd2f5de"}, -] -firebase-admin = [ - {file = "firebase_admin-6.0.1-py3-none-any.whl", hash = "sha256:1f903d8c9e353af8027c3c237696d98f8e77ad4e38025528be0c522dee037317"}, - {file = "firebase_admin-6.0.1.tar.gz", hash = "sha256:7de3fc7b8bf7722cd8d127f7162d060c7ffd270e69794bcec2cc1d571fb80b45"}, -] -funcy = [ - {file = "funcy-1.17-py2.py3-none-any.whl", hash = "sha256:ba7af5e58bfc69321aaf860a1547f18d35e145706b95d1b3c966abc4f0b60309"}, - {file = "funcy-1.17.tar.gz", hash = "sha256:40b9b9a88141ae6a174df1a95861f2b82f2fdc17669080788b73a3ed9370e968"}, -] -future = [ - {file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"}, -] -google-api-core = [ - {file = "google-api-core-2.11.0.tar.gz", hash = "sha256:4b9bb5d5a380a0befa0573b302651b8a9a89262c1730e37bf423cec511804c22"}, - {file = "google_api_core-2.11.0-py3-none-any.whl", hash = "sha256:ce222e27b0de0d7bc63eb043b956996d6dccab14cc3b690aaea91c9cc99dc16e"}, -] -google-api-python-client = [ - {file = "google-api-python-client-2.71.0.tar.gz", hash = "sha256:9412ad3445518fa9d24d02c673a70b07c9d124990f44763cdf4f5304ca5b4d08"}, - {file = "google_api_python_client-2.71.0-py2.py3-none-any.whl", hash = "sha256:a4ea351db2bb2a9b1a7e96d8fa8de0fcbc31d9e237b724f4a07b243c2d63e9a4"}, -] -google-auth = [ - {file = "google-auth-2.15.0.tar.gz", hash = "sha256:72f12a6cfc968d754d7bdab369c5c5c16032106e52d32c6dfd8484e4c01a6d1f"}, - {file = "google_auth-2.15.0-py2.py3-none-any.whl", hash = "sha256:6897b93556d8d807ad70701bb89f000183aea366ca7ed94680828b37437a4994"}, -] -google-auth-httplib2 = [ - {file = "google-auth-httplib2-0.1.0.tar.gz", hash = "sha256:a07c39fd632becacd3f07718dfd6021bf396978f03ad3ce4321d060015cc30ac"}, - {file = "google_auth_httplib2-0.1.0-py2.py3-none-any.whl", hash = "sha256:31e49c36c6b5643b57e82617cb3e021e3e1d2df9da63af67252c02fa9c1f4a10"}, -] -google-cloud-core = [ - {file = "google-cloud-core-2.3.2.tar.gz", hash = "sha256:b9529ee7047fd8d4bf4a2182de619154240df17fbe60ead399078c1ae152af9a"}, - {file = "google_cloud_core-2.3.2-py2.py3-none-any.whl", hash = "sha256:8417acf6466be2fa85123441696c4badda48db314c607cf1e5d543fa8bdc22fe"}, -] -google-cloud-firestore = [ - {file = "google-cloud-firestore-2.7.3.tar.gz", hash = "sha256:ac7d9a22cb795c712af77157c657c3ade44e2169ccf299aad9438e83d4f69235"}, - {file = "google_cloud_firestore-2.7.3-py2.py3-none-any.whl", hash = "sha256:a5038f4d95e6ce324e7354f4222ea7ebb6dddad3eac710829fe859f59f98cc2b"}, -] -google-cloud-storage = [ - {file = "google-cloud-storage-2.7.0.tar.gz", hash = "sha256:1ac2d58d2d693cb1341ebc48659a3527be778d9e2d8989697a2746025928ff17"}, - {file = "google_cloud_storage-2.7.0-py2.py3-none-any.whl", hash = "sha256:f78a63525e72dd46406b255bbdf858a22c43d6bad8dc5bdeb7851a42967e95a1"}, -] -google-crc32c = [ - {file = "google-crc32c-1.5.0.tar.gz", hash = "sha256:89284716bc6a5a415d4eaa11b1726d2d60a0cd12aadf5439828353662ede9dd7"}, - {file = "google_crc32c-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:596d1f98fc70232fcb6590c439f43b350cb762fb5d61ce7b0e9db4539654cc13"}, - {file = "google_crc32c-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:be82c3c8cfb15b30f36768797a640e800513793d6ae1724aaaafe5bf86f8f346"}, - {file = "google_crc32c-1.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:461665ff58895f508e2866824a47bdee72497b091c730071f2b7575d5762ab65"}, - {file = "google_crc32c-1.5.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2096eddb4e7c7bdae4bd69ad364e55e07b8316653234a56552d9c988bd2d61b"}, - {file = "google_crc32c-1.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:116a7c3c616dd14a3de8c64a965828b197e5f2d121fedd2f8c5585c547e87b02"}, - {file = "google_crc32c-1.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5829b792bf5822fd0a6f6eb34c5f81dd074f01d570ed7f36aa101d6fc7a0a6e4"}, - {file = "google_crc32c-1.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:64e52e2b3970bd891309c113b54cf0e4384762c934d5ae56e283f9a0afcd953e"}, - {file = "google_crc32c-1.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:02ebb8bf46c13e36998aeaad1de9b48f4caf545e91d14041270d9dca767b780c"}, - {file = "google_crc32c-1.5.0-cp310-cp310-win32.whl", hash = "sha256:2e920d506ec85eb4ba50cd4228c2bec05642894d4c73c59b3a2fe20346bd00ee"}, - {file = "google_crc32c-1.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:07eb3c611ce363c51a933bf6bd7f8e3878a51d124acfc89452a75120bc436289"}, - {file = "google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:cae0274952c079886567f3f4f685bcaf5708f0a23a5f5216fdab71f81a6c0273"}, - {file = "google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1034d91442ead5a95b5aaef90dbfaca8633b0247d1e41621d1e9f9db88c36298"}, - {file = "google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c42c70cd1d362284289c6273adda4c6af8039a8ae12dc451dcd61cdabb8ab57"}, - {file = "google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8485b340a6a9e76c62a7dce3c98e5f102c9219f4cfbf896a00cf48caf078d438"}, - {file = "google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906"}, - {file = "google_crc32c-1.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f583edb943cf2e09c60441b910d6a20b4d9d626c75a36c8fcac01a6c96c01183"}, - {file = "google_crc32c-1.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:a1fd716e7a01f8e717490fbe2e431d2905ab8aa598b9b12f8d10abebb36b04dd"}, - {file = "google_crc32c-1.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:72218785ce41b9cfd2fc1d6a017dc1ff7acfc4c17d01053265c41a2c0cc39b8c"}, - {file = "google_crc32c-1.5.0-cp311-cp311-win32.whl", hash = "sha256:66741ef4ee08ea0b2cc3c86916ab66b6aef03768525627fd6a1b34968b4e3709"}, - {file = "google_crc32c-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:ba1eb1843304b1e5537e1fca632fa894d6f6deca8d6389636ee5b4797affb968"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:98cb4d057f285bd80d8778ebc4fde6b4d509ac3f331758fb1528b733215443ae"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd8536e902db7e365f49e7d9029283403974ccf29b13fc7028b97e2295b33556"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19e0a019d2c4dcc5e598cd4a4bc7b008546b0358bd322537c74ad47a5386884f"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02c65b9817512edc6a4ae7c7e987fea799d2e0ee40c53ec573a692bee24de876"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6ac08d24c1f16bd2bf5eca8eaf8304812f44af5cfe5062006ec676e7e1d50afc"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3359fc442a743e870f4588fcf5dcbc1bf929df1fad8fb9905cd94e5edb02e84c"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e986b206dae4476f41bcec1faa057851f3889503a70e1bdb2378d406223994a"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:de06adc872bcd8c2a4e0dc51250e9e65ef2ca91be023b9d13ebd67c2ba552e1e"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-win32.whl", hash = "sha256:d3515f198eaa2f0ed49f8819d5732d70698c3fa37384146079b3799b97667a94"}, - {file = "google_crc32c-1.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:67b741654b851abafb7bc625b6d1cdd520a379074e64b6a128e3b688c3c04740"}, - {file = "google_crc32c-1.5.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c02ec1c5856179f171e032a31d6f8bf84e5a75c45c33b2e20a3de353b266ebd8"}, - {file = "google_crc32c-1.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:edfedb64740750e1a3b16152620220f51d58ff1b4abceb339ca92e934775c27a"}, - {file = "google_crc32c-1.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84e6e8cd997930fc66d5bb4fde61e2b62ba19d62b7abd7a69920406f9ecca946"}, - {file = "google_crc32c-1.5.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:024894d9d3cfbc5943f8f230e23950cd4906b2fe004c72e29b209420a1e6b05a"}, - {file = "google_crc32c-1.5.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:998679bf62b7fb599d2878aa3ed06b9ce688b8974893e7223c60db155f26bd8d"}, - {file = "google_crc32c-1.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:83c681c526a3439b5cf94f7420471705bbf96262f49a6fe546a6db5f687a3d4a"}, - {file = "google_crc32c-1.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4c6fdd4fccbec90cc8a01fc00773fcd5fa28db683c116ee3cb35cd5da9ef6c37"}, - {file = "google_crc32c-1.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5ae44e10a8e3407dbe138984f21e536583f2bba1be9491239f942c2464ac0894"}, - {file = "google_crc32c-1.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:37933ec6e693e51a5b07505bd05de57eee12f3e8c32b07da7e73669398e6630a"}, - {file = "google_crc32c-1.5.0-cp38-cp38-win32.whl", hash = "sha256:fe70e325aa68fa4b5edf7d1a4b6f691eb04bbccac0ace68e34820d283b5f80d4"}, - {file = "google_crc32c-1.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:74dea7751d98034887dbd821b7aae3e1d36eda111d6ca36c206c44478035709c"}, - {file = "google_crc32c-1.5.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c6c777a480337ac14f38564ac88ae82d4cd238bf293f0a22295b66eb89ffced7"}, - {file = "google_crc32c-1.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:759ce4851a4bb15ecabae28f4d2e18983c244eddd767f560165563bf9aefbc8d"}, - {file = "google_crc32c-1.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f13cae8cc389a440def0c8c52057f37359014ccbc9dc1f0827936bcd367c6100"}, - {file = "google_crc32c-1.5.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e560628513ed34759456a416bf86b54b2476c59144a9138165c9a1575801d0d9"}, - {file = "google_crc32c-1.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1674e4307fa3024fc897ca774e9c7562c957af85df55efe2988ed9056dc4e57"}, - {file = "google_crc32c-1.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:278d2ed7c16cfc075c91378c4f47924c0625f5fc84b2d50d921b18b7975bd210"}, - {file = "google_crc32c-1.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d5280312b9af0976231f9e317c20e4a61cd2f9629b7bfea6a693d1878a264ebd"}, - {file = "google_crc32c-1.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8b87e1a59c38f275c0e3676fc2ab6d59eccecfd460be267ac360cc31f7bcde96"}, - {file = "google_crc32c-1.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7c074fece789b5034b9b1404a1f8208fc2d4c6ce9decdd16e8220c5a793e6f61"}, - {file = "google_crc32c-1.5.0-cp39-cp39-win32.whl", hash = "sha256:7f57f14606cd1dd0f0de396e1e53824c371e9544a822648cd76c034d209b559c"}, - {file = "google_crc32c-1.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:a2355cba1f4ad8b6988a4ca3feed5bff33f6af2d7f134852cf279c2aebfde541"}, - {file = "google_crc32c-1.5.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f314013e7dcd5cf45ab1945d92e713eec788166262ae8deb2cfacd53def27325"}, - {file = "google_crc32c-1.5.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b747a674c20a67343cb61d43fdd9207ce5da6a99f629c6e2541aa0e89215bcd"}, - {file = "google_crc32c-1.5.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8f24ed114432de109aa9fd317278518a5af2d31ac2ea6b952b2f7782b43da091"}, - {file = "google_crc32c-1.5.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8667b48e7a7ef66afba2c81e1094ef526388d35b873966d8a9a447974ed9178"}, - {file = "google_crc32c-1.5.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:1c7abdac90433b09bad6c43a43af253e688c9cfc1c86d332aed13f9a7c7f65e2"}, - {file = "google_crc32c-1.5.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6f998db4e71b645350b9ac28a2167e6632c239963ca9da411523bb439c5c514d"}, - {file = "google_crc32c-1.5.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c99616c853bb585301df6de07ca2cadad344fd1ada6d62bb30aec05219c45d2"}, - {file = "google_crc32c-1.5.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2ad40e31093a4af319dadf503b2467ccdc8f67c72e4bcba97f8c10cb078207b5"}, - {file = "google_crc32c-1.5.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd67cf24a553339d5062eff51013780a00d6f97a39ca062781d06b3a73b15462"}, - {file = "google_crc32c-1.5.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:398af5e3ba9cf768787eef45c803ff9614cc3e22a5b2f7d7ae116df8b11e3314"}, - {file = "google_crc32c-1.5.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b1f8133c9a275df5613a451e73f36c2aea4fe13c5c8997e22cf355ebd7bd0728"}, - {file = "google_crc32c-1.5.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9ba053c5f50430a3fcfd36f75aff9caeba0440b2d076afdb79a318d6ca245f88"}, - {file = "google_crc32c-1.5.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:272d3892a1e1a2dbc39cc5cde96834c236d5327e2122d3aaa19f6614531bb6eb"}, - {file = "google_crc32c-1.5.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:635f5d4dd18758a1fbd1049a8e8d2fee4ffed124462d837d1a02a0e009c3ab31"}, - {file = "google_crc32c-1.5.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c672d99a345849301784604bfeaeba4db0c7aae50b95be04dd651fd2a7310b93"}, -] -google-resumable-media = [ - {file = "google-resumable-media-2.4.0.tar.gz", hash = "sha256:8d5518502f92b9ecc84ac46779bd4f09694ecb3ba38a3e7ca737a86d15cbca1f"}, - {file = "google_resumable_media-2.4.0-py2.py3-none-any.whl", hash = "sha256:2aa004c16d295c8f6c33b2b4788ba59d366677c0a25ae7382436cb30f776deaa"}, -] -googleapis-common-protos = [ - {file = "googleapis-common-protos-1.57.1.tar.gz", hash = "sha256:e877f2f041b640b4888b6917dde4f44515ab938bf744c4dbc06f11f0e8ed56b5"}, - {file = "googleapis_common_protos-1.57.1-py2.py3-none-any.whl", hash = "sha256:2672d6b3a7b6188b70a5a4c70def7ddbb9000852dfbf49daf52fc7306c09db0c"}, -] -gprof2dot = [ - {file = "gprof2dot-2022.7.29-py2.py3-none-any.whl", hash = "sha256:f165b3851d3c52ee4915eb1bd6cca571e5759823c2cd0f71a79bda93c2dc85d6"}, - {file = "gprof2dot-2022.7.29.tar.gz", hash = "sha256:45b4d298bd36608fccf9511c3fd88a773f7a1abc04d6cd39445b11ba43133ec5"}, -] -greenlet = [ - {file = "greenlet-2.0.1-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:9ed358312e63bf683b9ef22c8e442ef6c5c02973f0c2a939ec1d7b50c974015c"}, - {file = "greenlet-2.0.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:4f09b0010e55bec3239278f642a8a506b91034f03a4fb28289a7d448a67f1515"}, - {file = "greenlet-2.0.1-cp27-cp27m-win32.whl", hash = "sha256:1407fe45246632d0ffb7a3f4a520ba4e6051fc2cbd61ba1f806900c27f47706a"}, - {file = "greenlet-2.0.1-cp27-cp27m-win_amd64.whl", hash = "sha256:3001d00eba6bbf084ae60ec7f4bb8ed375748f53aeaefaf2a37d9f0370558524"}, - {file = "greenlet-2.0.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:d566b82e92ff2e09dd6342df7e0eb4ff6275a3f08db284888dcd98134dbd4243"}, - {file = "greenlet-2.0.1-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:0722c9be0797f544a3ed212569ca3fe3d9d1a1b13942d10dd6f0e8601e484d26"}, - {file = "greenlet-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d37990425b4687ade27810e3b1a1c37825d242ebc275066cfee8cb6b8829ccd"}, - {file = "greenlet-2.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be35822f35f99dcc48152c9839d0171a06186f2d71ef76dc57fa556cc9bf6b45"}, - {file = "greenlet-2.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c140e7eb5ce47249668056edf3b7e9900c6a2e22fb0eaf0513f18a1b2c14e1da"}, - {file = "greenlet-2.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d21681f09e297a5adaa73060737e3aa1279a13ecdcfcc6ef66c292cb25125b2d"}, - {file = "greenlet-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fb412b7db83fe56847df9c47b6fe3f13911b06339c2aa02dcc09dce8bbf582cd"}, - {file = "greenlet-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:c6a08799e9e88052221adca55741bf106ec7ea0710bca635c208b751f0d5b617"}, - {file = "greenlet-2.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9e112e03d37987d7b90c1e98ba5e1b59e1645226d78d73282f45b326f7bddcb9"}, - {file = "greenlet-2.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56961cfca7da2fdd178f95ca407fa330c64f33289e1804b592a77d5593d9bd94"}, - {file = "greenlet-2.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:13ba6e8e326e2116c954074c994da14954982ba2795aebb881c07ac5d093a58a"}, - {file = "greenlet-2.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bf633a50cc93ed17e494015897361010fc08700d92676c87931d3ea464123ce"}, - {file = "greenlet-2.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9f2c221eecb7ead00b8e3ddb913c67f75cba078fd1d326053225a3f59d850d72"}, - {file = "greenlet-2.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:13ebf93c343dd8bd010cd98e617cb4c1c1f352a0cf2524c82d3814154116aa82"}, - {file = "greenlet-2.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:6f61d71bbc9b4a3de768371b210d906726535d6ca43506737682caa754b956cd"}, - {file = "greenlet-2.0.1-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:2d0bac0385d2b43a7bd1d651621a4e0f1380abc63d6fb1012213a401cbd5bf8f"}, - {file = "greenlet-2.0.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:f6327b6907b4cb72f650a5b7b1be23a2aab395017aa6f1adb13069d66360eb3f"}, - {file = "greenlet-2.0.1-cp35-cp35m-win32.whl", hash = "sha256:81b0ea3715bf6a848d6f7149d25bf018fd24554a4be01fcbbe3fdc78e890b955"}, - {file = "greenlet-2.0.1-cp35-cp35m-win_amd64.whl", hash = "sha256:38255a3f1e8942573b067510f9611fc9e38196077b0c8eb7a8c795e105f9ce77"}, - {file = "greenlet-2.0.1-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:04957dc96669be041e0c260964cfef4c77287f07c40452e61abe19d647505581"}, - {file = "greenlet-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:4aeaebcd91d9fee9aa768c1b39cb12214b30bf36d2b7370505a9f2165fedd8d9"}, - {file = "greenlet-2.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:974a39bdb8c90a85982cdb78a103a32e0b1be986d411303064b28a80611f6e51"}, - {file = "greenlet-2.0.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dca09dedf1bd8684767bc736cc20c97c29bc0c04c413e3276e0962cd7aeb148"}, - {file = "greenlet-2.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a4c0757db9bd08470ff8277791795e70d0bf035a011a528ee9a5ce9454b6cba2"}, - {file = "greenlet-2.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:5067920de254f1a2dee8d3d9d7e4e03718e8fd2d2d9db962c8c9fa781ae82a39"}, - {file = "greenlet-2.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:5a8e05057fab2a365c81abc696cb753da7549d20266e8511eb6c9d9f72fe3e92"}, - {file = "greenlet-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:3d75b8d013086b08e801fbbb896f7d5c9e6ccd44f13a9241d2bf7c0df9eda928"}, - {file = "greenlet-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:097e3dae69321e9100202fc62977f687454cd0ea147d0fd5a766e57450c569fd"}, - {file = "greenlet-2.0.1-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:cb242fc2cda5a307a7698c93173d3627a2a90d00507bccf5bc228851e8304963"}, - {file = "greenlet-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:72b00a8e7c25dcea5946692a2485b1a0c0661ed93ecfedfa9b6687bd89a24ef5"}, - {file = "greenlet-2.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5b0ff9878333823226d270417f24f4d06f235cb3e54d1103b71ea537a6a86ce"}, - {file = "greenlet-2.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be9e0fb2ada7e5124f5282d6381903183ecc73ea019568d6d63d33f25b2a9000"}, - {file = "greenlet-2.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b493db84d124805865adc587532ebad30efa68f79ad68f11b336e0a51ec86c2"}, - {file = "greenlet-2.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0459d94f73265744fee4c2d5ec44c6f34aa8a31017e6e9de770f7bcf29710be9"}, - {file = "greenlet-2.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a20d33124935d27b80e6fdacbd34205732660e0a1d35d8b10b3328179a2b51a1"}, - {file = "greenlet-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:ea688d11707d30e212e0110a1aac7f7f3f542a259235d396f88be68b649e47d1"}, - {file = "greenlet-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:afe07421c969e259e9403c3bb658968702bc3b78ec0b6fde3ae1e73440529c23"}, - {file = "greenlet-2.0.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:cd4ccc364cf75d1422e66e247e52a93da6a9b73cefa8cad696f3cbbb75af179d"}, - {file = "greenlet-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:4c8b1c43e75c42a6cafcc71defa9e01ead39ae80bd733a2608b297412beede68"}, - {file = "greenlet-2.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:659f167f419a4609bc0516fb18ea69ed39dbb25594934bd2dd4d0401660e8a1e"}, - {file = "greenlet-2.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:356e4519d4dfa766d50ecc498544b44c0249b6de66426041d7f8b751de4d6b48"}, - {file = "greenlet-2.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:811e1d37d60b47cb8126e0a929b58c046251f28117cb16fcd371eed61f66b764"}, - {file = "greenlet-2.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d38ffd0e81ba8ef347d2be0772e899c289b59ff150ebbbbe05dc61b1246eb4e0"}, - {file = "greenlet-2.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0109af1138afbfb8ae647e31a2b1ab030f58b21dd8528c27beaeb0093b7938a9"}, - {file = "greenlet-2.0.1-cp38-cp38-win32.whl", hash = "sha256:88c8d517e78acdf7df8a2134a3c4b964415b575d2840a2746ddb1cc6175f8608"}, - {file = "greenlet-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:d6ee1aa7ab36475035eb48c01efae87d37936a8173fc4d7b10bb02c2d75dd8f6"}, - {file = "greenlet-2.0.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:b1992ba9d4780d9af9726bbcef6a1db12d9ab1ccc35e5773685a24b7fb2758eb"}, - {file = "greenlet-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:b5e83e4de81dcc9425598d9469a624826a0b1211380ac444c7c791d4a2137c19"}, - {file = "greenlet-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:505138d4fa69462447a562a7c2ef723c6025ba12ac04478bc1ce2fcc279a2db5"}, - {file = "greenlet-2.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cce1e90dd302f45716a7715517c6aa0468af0bf38e814ad4eab58e88fc09f7f7"}, - {file = "greenlet-2.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e9744c657d896c7b580455e739899e492a4a452e2dd4d2b3e459f6b244a638d"}, - {file = "greenlet-2.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:662e8f7cad915ba75d8017b3e601afc01ef20deeeabf281bd00369de196d7726"}, - {file = "greenlet-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:41b825d65f31e394b523c84db84f9383a2f7eefc13d987f308f4663794d2687e"}, - {file = "greenlet-2.0.1-cp39-cp39-win32.whl", hash = "sha256:db38f80540083ea33bdab614a9d28bcec4b54daa5aff1668d7827a9fc769ae0a"}, - {file = "greenlet-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:b23d2a46d53210b498e5b701a1913697671988f4bf8e10f935433f6e7c332fb6"}, - {file = "greenlet-2.0.1.tar.gz", hash = "sha256:42e602564460da0e8ee67cb6d7236363ee5e131aa15943b6670e44e5c2ed0f67"}, -] -grpcio = [ - {file = "grpcio-1.51.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:cc2bece1737b44d878cc1510ea04469a8073dbbcdd762175168937ae4742dfb3"}, - {file = "grpcio-1.51.1-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:e223a9793522680beae44671b9ed8f6d25bbe5ddf8887e66aebad5e0686049ef"}, - {file = "grpcio-1.51.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:24ac1154c4b2ab4a0c5326a76161547e70664cd2c39ba75f00fc8a2170964ea2"}, - {file = "grpcio-1.51.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4ef09f8997c4be5f3504cefa6b5c6cc3cf648274ce3cede84d4342a35d76db6"}, - {file = "grpcio-1.51.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8a0b77e992c64880e6efbe0086fe54dfc0bbd56f72a92d9e48264dcd2a3db98"}, - {file = "grpcio-1.51.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:eacad297ea60c72dd280d3353d93fb1dcca952ec11de6bb3c49d12a572ba31dd"}, - {file = "grpcio-1.51.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:16c71740640ba3a882f50b01bf58154681d44b51f09a5728180a8fdc66c67bd5"}, - {file = "grpcio-1.51.1-cp310-cp310-win32.whl", hash = "sha256:29cb97d41a4ead83b7bcad23bdb25bdd170b1e2cba16db6d3acbb090bc2de43c"}, - {file = "grpcio-1.51.1-cp310-cp310-win_amd64.whl", hash = "sha256:9ff42c5620b4e4530609e11afefa4a62ca91fa0abb045a8957e509ef84e54d30"}, - {file = "grpcio-1.51.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:bc59f7ba87972ab236f8669d8ca7400f02a0eadf273ca00e02af64d588046f02"}, - {file = "grpcio-1.51.1-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:3c2b3842dcf870912da31a503454a33a697392f60c5e2697c91d133130c2c85d"}, - {file = "grpcio-1.51.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22b011674090594f1f3245960ced7386f6af35485a38901f8afee8ad01541dbd"}, - {file = "grpcio-1.51.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49d680356a975d9c66a678eb2dde192d5dc427a7994fb977363634e781614f7c"}, - {file = "grpcio-1.51.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:094e64236253590d9d4075665c77b329d707b6fca864dd62b144255e199b4f87"}, - {file = "grpcio-1.51.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:257478300735ce3c98d65a930bbda3db172bd4e00968ba743e6a1154ea6edf10"}, - {file = "grpcio-1.51.1-cp311-cp311-win32.whl", hash = "sha256:5a6ebcdef0ef12005d56d38be30f5156d1cb3373b52e96f147f4a24b0ddb3a9d"}, - {file = "grpcio-1.51.1-cp311-cp311-win_amd64.whl", hash = "sha256:3f9b0023c2c92bebd1be72cdfca23004ea748be1813a66d684d49d67d836adde"}, - {file = "grpcio-1.51.1-cp37-cp37m-linux_armv7l.whl", hash = "sha256:cd3baccea2bc5c38aeb14e5b00167bd4e2373a373a5e4d8d850bd193edad150c"}, - {file = "grpcio-1.51.1-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:17ec9b13cec4a286b9e606b48191e560ca2f3bbdf3986f91e480a95d1582e1a7"}, - {file = "grpcio-1.51.1-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:fbdbe9a849854fe484c00823f45b7baab159bdd4a46075302281998cb8719df5"}, - {file = "grpcio-1.51.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:31bb6bc7ff145e2771c9baf612f4b9ebbc9605ccdc5f3ff3d5553de7fc0e0d79"}, - {file = "grpcio-1.51.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e473525c28251558337b5c1ad3fa969511e42304524a4e404065e165b084c9e4"}, - {file = "grpcio-1.51.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:6f0b89967ee11f2b654c23b27086d88ad7bf08c0b3c2a280362f28c3698b2896"}, - {file = "grpcio-1.51.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:7942b32a291421460d6a07883033e392167d30724aa84987e6956cd15f1a21b9"}, - {file = "grpcio-1.51.1-cp37-cp37m-win32.whl", hash = "sha256:f96ace1540223f26fbe7c4ebbf8a98e3929a6aa0290c8033d12526847b291c0f"}, - {file = "grpcio-1.51.1-cp37-cp37m-win_amd64.whl", hash = "sha256:f1fec3abaf274cdb85bf3878167cfde5ad4a4d97c68421afda95174de85ba813"}, - {file = "grpcio-1.51.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:0e1a9e1b4a23808f1132aa35f968cd8e659f60af3ffd6fb00bcf9a65e7db279f"}, - {file = "grpcio-1.51.1-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:6df3b63538c362312bc5fa95fb965069c65c3ea91d7ce78ad9c47cab57226f54"}, - {file = "grpcio-1.51.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:172405ca6bdfedd6054c74c62085946e45ad4d9cec9f3c42b4c9a02546c4c7e9"}, - {file = "grpcio-1.51.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:506b9b7a4cede87d7219bfb31014d7b471cfc77157da9e820a737ec1ea4b0663"}, - {file = "grpcio-1.51.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0fb93051331acbb75b49a2a0fd9239c6ba9528f6bdc1dd400ad1cb66cf864292"}, - {file = "grpcio-1.51.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5dca372268c6ab6372d37d6b9f9343e7e5b4bc09779f819f9470cd88b2ece3c3"}, - {file = "grpcio-1.51.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:471d39d3370ca923a316d49c8aac66356cea708a11e647e3bdc3d0b5de4f0a40"}, - {file = "grpcio-1.51.1-cp38-cp38-win32.whl", hash = "sha256:75e29a90dc319f0ad4d87ba6d20083615a00d8276b51512e04ad7452b5c23b04"}, - {file = "grpcio-1.51.1-cp38-cp38-win_amd64.whl", hash = "sha256:f1158bccbb919da42544a4d3af5d9296a3358539ffa01018307337365a9a0c64"}, - {file = "grpcio-1.51.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:59dffade859f157bcc55243714d57b286da6ae16469bf1ac0614d281b5f49b67"}, - {file = "grpcio-1.51.1-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:dad6533411d033b77f5369eafe87af8583178efd4039c41d7515d3336c53b4f1"}, - {file = "grpcio-1.51.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:4c4423ea38a7825b8fed8934d6d9aeebdf646c97e3c608c3b0bcf23616f33877"}, - {file = "grpcio-1.51.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0dc5354e38e5adf2498312f7241b14c7ce3484eefa0082db4297189dcbe272e6"}, - {file = "grpcio-1.51.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97d67983189e2e45550eac194d6234fc38b8c3b5396c153821f2d906ed46e0ce"}, - {file = "grpcio-1.51.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:538d981818e49b6ed1e9c8d5e5adf29f71c4e334e7d459bf47e9b7abb3c30e09"}, - {file = "grpcio-1.51.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9235dcd5144a83f9ca6f431bd0eccc46b90e2c22fe27b7f7d77cabb2fb515595"}, - {file = "grpcio-1.51.1-cp39-cp39-win32.whl", hash = "sha256:aacb54f7789ede5cbf1d007637f792d3e87f1c9841f57dd51abf89337d1b8472"}, - {file = "grpcio-1.51.1-cp39-cp39-win_amd64.whl", hash = "sha256:2b170eaf51518275c9b6b22ccb59450537c5a8555326fd96ff7391b5dd75303c"}, - {file = "grpcio-1.51.1.tar.gz", hash = "sha256:e6dfc2b6567b1c261739b43d9c59d201c1b89e017afd9e684d85aa7a186c9f7a"}, -] -grpcio-status = [ - {file = "grpcio-status-1.51.1.tar.gz", hash = "sha256:ac2617a3095935ebd785e2228958f24b10a0d527a0c9eb5a0863c784f648a816"}, - {file = "grpcio_status-1.51.1-py3-none-any.whl", hash = "sha256:a52cbdc4b18f325bfc13d319ae7c7ae7a0fee07f3d9a005504d6097896d7a495"}, -] -gunicorn = [ - {file = "gunicorn-19.10.0-py2.py3-none-any.whl", hash = "sha256:c3930fe8de6778ab5ea716cab432ae6335fa9f03b3f2c3e02529214c476f4bcb"}, - {file = "gunicorn-19.10.0.tar.gz", hash = "sha256:f9de24e358b841567063629cd0a656b26792a41e23a24d0dcb40224fc3940081"}, -] -html5lib = [ - {file = "html5lib-1.1-py2.py3-none-any.whl", hash = "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d"}, - {file = "html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f"}, -] -httplib2 = [ - {file = "httplib2-0.21.0-py3-none-any.whl", hash = "sha256:987c8bb3eb82d3fa60c68699510a692aa2ad9c4bd4f123e51dfb1488c14cdd01"}, - {file = "httplib2-0.21.0.tar.gz", hash = "sha256:fc144f091c7286b82bec71bdbd9b27323ba709cc612568d3000893bfd9cb4b34"}, -] -identify = [ - {file = "identify-2.5.12-py2.py3-none-any.whl", hash = "sha256:e8a400c3062d980243d27ce10455a52832205649bbcaf27ffddb3dfaaf477bad"}, - {file = "identify-2.5.12.tar.gz", hash = "sha256:0bc96b09c838310b6fcfcc61f78a981ea07f94836ef6ef553da5bb5d4745d662"}, -] -idna = [ - {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, - {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, -] -importlib-metadata = [ - {file = "importlib_metadata-4.8.1-py3-none-any.whl", hash = "sha256:b618b6d2d5ffa2f16add5697cf57a46c76a56229b0ed1c438322e4e95645bd15"}, - {file = "importlib_metadata-4.8.1.tar.gz", hash = "sha256:f284b3e11256ad1e5d03ab86bb2ccd6f5339688ff17a4d797a0fe7df326f23b1"}, -] -inflection = [ - {file = "inflection-0.5.1-py2.py3-none-any.whl", hash = "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2"}, - {file = "inflection-0.5.1.tar.gz", hash = "sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417"}, -] -isort = [ - {file = "isort-5.11.4-py3-none-any.whl", hash = "sha256:c033fd0edb91000a7f09527fe5c75321878f98322a77ddcc81adbd83724afb7b"}, - {file = "isort-5.11.4.tar.gz", hash = "sha256:6db30c5ded9815d813932c04c2f85a360bcdd35fed496f4d8f35495ef0a261b6"}, -] -itypes = [ - {file = "itypes-1.2.0-py2.py3-none-any.whl", hash = "sha256:03da6872ca89d29aef62773672b2d408f490f80db48b23079a4b194c86dd04c6"}, - {file = "itypes-1.2.0.tar.gz", hash = "sha256:af886f129dea4a2a1e3d36595a2d139589e4dd287f5cab0b40e799ee81570ff1"}, -] -jinja2 = [ - {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, - {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, -] -jinxed = [ - {file = "jinxed-1.2.0-py2.py3-none-any.whl", hash = "sha256:cfc2b2e4e3b4326954d546ba6d6b9a7a796ddcb0aef8d03161d005177eb0d48b"}, - {file = "jinxed-1.2.0.tar.gz", hash = "sha256:032acda92d5c57cd216033cbbd53de731e6ed50deb63eb4781336ca55f72cda5"}, -] -jmespath = [ - {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"}, - {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, -] -kombu = [ - {file = "kombu-4.6.11-py2.py3-none-any.whl", hash = "sha256:be48cdffb54a2194d93ad6533d73f69408486483d189fe9f5990ee24255b0e0a"}, - {file = "kombu-4.6.11.tar.gz", hash = "sha256:ca1b45faac8c0b18493d02a8571792f3c40291cf2bcf1f55afed3d8f3aa7ba74"}, -] -lazy-object-proxy = [ - {file = "lazy-object-proxy-1.9.0.tar.gz", hash = "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-win32.whl", hash = "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-win32.whl", hash = "sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win32.whl", hash = "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-win32.whl", hash = "sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-win32.whl", hash = "sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f"}, -] -lxml = [ - {file = "lxml-4.9.2-cp27-cp27m-macosx_10_15_x86_64.whl", hash = "sha256:76cf573e5a365e790396a5cc2b909812633409306c6531a6877c59061e42c4f2"}, - {file = "lxml-4.9.2-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b1f42b6921d0e81b1bcb5e395bc091a70f41c4d4e55ba99c6da2b31626c44892"}, - {file = "lxml-4.9.2-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:9f102706d0ca011de571de32c3247c6476b55bb6bc65a20f682f000b07a4852a"}, - {file = "lxml-4.9.2-cp27-cp27m-win32.whl", hash = "sha256:8d0b4612b66ff5d62d03bcaa043bb018f74dfea51184e53f067e6fdcba4bd8de"}, - {file = "lxml-4.9.2-cp27-cp27m-win_amd64.whl", hash = "sha256:4c8f293f14abc8fd3e8e01c5bd86e6ed0b6ef71936ded5bf10fe7a5efefbaca3"}, - {file = "lxml-4.9.2-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2899456259589aa38bfb018c364d6ae7b53c5c22d8e27d0ec7609c2a1ff78b50"}, - {file = "lxml-4.9.2-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6749649eecd6a9871cae297bffa4ee76f90b4504a2a2ab528d9ebe912b101975"}, - {file = "lxml-4.9.2-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:a08cff61517ee26cb56f1e949cca38caabe9ea9fbb4b1e10a805dc39844b7d5c"}, - {file = "lxml-4.9.2-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:85cabf64adec449132e55616e7ca3e1000ab449d1d0f9d7f83146ed5bdcb6d8a"}, - {file = "lxml-4.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:8340225bd5e7a701c0fa98284c849c9b9fc9238abf53a0ebd90900f25d39a4e4"}, - {file = "lxml-4.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:1ab8f1f932e8f82355e75dda5413a57612c6ea448069d4fb2e217e9a4bed13d4"}, - {file = "lxml-4.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:699a9af7dffaf67deeae27b2112aa06b41c370d5e7633e0ee0aea2e0b6c211f7"}, - {file = "lxml-4.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b9cc34af337a97d470040f99ba4282f6e6bac88407d021688a5d585e44a23184"}, - {file = "lxml-4.9.2-cp310-cp310-win32.whl", hash = "sha256:d02a5399126a53492415d4906ab0ad0375a5456cc05c3fc0fc4ca11771745cda"}, - {file = "lxml-4.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:a38486985ca49cfa574a507e7a2215c0c780fd1778bb6290c21193b7211702ab"}, - {file = "lxml-4.9.2-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:c83203addf554215463b59f6399835201999b5e48019dc17f182ed5ad87205c9"}, - {file = "lxml-4.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:2a87fa548561d2f4643c99cd13131acb607ddabb70682dcf1dff5f71f781a4bf"}, - {file = "lxml-4.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:d6b430a9938a5a5d85fc107d852262ddcd48602c120e3dbb02137c83d212b380"}, - {file = "lxml-4.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3efea981d956a6f7173b4659849f55081867cf897e719f57383698af6f618a92"}, - {file = "lxml-4.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:df0623dcf9668ad0445e0558a21211d4e9a149ea8f5666917c8eeec515f0a6d1"}, - {file = "lxml-4.9.2-cp311-cp311-win32.whl", hash = "sha256:da248f93f0418a9e9d94b0080d7ebc407a9a5e6d0b57bb30db9b5cc28de1ad33"}, - {file = "lxml-4.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:3818b8e2c4b5148567e1b09ce739006acfaa44ce3156f8cbbc11062994b8e8dd"}, - {file = "lxml-4.9.2-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ca989b91cf3a3ba28930a9fc1e9aeafc2a395448641df1f387a2d394638943b0"}, - {file = "lxml-4.9.2-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:822068f85e12a6e292803e112ab876bc03ed1f03dddb80154c395f891ca6b31e"}, - {file = "lxml-4.9.2-cp35-cp35m-win32.whl", hash = "sha256:be7292c55101e22f2a3d4d8913944cbea71eea90792bf914add27454a13905df"}, - {file = "lxml-4.9.2-cp35-cp35m-win_amd64.whl", hash = "sha256:998c7c41910666d2976928c38ea96a70d1aa43be6fe502f21a651e17483a43c5"}, - {file = "lxml-4.9.2-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:b26a29f0b7fc6f0897f043ca366142d2b609dc60756ee6e4e90b5f762c6adc53"}, - {file = "lxml-4.9.2-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:ab323679b8b3030000f2be63e22cdeea5b47ee0abd2d6a1dc0c8103ddaa56cd7"}, - {file = "lxml-4.9.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:689bb688a1db722485e4610a503e3e9210dcc20c520b45ac8f7533c837be76fe"}, - {file = "lxml-4.9.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:f49e52d174375a7def9915c9f06ec4e569d235ad428f70751765f48d5926678c"}, - {file = "lxml-4.9.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:36c3c175d34652a35475a73762b545f4527aec044910a651d2bf50de9c3352b1"}, - {file = "lxml-4.9.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a35f8b7fa99f90dd2f5dc5a9fa12332642f087a7641289ca6c40d6e1a2637d8e"}, - {file = "lxml-4.9.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:58bfa3aa19ca4c0f28c5dde0ff56c520fbac6f0daf4fac66ed4c8d2fb7f22e74"}, - {file = "lxml-4.9.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc718cd47b765e790eecb74d044cc8d37d58562f6c314ee9484df26276d36a38"}, - {file = "lxml-4.9.2-cp36-cp36m-win32.whl", hash = "sha256:d5bf6545cd27aaa8a13033ce56354ed9e25ab0e4ac3b5392b763d8d04b08e0c5"}, - {file = "lxml-4.9.2-cp36-cp36m-win_amd64.whl", hash = "sha256:3ab9fa9d6dc2a7f29d7affdf3edebf6ece6fb28a6d80b14c3b2fb9d39b9322c3"}, - {file = "lxml-4.9.2-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:05ca3f6abf5cf78fe053da9b1166e062ade3fa5d4f92b4ed688127ea7d7b1d03"}, - {file = "lxml-4.9.2-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:a5da296eb617d18e497bcf0a5c528f5d3b18dadb3619fbdadf4ed2356ef8d941"}, - {file = "lxml-4.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:04876580c050a8c5341d706dd464ff04fd597095cc8c023252566a8826505726"}, - {file = "lxml-4.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:c9ec3eaf616d67db0764b3bb983962b4f385a1f08304fd30c7283954e6a7869b"}, - {file = "lxml-4.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2a29ba94d065945944016b6b74e538bdb1751a1db6ffb80c9d3c2e40d6fa9894"}, - {file = "lxml-4.9.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a82d05da00a58b8e4c0008edbc8a4b6ec5a4bc1e2ee0fb6ed157cf634ed7fa45"}, - {file = "lxml-4.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:223f4232855ade399bd409331e6ca70fb5578efef22cf4069a6090acc0f53c0e"}, - {file = "lxml-4.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d17bc7c2ccf49c478c5bdd447594e82692c74222698cfc9b5daae7ae7e90743b"}, - {file = "lxml-4.9.2-cp37-cp37m-win32.whl", hash = "sha256:b64d891da92e232c36976c80ed7ebb383e3f148489796d8d31a5b6a677825efe"}, - {file = "lxml-4.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:a0a336d6d3e8b234a3aae3c674873d8f0e720b76bc1d9416866c41cd9500ffb9"}, - {file = "lxml-4.9.2-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:da4dd7c9c50c059aba52b3524f84d7de956f7fef88f0bafcf4ad7dde94a064e8"}, - {file = "lxml-4.9.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:821b7f59b99551c69c85a6039c65b75f5683bdc63270fec660f75da67469ca24"}, - {file = "lxml-4.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:e5168986b90a8d1f2f9dc1b841467c74221bd752537b99761a93d2d981e04889"}, - {file = "lxml-4.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:8e20cb5a47247e383cf4ff523205060991021233ebd6f924bca927fcf25cf86f"}, - {file = "lxml-4.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:13598ecfbd2e86ea7ae45ec28a2a54fb87ee9b9fdb0f6d343297d8e548392c03"}, - {file = "lxml-4.9.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:880bbbcbe2fca64e2f4d8e04db47bcdf504936fa2b33933efd945e1b429bea8c"}, - {file = "lxml-4.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7d2278d59425777cfcb19735018d897ca8303abe67cc735f9f97177ceff8027f"}, - {file = "lxml-4.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5344a43228767f53a9df6e5b253f8cdca7dfc7b7aeae52551958192f56d98457"}, - {file = "lxml-4.9.2-cp38-cp38-win32.whl", hash = "sha256:925073b2fe14ab9b87e73f9a5fde6ce6392da430f3004d8b72cc86f746f5163b"}, - {file = "lxml-4.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:9b22c5c66f67ae00c0199f6055705bc3eb3fcb08d03d2ec4059a2b1b25ed48d7"}, - {file = "lxml-4.9.2-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:5f50a1c177e2fa3ee0667a5ab79fdc6b23086bc8b589d90b93b4bd17eb0e64d1"}, - {file = "lxml-4.9.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:090c6543d3696cbe15b4ac6e175e576bcc3f1ccfbba970061b7300b0c15a2140"}, - {file = "lxml-4.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:63da2ccc0857c311d764e7d3d90f429c252e83b52d1f8f1d1fe55be26827d1f4"}, - {file = "lxml-4.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:5b4545b8a40478183ac06c073e81a5ce4cf01bf1734962577cf2bb569a5b3bbf"}, - {file = "lxml-4.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2e430cd2824f05f2d4f687701144556646bae8f249fd60aa1e4c768ba7018947"}, - {file = "lxml-4.9.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6804daeb7ef69e7b36f76caddb85cccd63d0c56dedb47555d2fc969e2af6a1a5"}, - {file = "lxml-4.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a6e441a86553c310258aca15d1c05903aaf4965b23f3bc2d55f200804e005ee5"}, - {file = "lxml-4.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ca34efc80a29351897e18888c71c6aca4a359247c87e0b1c7ada14f0ab0c0fb2"}, - {file = "lxml-4.9.2-cp39-cp39-win32.whl", hash = "sha256:6b418afe5df18233fc6b6093deb82a32895b6bb0b1155c2cdb05203f583053f1"}, - {file = "lxml-4.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:f1496ea22ca2c830cbcbd473de8f114a320da308438ae65abad6bab7867fe38f"}, - {file = "lxml-4.9.2-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:b264171e3143d842ded311b7dccd46ff9ef34247129ff5bf5066123c55c2431c"}, - {file = "lxml-4.9.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0dc313ef231edf866912e9d8f5a042ddab56c752619e92dfd3a2c277e6a7299a"}, - {file = "lxml-4.9.2-pp38-pypy38_pp73-macosx_10_15_x86_64.whl", hash = "sha256:16efd54337136e8cd72fb9485c368d91d77a47ee2d42b057564aae201257d419"}, - {file = "lxml-4.9.2-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:0f2b1e0d79180f344ff9f321327b005ca043a50ece8713de61d1cb383fb8ac05"}, - {file = "lxml-4.9.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:7b770ed79542ed52c519119473898198761d78beb24b107acf3ad65deae61f1f"}, - {file = "lxml-4.9.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:efa29c2fe6b4fdd32e8ef81c1528506895eca86e1d8c4657fda04c9b3786ddf9"}, - {file = "lxml-4.9.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7e91ee82f4199af8c43d8158024cbdff3d931df350252288f0d4ce656df7f3b5"}, - {file = "lxml-4.9.2-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:b23e19989c355ca854276178a0463951a653309fb8e57ce674497f2d9f208746"}, - {file = "lxml-4.9.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:01d36c05f4afb8f7c20fd9ed5badca32a2029b93b1750f571ccc0b142531caf7"}, - {file = "lxml-4.9.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7b515674acfdcadb0eb5d00d8a709868173acece5cb0be3dd165950cbfdf5409"}, - {file = "lxml-4.9.2.tar.gz", hash = "sha256:2455cfaeb7ac70338b3257f41e21f0724f4b5b0c0e7702da67ee6c3640835b67"}, -] -markupsafe = [ - {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"}, - {file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"}, - {file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"}, - {file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"}, - {file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"}, - {file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"}, -] -mccabe = [ - {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, - {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, -] -more-itertools = [ - {file = "more-itertools-9.0.0.tar.gz", hash = "sha256:5a6257e40878ef0520b1803990e3e22303a41b5714006c32a3fd8304b26ea1ab"}, - {file = "more_itertools-9.0.0-py3-none-any.whl", hash = "sha256:250e83d7e81d0c87ca6bd942e6aeab8cc9daa6096d12c5308f3f92fa5e5c1f41"}, -] -msgpack = [ - {file = "msgpack-1.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4ab251d229d10498e9a2f3b1e68ef64cb393394ec477e3370c457f9430ce9250"}, - {file = "msgpack-1.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:112b0f93202d7c0fef0b7810d465fde23c746a2d482e1e2de2aafd2ce1492c88"}, - {file = "msgpack-1.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:002b5c72b6cd9b4bafd790f364b8480e859b4712e91f43014fe01e4f957b8467"}, - {file = "msgpack-1.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35bc0faa494b0f1d851fd29129b2575b2e26d41d177caacd4206d81502d4c6a6"}, - {file = "msgpack-1.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4733359808c56d5d7756628736061c432ded018e7a1dff2d35a02439043321aa"}, - {file = "msgpack-1.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb514ad14edf07a1dbe63761fd30f89ae79b42625731e1ccf5e1f1092950eaa6"}, - {file = "msgpack-1.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c23080fdeec4716aede32b4e0ef7e213c7b1093eede9ee010949f2a418ced6ba"}, - {file = "msgpack-1.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:49565b0e3d7896d9ea71d9095df15b7f75a035c49be733051c34762ca95bbf7e"}, - {file = "msgpack-1.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:aca0f1644d6b5a73eb3e74d4d64d5d8c6c3d577e753a04c9e9c87d07692c58db"}, - {file = "msgpack-1.0.4-cp310-cp310-win32.whl", hash = "sha256:0dfe3947db5fb9ce52aaea6ca28112a170db9eae75adf9339a1aec434dc954ef"}, - {file = "msgpack-1.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dea20515f660aa6b7e964433b1808d098dcfcabbebeaaad240d11f909298075"}, - {file = "msgpack-1.0.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e83f80a7fec1a62cf4e6c9a660e39c7f878f603737a0cdac8c13131d11d97f52"}, - {file = "msgpack-1.0.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c11a48cf5e59026ad7cb0dc29e29a01b5a66a3e333dc11c04f7e991fc5510a9"}, - {file = "msgpack-1.0.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1276e8f34e139aeff1c77a3cefb295598b504ac5314d32c8c3d54d24fadb94c9"}, - {file = "msgpack-1.0.4-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c9566f2c39ccced0a38d37c26cc3570983b97833c365a6044edef3574a00c08"}, - {file = "msgpack-1.0.4-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:fcb8a47f43acc113e24e910399376f7277cf8508b27e5b88499f053de6b115a8"}, - {file = "msgpack-1.0.4-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:76ee788122de3a68a02ed6f3a16bbcd97bc7c2e39bd4d94be2f1821e7c4a64e6"}, - {file = "msgpack-1.0.4-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:0a68d3ac0104e2d3510de90a1091720157c319ceeb90d74f7b5295a6bee51bae"}, - {file = "msgpack-1.0.4-cp36-cp36m-win32.whl", hash = "sha256:85f279d88d8e833ec015650fd15ae5eddce0791e1e8a59165318f371158efec6"}, - {file = "msgpack-1.0.4-cp36-cp36m-win_amd64.whl", hash = "sha256:c1683841cd4fa45ac427c18854c3ec3cd9b681694caf5bff04edb9387602d661"}, - {file = "msgpack-1.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a75dfb03f8b06f4ab093dafe3ddcc2d633259e6c3f74bb1b01996f5d8aa5868c"}, - {file = "msgpack-1.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9667bdfdf523c40d2511f0e98a6c9d3603be6b371ae9a238b7ef2dc4e7a427b0"}, - {file = "msgpack-1.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11184bc7e56fd74c00ead4f9cc9a3091d62ecb96e97653add7a879a14b003227"}, - {file = "msgpack-1.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ac5bd7901487c4a1dd51a8c58f2632b15d838d07ceedaa5e4c080f7190925bff"}, - {file = "msgpack-1.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1e91d641d2bfe91ba4c52039adc5bccf27c335356055825c7f88742c8bb900dd"}, - {file = "msgpack-1.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2a2df1b55a78eb5f5b7d2a4bb221cd8363913830145fad05374a80bf0877cb1e"}, - {file = "msgpack-1.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:545e3cf0cf74f3e48b470f68ed19551ae6f9722814ea969305794645da091236"}, - {file = "msgpack-1.0.4-cp37-cp37m-win32.whl", hash = "sha256:2cc5ca2712ac0003bcb625c96368fd08a0f86bbc1a5578802512d87bc592fe44"}, - {file = "msgpack-1.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:eba96145051ccec0ec86611fe9cf693ce55f2a3ce89c06ed307de0e085730ec1"}, - {file = "msgpack-1.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:7760f85956c415578c17edb39eed99f9181a48375b0d4a94076d84148cf67b2d"}, - {file = "msgpack-1.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:449e57cc1ff18d3b444eb554e44613cffcccb32805d16726a5494038c3b93dab"}, - {file = "msgpack-1.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d603de2b8d2ea3f3bcb2efe286849aa7a81531abc52d8454da12f46235092bcb"}, - {file = "msgpack-1.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f5d88c99f64c456413d74a975bd605a9b0526293218a3b77220a2c15458ba9"}, - {file = "msgpack-1.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6916c78f33602ecf0509cc40379271ba0f9ab572b066bd4bdafd7434dee4bc6e"}, - {file = "msgpack-1.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:81fc7ba725464651190b196f3cd848e8553d4d510114a954681fd0b9c479d7e1"}, - {file = "msgpack-1.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d5b5b962221fa2c5d3a7f8133f9abffc114fe218eb4365e40f17732ade576c8e"}, - {file = "msgpack-1.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:77ccd2af37f3db0ea59fb280fa2165bf1b096510ba9fe0cc2bf8fa92a22fdb43"}, - {file = "msgpack-1.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b17be2478b622939e39b816e0aa8242611cc8d3583d1cd8ec31b249f04623243"}, - {file = "msgpack-1.0.4-cp38-cp38-win32.whl", hash = "sha256:2bb8cdf50dd623392fa75525cce44a65a12a00c98e1e37bf0fb08ddce2ff60d2"}, - {file = "msgpack-1.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:26b8feaca40a90cbe031b03d82b2898bf560027160d3eae1423f4a67654ec5d6"}, - {file = "msgpack-1.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:462497af5fd4e0edbb1559c352ad84f6c577ffbbb708566a0abaaa84acd9f3ae"}, - {file = "msgpack-1.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2999623886c5c02deefe156e8f869c3b0aaeba14bfc50aa2486a0415178fce55"}, - {file = "msgpack-1.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f0029245c51fd9473dc1aede1160b0a29f4a912e6b1dd353fa6d317085b219da"}, - {file = "msgpack-1.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed6f7b854a823ea44cf94919ba3f727e230da29feb4a99711433f25800cf747f"}, - {file = "msgpack-1.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0df96d6eaf45ceca04b3f3b4b111b86b33785683d682c655063ef8057d61fd92"}, - {file = "msgpack-1.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a4192b1ab40f8dca3f2877b70e63799d95c62c068c84dc028b40a6cb03ccd0f"}, - {file = "msgpack-1.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0e3590f9fb9f7fbc36df366267870e77269c03172d086fa76bb4eba8b2b46624"}, - {file = "msgpack-1.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:1576bd97527a93c44fa856770197dec00d223b0b9f36ef03f65bac60197cedf8"}, - {file = "msgpack-1.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:63e29d6e8c9ca22b21846234913c3466b7e4ee6e422f205a2988083de3b08cae"}, - {file = "msgpack-1.0.4-cp39-cp39-win32.whl", hash = "sha256:fb62ea4b62bfcb0b380d5680f9a4b3f9a2d166d9394e9bbd9666c0ee09a3645c"}, - {file = "msgpack-1.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:4d5834a2a48965a349da1c5a79760d94a1a0172fbb5ab6b5b33cbf8447e109ce"}, - {file = "msgpack-1.0.4.tar.gz", hash = "sha256:f5d869c18f030202eb412f08b28d2afeea553d6613aee89e200d7aca7ef01f5f"}, -] -mypy-extensions = [ - {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, - {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, -] -mysqlclient = [ - {file = "mysqlclient-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:c1ed71bd6244993b526113cca3df66428609f90e4652f37eb51c33496d478b37"}, - {file = "mysqlclient-2.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:c812b67e90082a840efb82a8978369e6e69fc62ce1bda4ca8f3084a9d862308b"}, - {file = "mysqlclient-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:0d1cd3a5a4d28c222fa199002810e8146cffd821410b67851af4cc80aeccd97c"}, - {file = "mysqlclient-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:b355c8b5a7d58f2e909acdbb050858390ee1b0e13672ae759e5e784110022994"}, - {file = "mysqlclient-2.1.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:996924f3483fd36a34a5812210c69e71dea5a3d5978d01199b78b7f6d485c855"}, - {file = "mysqlclient-2.1.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:dea88c8d3f5a5d9293dfe7f087c16dd350ceb175f2f6631c9cf4caf3e19b7a96"}, - {file = "mysqlclient-2.1.1.tar.gz", hash = "sha256:828757e419fb11dd6c5ed2576ec92c3efaa93a0f7c39e263586d1ee779c3d782"}, -] -nodeenv = [ - {file = "nodeenv-1.7.0-py2.py3-none-any.whl", hash = "sha256:27083a7b96a25f2f5e1d8cb4b6317ee8aeda3bdd121394e5ac54e498028a042e"}, - {file = "nodeenv-1.7.0.tar.gz", hash = "sha256:e0e7f7dfb85fc5394c6fe1e8fa98131a2473e04311a45afb6508f7cf1836fa2b"}, -] -packaging = [ - {file = "packaging-22.0-py3-none-any.whl", hash = "sha256:957e2148ba0e1a3b282772e791ef1d8083648bc131c8ab0c1feba110ce1146c3"}, - {file = "packaging-22.0.tar.gz", hash = "sha256:2198ec20bd4c017b8f9717e00f0c8714076fc2fd93816750ab48e2c41de2cfd3"}, -] -pathspec = [ - {file = "pathspec-0.10.3-py3-none-any.whl", hash = "sha256:3c95343af8b756205e2aba76e843ba9520a24dd84f68c22b9f93251507509dd6"}, - {file = "pathspec-0.10.3.tar.gz", hash = "sha256:56200de4077d9d0791465aa9095a01d421861e405b5096955051deefd697d6f6"}, -] -pillow = [ - {file = "Pillow-9.4.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:2968c58feca624bb6c8502f9564dd187d0e1389964898f5e9e1fbc8533169157"}, - {file = "Pillow-9.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c5c1362c14aee73f50143d74389b2c158707b4abce2cb055b7ad37ce60738d47"}, - {file = "Pillow-9.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd752c5ff1b4a870b7661234694f24b1d2b9076b8bf337321a814c612665f343"}, - {file = "Pillow-9.4.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a3049a10261d7f2b6514d35bbb7a4dfc3ece4c4de14ef5876c4b7a23a0e566d"}, - {file = "Pillow-9.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16a8df99701f9095bea8a6c4b3197da105df6f74e6176c5b410bc2df2fd29a57"}, - {file = "Pillow-9.4.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:94cdff45173b1919350601f82d61365e792895e3c3a3443cf99819e6fbf717a5"}, - {file = "Pillow-9.4.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:ed3e4b4e1e6de75fdc16d3259098de7c6571b1a6cc863b1a49e7d3d53e036070"}, - {file = "Pillow-9.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5b2f8a31bd43e0f18172d8ac82347c8f37ef3e0b414431157718aa234991b28"}, - {file = "Pillow-9.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:09b89ddc95c248ee788328528e6a2996e09eaccddeeb82a5356e92645733be35"}, - {file = "Pillow-9.4.0-cp310-cp310-win32.whl", hash = "sha256:f09598b416ba39a8f489c124447b007fe865f786a89dbfa48bb5cf395693132a"}, - {file = "Pillow-9.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:f6e78171be3fb7941f9910ea15b4b14ec27725865a73c15277bc39f5ca4f8391"}, - {file = "Pillow-9.4.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:3fa1284762aacca6dc97474ee9c16f83990b8eeb6697f2ba17140d54b453e133"}, - {file = "Pillow-9.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:eaef5d2de3c7e9b21f1e762f289d17b726c2239a42b11e25446abf82b26ac132"}, - {file = "Pillow-9.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a4dfdae195335abb4e89cc9762b2edc524f3c6e80d647a9a81bf81e17e3fb6f0"}, - {file = "Pillow-9.4.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6abfb51a82e919e3933eb137e17c4ae9c0475a25508ea88993bb59faf82f3b35"}, - {file = "Pillow-9.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:451f10ef963918e65b8869e17d67db5e2f4ab40e716ee6ce7129b0cde2876eab"}, - {file = "Pillow-9.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:6663977496d616b618b6cfa43ec86e479ee62b942e1da76a2c3daa1c75933ef4"}, - {file = "Pillow-9.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:60e7da3a3ad1812c128750fc1bc14a7ceeb8d29f77e0a2356a8fb2aa8925287d"}, - {file = "Pillow-9.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:19005a8e58b7c1796bc0167862b1f54a64d3b44ee5d48152b06bb861458bc0f8"}, - {file = "Pillow-9.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f715c32e774a60a337b2bb8ad9839b4abf75b267a0f18806f6f4f5f1688c4b5a"}, - {file = "Pillow-9.4.0-cp311-cp311-win32.whl", hash = "sha256:b222090c455d6d1a64e6b7bb5f4035c4dff479e22455c9eaa1bdd4c75b52c80c"}, - {file = "Pillow-9.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:ba6612b6548220ff5e9df85261bddc811a057b0b465a1226b39bfb8550616aee"}, - {file = "Pillow-9.4.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:5f532a2ad4d174eb73494e7397988e22bf427f91acc8e6ebf5bb10597b49c493"}, - {file = "Pillow-9.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dd5a9c3091a0f414a963d427f920368e2b6a4c2f7527fdd82cde8ef0bc7a327"}, - {file = "Pillow-9.4.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef21af928e807f10bf4141cad4746eee692a0dd3ff56cfb25fce076ec3cc8abe"}, - {file = "Pillow-9.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:847b114580c5cc9ebaf216dd8c8dbc6b00a3b7ab0131e173d7120e6deade1f57"}, - {file = "Pillow-9.4.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:653d7fb2df65efefbcbf81ef5fe5e5be931f1ee4332c2893ca638c9b11a409c4"}, - {file = "Pillow-9.4.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:46f39cab8bbf4a384ba7cb0bc8bae7b7062b6a11cfac1ca4bc144dea90d4a9f5"}, - {file = "Pillow-9.4.0-cp37-cp37m-win32.whl", hash = "sha256:7ac7594397698f77bce84382929747130765f66406dc2cd8b4ab4da68ade4c6e"}, - {file = "Pillow-9.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:46c259e87199041583658457372a183636ae8cd56dbf3f0755e0f376a7f9d0e6"}, - {file = "Pillow-9.4.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:0e51f608da093e5d9038c592b5b575cadc12fd748af1479b5e858045fff955a9"}, - {file = "Pillow-9.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:765cb54c0b8724a7c12c55146ae4647e0274a839fb6de7bcba841e04298e1011"}, - {file = "Pillow-9.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:519e14e2c49fcf7616d6d2cfc5c70adae95682ae20f0395e9280db85e8d6c4df"}, - {file = "Pillow-9.4.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d197df5489004db87d90b918033edbeee0bd6df3848a204bca3ff0a903bef837"}, - {file = "Pillow-9.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0845adc64fe9886db00f5ab68c4a8cd933ab749a87747555cec1c95acea64b0b"}, - {file = "Pillow-9.4.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:e1339790c083c5a4de48f688b4841f18df839eb3c9584a770cbd818b33e26d5d"}, - {file = "Pillow-9.4.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:a96e6e23f2b79433390273eaf8cc94fec9c6370842e577ab10dabdcc7ea0a66b"}, - {file = "Pillow-9.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7cfc287da09f9d2a7ec146ee4d72d6ea1342e770d975e49a8621bf54eaa8f30f"}, - {file = "Pillow-9.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d7081c084ceb58278dd3cf81f836bc818978c0ccc770cbbb202125ddabec6628"}, - {file = "Pillow-9.4.0-cp38-cp38-win32.whl", hash = "sha256:df41112ccce5d47770a0c13651479fbcd8793f34232a2dd9faeccb75eb5d0d0d"}, - {file = "Pillow-9.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:7a21222644ab69ddd9967cfe6f2bb420b460dae4289c9d40ff9a4896e7c35c9a"}, - {file = "Pillow-9.4.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0f3269304c1a7ce82f1759c12ce731ef9b6e95b6df829dccd9fe42912cc48569"}, - {file = "Pillow-9.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cb362e3b0976dc994857391b776ddaa8c13c28a16f80ac6522c23d5257156bed"}, - {file = "Pillow-9.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a2e0f87144fcbbe54297cae708c5e7f9da21a4646523456b00cc956bd4c65815"}, - {file = "Pillow-9.4.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:28676836c7796805914b76b1837a40f76827ee0d5398f72f7dcc634bae7c6264"}, - {file = "Pillow-9.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0884ba7b515163a1a05440a138adeb722b8a6ae2c2b33aea93ea3118dd3a899e"}, - {file = "Pillow-9.4.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:53dcb50fbdc3fb2c55431a9b30caeb2f7027fcd2aeb501459464f0214200a503"}, - {file = "Pillow-9.4.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:e8c5cf126889a4de385c02a2c3d3aba4b00f70234bfddae82a5eaa3ee6d5e3e6"}, - {file = "Pillow-9.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6c6b1389ed66cdd174d040105123a5a1bc91d0aa7059c7261d20e583b6d8cbd2"}, - {file = "Pillow-9.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0dd4c681b82214b36273c18ca7ee87065a50e013112eea7d78c7a1b89a739153"}, - {file = "Pillow-9.4.0-cp39-cp39-win32.whl", hash = "sha256:6d9dfb9959a3b0039ee06c1a1a90dc23bac3b430842dcb97908ddde05870601c"}, - {file = "Pillow-9.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:54614444887e0d3043557d9dbc697dbb16cfb5a35d672b7a0fcc1ed0cf1c600b"}, - {file = "Pillow-9.4.0-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b9b752ab91e78234941e44abdecc07f1f0d8f51fb62941d32995b8161f68cfe5"}, - {file = "Pillow-9.4.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3b56206244dc8711f7e8b7d6cad4663917cd5b2d950799425076681e8766286"}, - {file = "Pillow-9.4.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aabdab8ec1e7ca7f1434d042bf8b1e92056245fb179790dc97ed040361f16bfd"}, - {file = "Pillow-9.4.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:db74f5562c09953b2c5f8ec4b7dfd3f5421f31811e97d1dbc0a7c93d6e3a24df"}, - {file = "Pillow-9.4.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e9d7747847c53a16a729b6ee5e737cf170f7a16611c143d95aa60a109a59c336"}, - {file = "Pillow-9.4.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b52ff4f4e002f828ea6483faf4c4e8deea8d743cf801b74910243c58acc6eda3"}, - {file = "Pillow-9.4.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:575d8912dca808edd9acd6f7795199332696d3469665ef26163cd090fa1f8bfa"}, - {file = "Pillow-9.4.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3c4ed2ff6760e98d262e0cc9c9a7f7b8a9f61aa4d47c58835cdaf7b0b8811bb"}, - {file = "Pillow-9.4.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e621b0246192d3b9cb1dc62c78cfa4c6f6d2ddc0ec207d43c0dedecb914f152a"}, - {file = "Pillow-9.4.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:8f127e7b028900421cad64f51f75c051b628db17fb00e099eb148761eed598c9"}, - {file = "Pillow-9.4.0.tar.gz", hash = "sha256:a1c2d7780448eb93fbcc3789bf3916aa5720d942e37945f4056680317f1cd23e"}, -] -platformdirs = [ - {file = "platformdirs-2.6.2-py3-none-any.whl", hash = "sha256:83c8f6d04389165de7c9b6f0c682439697887bca0aa2f1c87ef1826be3584490"}, - {file = "platformdirs-2.6.2.tar.gz", hash = "sha256:e1fea1fe471b9ff8332e229df3cb7de4f53eeea4998d3b6bfff542115e998bd2"}, -] -pluggy = [ - {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, - {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, -] -pre-commit = [ - {file = "pre_commit-2.21.0-py2.py3-none-any.whl", hash = "sha256:e2f91727039fc39a92f58a588a25b87f936de6567eed4f0e673e0507edc75bad"}, - {file = "pre_commit-2.21.0.tar.gz", hash = "sha256:31ef31af7e474a8d8995027fefdfcf509b5c913ff31f2015b4ec4beb26a6f658"}, -] -proto-plus = [ - {file = "proto-plus-1.22.1.tar.gz", hash = "sha256:6c7dfd122dfef8019ff654746be4f5b1d9c80bba787fe9611b508dd88be3a2fa"}, - {file = "proto_plus-1.22.1-py3-none-any.whl", hash = "sha256:ea8982669a23c379f74495bc48e3dcb47c822c484ce8ee1d1d7beb339d4e34c5"}, -] -protobuf = [ - {file = "protobuf-4.21.12-cp310-abi3-win32.whl", hash = "sha256:b135410244ebe777db80298297a97fbb4c862c881b4403b71bac9d4107d61fd1"}, - {file = "protobuf-4.21.12-cp310-abi3-win_amd64.whl", hash = "sha256:89f9149e4a0169cddfc44c74f230d7743002e3aa0b9472d8c28f0388102fc4c2"}, - {file = "protobuf-4.21.12-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:299ea899484ee6f44604deb71f424234f654606b983cb496ea2a53e3c63ab791"}, - {file = "protobuf-4.21.12-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:d1736130bce8cf131ac7957fa26880ca19227d4ad68b4888b3be0dea1f95df97"}, - {file = "protobuf-4.21.12-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:78a28c9fa223998472886c77042e9b9afb6fe4242bd2a2a5aced88e3f4422aa7"}, - {file = "protobuf-4.21.12-cp37-cp37m-win32.whl", hash = "sha256:3d164928ff0727d97022957c2b849250ca0e64777ee31efd7d6de2e07c494717"}, - {file = "protobuf-4.21.12-cp37-cp37m-win_amd64.whl", hash = "sha256:f45460f9ee70a0ec1b6694c6e4e348ad2019275680bd68a1d9314b8c7e01e574"}, - {file = "protobuf-4.21.12-cp38-cp38-win32.whl", hash = "sha256:6ab80df09e3208f742c98443b6166bcb70d65f52cfeb67357d52032ea1ae9bec"}, - {file = "protobuf-4.21.12-cp38-cp38-win_amd64.whl", hash = "sha256:1f22ac0ca65bb70a876060d96d914dae09ac98d114294f77584b0d2644fa9c30"}, - {file = "protobuf-4.21.12-cp39-cp39-win32.whl", hash = "sha256:27f4d15021da6d2b706ddc3860fac0a5ddaba34ab679dc182b60a8bb4e1121cc"}, - {file = "protobuf-4.21.12-cp39-cp39-win_amd64.whl", hash = "sha256:237216c3326d46808a9f7c26fd1bd4b20015fb6867dc5d263a493ef9a539293b"}, - {file = "protobuf-4.21.12-py2.py3-none-any.whl", hash = "sha256:a53fd3f03e578553623272dc46ac2f189de23862e68565e83dde203d41b76fc5"}, - {file = "protobuf-4.21.12-py3-none-any.whl", hash = "sha256:b98d0148f84e3a3c569e19f52103ca1feacdac0d2df8d6533cf983d1fda28462"}, - {file = "protobuf-4.21.12.tar.gz", hash = "sha256:7cd532c4566d0e6feafecc1059d04c7915aec8e182d1cf7adee8b24ef1e2e6ab"}, -] -py = [ - {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, - {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, -] -pyasn1 = [ - {file = "pyasn1-0.4.8-py2.py3-none-any.whl", hash = "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d"}, - {file = "pyasn1-0.4.8.tar.gz", hash = "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba"}, -] -pyasn1-modules = [ - {file = "pyasn1-modules-0.2.8.tar.gz", hash = "sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e"}, - {file = "pyasn1_modules-0.2.8-py2.py3-none-any.whl", hash = "sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74"}, -] -pycodestyle = [ - {file = "pycodestyle-2.10.0-py2.py3-none-any.whl", hash = "sha256:8a4eaf0d0495c7395bdab3589ac2db602797d76207242c17d470186815706610"}, - {file = "pycodestyle-2.10.0.tar.gz", hash = "sha256:347187bdb476329d98f695c213d7295a846d1152ff4fe9bacb8a9590b8ee7053"}, -] -pycparser = [ - {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, - {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, -] -pygments = [ - {file = "Pygments-2.14.0-py3-none-any.whl", hash = "sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717"}, - {file = "Pygments-2.14.0.tar.gz", hash = "sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297"}, -] -pyjwt = [ - {file = "PyJWT-2.6.0-py3-none-any.whl", hash = "sha256:d83c3d892a77bbb74d3e1a2cfa90afaadb60945205d1095d9221f04466f64c14"}, - {file = "PyJWT-2.6.0.tar.gz", hash = "sha256:69285c7e31fc44f68a1feb309e948e0df53259d579295e6cfe2b1792329f05fd"}, -] -pylint = [ - {file = "pylint-2.13.9-py3-none-any.whl", hash = "sha256:705c620d388035bdd9ff8b44c5bcdd235bfb49d276d488dd2c8ff1736aa42526"}, - {file = "pylint-2.13.9.tar.gz", hash = "sha256:095567c96e19e6f57b5b907e67d265ff535e588fe26b12b5ebe1fc5645b2c731"}, -] -pylint-django = [ - {file = "pylint-django-2.5.3.tar.gz", hash = "sha256:0ac090d106c62fe33782a1d01bda1610b761bb1c9bf5035ced9d5f23a13d8591"}, - {file = "pylint_django-2.5.3-py3-none-any.whl", hash = "sha256:56b12b6adf56d548412445bd35483034394a1a94901c3f8571980a13882299d5"}, -] -pylint-plugin-utils = [ - {file = "pylint-plugin-utils-0.7.tar.gz", hash = "sha256:ce48bc0516ae9415dd5c752c940dfe601b18fe0f48aa249f2386adfa95a004dd"}, - {file = "pylint_plugin_utils-0.7-py3-none-any.whl", hash = "sha256:b3d43e85ab74c4f48bb46ae4ce771e39c3a20f8b3d56982ab17aa73b4f98d535"}, -] -pyotp = [ - {file = "pyotp-2.8.0-py3-none-any.whl", hash = "sha256:889d037fdde6accad28531fc62a790f089e5dfd5b638773e9ee004cce074a2e5"}, - {file = "pyotp-2.8.0.tar.gz", hash = "sha256:c2f5e17d9da92d8ec1f7de6331ab08116b9115adbabcba6e208d46fc49a98c5a"}, -] -pyparsing = [ - {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, - {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, -] -pytest = [ - {file = "pytest-5.4.3-py3-none-any.whl", hash = "sha256:5c0db86b698e8f170ba4582a492248919255fcd4c79b1ee64ace34301fb589a1"}, - {file = "pytest-5.4.3.tar.gz", hash = "sha256:7979331bfcba207414f5e1263b5a0f8f521d0f457318836a7355531ed1a4c7d8"}, -] -pytest-cov = [ - {file = "pytest-cov-2.12.1.tar.gz", hash = "sha256:261ceeb8c227b726249b376b8526b600f38667ee314f910353fa318caa01f4d7"}, - {file = "pytest_cov-2.12.1-py2.py3-none-any.whl", hash = "sha256:261bb9e47e65bd099c89c3edf92972865210c36813f80ede5277dceb77a4a62a"}, -] -pytest-django = [ - {file = "pytest-django-3.10.0.tar.gz", hash = "sha256:4de6dbd077ed8606616958f77655fed0d5e3ee45159475671c7fa67596c6dba6"}, - {file = "pytest_django-3.10.0-py2.py3-none-any.whl", hash = "sha256:c33e3d3da14d8409b125d825d4e74da17bb252191bf6fc3da6856e27a8b73ea4"}, -] -python-crontab = [ - {file = "python-crontab-2.7.1.tar.gz", hash = "sha256:b21af4647c7bbb848fef2f020616c6b0289dcb9f94b4f991a55310ff9bec5749"}, - {file = "python_crontab-2.7.1-py3-none-any.whl", hash = "sha256:9c374d1c9d401afdd8dd958f20077f74c158ab3fffb9604296802715e887fe48"}, -] -python-dateutil = [ - {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, - {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, -] -pytz = [ - {file = "pytz-2022.7-py2.py3-none-any.whl", hash = "sha256:93007def75ae22f7cd991c84e02d434876818661f8df9ad5df9e950ff4e52cfd"}, - {file = "pytz-2022.7.tar.gz", hash = "sha256:7ccfae7b4b2c067464a6733c6261673fdb8fd1be905460396b97a073e9fa683a"}, -] -pyyaml = [ - {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, - {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, - {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, - {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, - {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"}, - {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"}, - {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"}, - {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"}, - {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, - {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, - {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, - {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, - {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, - {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, - {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, - {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, - {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, - {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, - {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, - {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, -] -redis = [ - {file = "redis-3.5.3-py2.py3-none-any.whl", hash = "sha256:432b788c4530cfe16d8d943a09d40ca6c16149727e4afe8c2c9d5580c59d9f24"}, - {file = "redis-3.5.3.tar.gz", hash = "sha256:0e7e0cfca8660dea8b7d5cd8c4f6c5e29e11f31158c0b0ae91a397f00e5a05a2"}, -] -requests = [ - {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"}, - {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, -] -rsa = [ - {file = "rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7"}, - {file = "rsa-4.9.tar.gz", hash = "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21"}, -] -ruamel-yaml = [ - {file = "ruamel.yaml-0.17.21-py3-none-any.whl", hash = "sha256:742b35d3d665023981bd6d16b3d24248ce5df75fdb4e2924e93a05c1f8b61ca7"}, - {file = "ruamel.yaml-0.17.21.tar.gz", hash = "sha256:8b7ce697a2f212752a35c1ac414471dc16c424c9573be4926b56ff3f5d23b7af"}, -] -ruamel-yaml-clib = [ - {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d5859983f26d8cd7bb5c287ef452e8aacc86501487634573d260968f753e1d71"}, - {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:debc87a9516b237d0466a711b18b6ebeb17ba9f391eb7f91c649c5c4ec5006c7"}, - {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:df5828871e6648db72d1c19b4bd24819b80a755c4541d3409f0f7acd0f335c80"}, - {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:efa08d63ef03d079dcae1dfe334f6c8847ba8b645d08df286358b1f5293d24ab"}, - {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win32.whl", hash = "sha256:763d65baa3b952479c4e972669f679fe490eee058d5aa85da483ebae2009d231"}, - {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:d000f258cf42fec2b1bbf2863c61d7b8918d31ffee905da62dede869254d3b8a"}, - {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:045e0626baf1c52e5527bd5db361bc83180faaba2ff586e763d3d5982a876a9e"}, - {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_12_6_arm64.whl", hash = "sha256:721bc4ba4525f53f6a611ec0967bdcee61b31df5a56801281027a3a6d1c2daf5"}, - {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:41d0f1fa4c6830176eef5b276af04c89320ea616655d01327d5ce65e50575c94"}, - {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:4b3a93bb9bc662fc1f99c5c3ea8e623d8b23ad22f861eb6fce9377ac07ad6072"}, - {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-macosx_12_0_arm64.whl", hash = "sha256:a234a20ae07e8469da311e182e70ef6b199d0fbeb6c6cc2901204dd87fb867e8"}, - {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:15910ef4f3e537eea7fe45f8a5d19997479940d9196f357152a09031c5be59f3"}, - {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:370445fd795706fd291ab00c9df38a0caed0f17a6fb46b0f607668ecb16ce763"}, - {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-win32.whl", hash = "sha256:ecdf1a604009bd35c674b9225a8fa609e0282d9b896c03dd441a91e5f53b534e"}, - {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-win_amd64.whl", hash = "sha256:f34019dced51047d6f70cb9383b2ae2853b7fc4dce65129a5acd49f4f9256646"}, - {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2aa261c29a5545adfef9296b7e33941f46aa5bbd21164228e833412af4c9c75f"}, - {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-macosx_12_0_arm64.whl", hash = "sha256:f01da5790e95815eb5a8a138508c01c758e5f5bc0ce4286c4f7028b8dd7ac3d0"}, - {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:40d030e2329ce5286d6b231b8726959ebbe0404c92f0a578c0e2482182e38282"}, - {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:c3ca1fbba4ae962521e5eb66d72998b51f0f4d0f608d3c0347a48e1af262efa7"}, - {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-win32.whl", hash = "sha256:7bdb4c06b063f6fd55e472e201317a3bb6cdeeee5d5a38512ea5c01e1acbdd93"}, - {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:be2a7ad8fd8f7442b24323d24ba0b56c51219513cfa45b9ada3b87b76c374d4b"}, - {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:91a789b4aa0097b78c93e3dc4b40040ba55bef518f84a40d4442f713b4094acb"}, - {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:99e77daab5d13a48a4054803d052ff40780278240a902b880dd37a51ba01a307"}, - {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:3243f48ecd450eddadc2d11b5feb08aca941b5cd98c9b1db14b2fd128be8c697"}, - {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:8831a2cedcd0f0927f788c5bdf6567d9dc9cc235646a434986a852af1cb54b4b"}, - {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-win32.whl", hash = "sha256:3110a99e0f94a4a3470ff67fc20d3f96c25b13d24c6980ff841e82bafe827cac"}, - {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:92460ce908546ab69770b2e576e4f99fbb4ce6ab4b245345a3869a0a0410488f"}, - {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5bc0667c1eb8f83a3752b71b9c4ba55ef7c7058ae57022dd9b29065186a113d9"}, - {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:4a4d8d417868d68b979076a9be6a38c676eca060785abaa6709c7b31593c35d1"}, - {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:bf9a6bc4a0221538b1a7de3ed7bca4c93c02346853f44e1cd764be0023cd3640"}, - {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a7b301ff08055d73223058b5c46c55638917f04d21577c95e00e0c4d79201a6b"}, - {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-win32.whl", hash = "sha256:d5e51e2901ec2366b79f16c2299a03e74ba4531ddcfacc1416639c557aef0ad8"}, - {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:184faeaec61dbaa3cace407cffc5819f7b977e75360e8d5ca19461cd851a5fc5"}, - {file = "ruamel.yaml.clib-0.2.7.tar.gz", hash = "sha256:1f08fd5a2bea9c4180db71678e850b995d2a5f4537be0e94557668cf0f5f9497"}, -] -s3transfer = [ - {file = "s3transfer-0.6.0-py3-none-any.whl", hash = "sha256:06176b74f3a15f61f1b4f25a1fc29a4429040b7647133a463da8fa5bd28d5ecd"}, - {file = "s3transfer-0.6.0.tar.gz", hash = "sha256:2ed07d3866f523cc561bf4a00fc5535827981b117dd7876f036b0c1aca42c947"}, -] -sentry-sdk = [ - {file = "sentry-sdk-0.19.4.tar.gz", hash = "sha256:1052f0ed084e532f66cb3e4ba617960d820152aee8b93fc6c05bd53861768c1c"}, - {file = "sentry_sdk-0.19.4-py2.py3-none-any.whl", hash = "sha256:4c42910a55a6b1fe694d5e4790d5188d105d77b5a6346c1c64cbea8c06c0e8b7"}, -] -setuptools = [ - {file = "setuptools-65.6.3-py3-none-any.whl", hash = "sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54"}, - {file = "setuptools-65.6.3.tar.gz", hash = "sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75"}, -] -six = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] -soupsieve = [ - {file = "soupsieve-2.3.2.post1-py3-none-any.whl", hash = "sha256:3b2503d3c7084a42b1ebd08116e5f81aadfaea95863628c80a3b774a11b7c759"}, - {file = "soupsieve-2.3.2.post1.tar.gz", hash = "sha256:fc53893b3da2c33de295667a0e19f078c14bf86544af307354de5fcf12a3f30d"}, -] -sqlparse = [ - {file = "sqlparse-0.4.3-py3-none-any.whl", hash = "sha256:0323c0ec29cd52bceabc1b4d9d579e311f3e4961b98d174201d5622a23b85e34"}, - {file = "sqlparse-0.4.3.tar.gz", hash = "sha256:69ca804846bb114d2ec380e4360a8a340db83f0ccf3afceeb1404df028f57268"}, -] -toml = [ - {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, - {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, -] -tomli = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, -] -tqdm = [ - {file = "tqdm-4.64.1-py2.py3-none-any.whl", hash = "sha256:6fee160d6ffcd1b1c68c65f14c829c22832bc401726335ce92c52d395944a6a1"}, - {file = "tqdm-4.64.1.tar.gz", hash = "sha256:5f4f682a004951c1b450bc753c710e9280c5746ce6ffedee253ddbcbf54cf1e4"}, -] -typed-ast = [ - {file = "typed_ast-1.5.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:669dd0c4167f6f2cd9f57041e03c3c2ebf9063d0757dc89f79ba1daa2bfca9d4"}, - {file = "typed_ast-1.5.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:211260621ab1cd7324e0798d6be953d00b74e0428382991adfddb352252f1d62"}, - {file = "typed_ast-1.5.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:267e3f78697a6c00c689c03db4876dd1efdfea2f251a5ad6555e82a26847b4ac"}, - {file = "typed_ast-1.5.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c542eeda69212fa10a7ada75e668876fdec5f856cd3d06829e6aa64ad17c8dfe"}, - {file = "typed_ast-1.5.4-cp310-cp310-win_amd64.whl", hash = "sha256:a9916d2bb8865f973824fb47436fa45e1ebf2efd920f2b9f99342cb7fab93f72"}, - {file = "typed_ast-1.5.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:79b1e0869db7c830ba6a981d58711c88b6677506e648496b1f64ac7d15633aec"}, - {file = "typed_ast-1.5.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a94d55d142c9265f4ea46fab70977a1944ecae359ae867397757d836ea5a3f47"}, - {file = "typed_ast-1.5.4-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:183afdf0ec5b1b211724dfef3d2cad2d767cbefac291f24d69b00546c1837fb6"}, - {file = "typed_ast-1.5.4-cp36-cp36m-win_amd64.whl", hash = "sha256:639c5f0b21776605dd6c9dbe592d5228f021404dafd377e2b7ac046b0349b1a1"}, - {file = "typed_ast-1.5.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cf4afcfac006ece570e32d6fa90ab74a17245b83dfd6655a6f68568098345ff6"}, - {file = "typed_ast-1.5.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed855bbe3eb3715fca349c80174cfcfd699c2f9de574d40527b8429acae23a66"}, - {file = "typed_ast-1.5.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6778e1b2f81dfc7bc58e4b259363b83d2e509a65198e85d5700dfae4c6c8ff1c"}, - {file = "typed_ast-1.5.4-cp37-cp37m-win_amd64.whl", hash = "sha256:0261195c2062caf107831e92a76764c81227dae162c4f75192c0d489faf751a2"}, - {file = "typed_ast-1.5.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2efae9db7a8c05ad5547d522e7dbe62c83d838d3906a3716d1478b6c1d61388d"}, - {file = "typed_ast-1.5.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7d5d014b7daa8b0bf2eaef684295acae12b036d79f54178b92a2b6a56f92278f"}, - {file = "typed_ast-1.5.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:370788a63915e82fd6f212865a596a0fefcbb7d408bbbb13dea723d971ed8bdc"}, - {file = "typed_ast-1.5.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4e964b4ff86550a7a7d56345c7864b18f403f5bd7380edf44a3c1fb4ee7ac6c6"}, - {file = "typed_ast-1.5.4-cp38-cp38-win_amd64.whl", hash = "sha256:683407d92dc953c8a7347119596f0b0e6c55eb98ebebd9b23437501b28dcbb8e"}, - {file = "typed_ast-1.5.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4879da6c9b73443f97e731b617184a596ac1235fe91f98d279a7af36c796da35"}, - {file = "typed_ast-1.5.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3e123d878ba170397916557d31c8f589951e353cc95fb7f24f6bb69adc1a8a97"}, - {file = "typed_ast-1.5.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebd9d7f80ccf7a82ac5f88c521115cc55d84e35bf8b446fcd7836eb6b98929a3"}, - {file = "typed_ast-1.5.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98f80dee3c03455e92796b58b98ff6ca0b2a6f652120c263efdba4d6c5e58f72"}, - {file = "typed_ast-1.5.4-cp39-cp39-win_amd64.whl", hash = "sha256:0fdbcf2fef0ca421a3f5912555804296f0b0960f0418c440f5d6d3abb549f3e1"}, - {file = "typed_ast-1.5.4.tar.gz", hash = "sha256:39e21ceb7388e4bb37f4c679d72707ed46c2fbf2a5609b8b8ebc4b067d977df2"}, -] -typing-extensions = [ - {file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"}, - {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"}, -] -uritemplate = [ - {file = "uritemplate-4.1.1-py2.py3-none-any.whl", hash = "sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e"}, - {file = "uritemplate-4.1.1.tar.gz", hash = "sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0"}, -] -urllib3 = [ - {file = "urllib3-1.26.13-py2.py3-none-any.whl", hash = "sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc"}, - {file = "urllib3-1.26.13.tar.gz", hash = "sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8"}, -] -vine = [ - {file = "vine-1.3.0-py2.py3-none-any.whl", hash = "sha256:ea4947cc56d1fd6f2095c8d543ee25dad966f78692528e68b4fada11ba3f98af"}, - {file = "vine-1.3.0.tar.gz", hash = "sha256:133ee6d7a9016f177ddeaf191c1f58421a1dcc6ee9a42c58b34bed40e1d2cd87"}, -] -virtualenv = [ - {file = "virtualenv-20.16.2-py2.py3-none-any.whl", hash = "sha256:635b272a8e2f77cb051946f46c60a54ace3cb5e25568228bd6b57fc70eca9ff3"}, - {file = "virtualenv-20.16.2.tar.gz", hash = "sha256:0ef5be6d07181946891f5abc8047fda8bc2f0b4b9bf222c64e6e8963baee76db"}, -] -wcwidth = [ - {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, - {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, -] -webencodings = [ - {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, - {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, -] -wrapt = [ - {file = "wrapt-1.14.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1"}, - {file = "wrapt-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320"}, - {file = "wrapt-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2"}, - {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4"}, - {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069"}, - {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310"}, - {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f"}, - {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656"}, - {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c"}, - {file = "wrapt-1.14.1-cp310-cp310-win32.whl", hash = "sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8"}, - {file = "wrapt-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d"}, - {file = "wrapt-1.14.1-cp35-cp35m-win32.whl", hash = "sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7"}, - {file = "wrapt-1.14.1-cp35-cp35m-win_amd64.whl", hash = "sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00"}, - {file = "wrapt-1.14.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4"}, - {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1"}, - {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1"}, - {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff"}, - {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d"}, - {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1"}, - {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569"}, - {file = "wrapt-1.14.1-cp36-cp36m-win32.whl", hash = "sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed"}, - {file = "wrapt-1.14.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471"}, - {file = "wrapt-1.14.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248"}, - {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68"}, - {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d"}, - {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77"}, - {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7"}, - {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015"}, - {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a"}, - {file = "wrapt-1.14.1-cp37-cp37m-win32.whl", hash = "sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853"}, - {file = "wrapt-1.14.1-cp37-cp37m-win_amd64.whl", hash = "sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c"}, - {file = "wrapt-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456"}, - {file = "wrapt-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f"}, - {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc"}, - {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1"}, - {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af"}, - {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b"}, - {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0"}, - {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57"}, - {file = "wrapt-1.14.1-cp38-cp38-win32.whl", hash = "sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5"}, - {file = "wrapt-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d"}, - {file = "wrapt-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383"}, - {file = "wrapt-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7"}, - {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86"}, - {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735"}, - {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b"}, - {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3"}, - {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3"}, - {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe"}, - {file = "wrapt-1.14.1-cp39-cp39-win32.whl", hash = "sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5"}, - {file = "wrapt-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb"}, - {file = "wrapt-1.14.1.tar.gz", hash = "sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d"}, -] -zipp = [ - {file = "zipp-3.11.0-py3-none-any.whl", hash = "sha256:83a28fcb75844b5c0cdaf5aa4003c2d728c77e05f5aeabe8e95e56727005fbaa"}, - {file = "zipp-3.11.0.tar.gz", hash = "sha256:a7a22e05929290a67401440b39690ae6563279bced5f314609d9d03798f56766"}, -] diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index 75b03f20..00000000 --- a/pyproject.toml +++ /dev/null @@ -1,62 +0,0 @@ -[tool.poetry] -name = "new-ara-api" -version = "2.0.6" -description = "" -authors = [] - -[tool.poetry.dependencies] -python = "^3.7" -djangorestframework = "^3.12" -django-s3-storage = "0.13.3" -django-cors-headers = "^3.1" -django-mysql = "^3.2" -requests = "^2.22" -beautifulsoup4 = "^4.8" -django-extensions = "^2.2" -djangorestframework-filters = "^1.0.0.dev0" -drf-yasg = "^1.17" -bleach = "^3.1" -pillow = "^9.4.0" -django-environ = "^0.4.5" -gunicorn = "^19.9" -pytest = "^5.4.2" -pytest-django = "^3.9.0" -pytest-cov = "^2.8.1" -lxml = "^4.6.5" -django-crontab = "^0.7.1" -redis = "^3.5.3" -celery = {extras = ["redis"], version = "^4.4.7"} -django-celery-beat = "^2.0.0" -django-celery-results = "^1.2.1" -mysqlclient = "^2.0.1" -django-redis = "^4.12.1" -bpython = "^0.19" -django-ses = "^1.0.2" -tqdm = "^4.48.2" -cached-property = "^1.5.1" -django-cacheops = "^5.0.1" -fake-useragent = "^0.1.11" -sentry-sdk = "0.19.4" -django-elasticsearch-dsl = "^7.1.4" -html5lib = "^1.1" -pyotp = "^2.6.0" -Django = "^3.2.13" -importlib-metadata = "4.8.1" -firebase-admin = "^6.0.1" -django-dotenv = "^1.4.2" -elasticsearch-dsl = "^7.0.0" -blessings = "^1.7" - -[tool.poetry.dev-dependencies] -pylint = "^2.4" -autopep8 = "^1.4" -pylint-django = "^2.3.0" -django-silk = "^4.1.0" -django-debug-toolbar = "^2.2" -django-debug-toolbar-force = "0.1.8" -pre-commit = "^2.8.2" -black = "^22.10.0" - -[build-system] -requires = ["poetry-core>=1.0.0"] -build-backend = "poetry.core.masonry.api" diff --git a/tests/conftest.py b/tests/conftest.py index 34dc8e42..7ab8a049 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,9 +2,8 @@ Python 3.5 이후로는 pytest-django를 쓸 때 module-scope fixture에서 DB접근이 안되기 때문에 class-scope fixture 사용 https://github.com/pytest-dev/pytest-django/issues/53#issuecomment-407073682 """ - import pytest -from django.contrib.auth.models import User +from django.contrib.auth import get_user_model from django.test import TestCase as DjangoTestCase from django.utils import timezone from rest_framework.test import APIClient @@ -12,6 +11,8 @@ from apps.user.models import UserProfile from ara import redis +User = get_user_model() + @pytest.fixture(scope="class") def set_admin_client(request): @@ -62,6 +63,11 @@ def set_user_client2(request): nickname="User2", group=UserProfile.UserGroup.KAIST_MEMBER, agree_terms_of_service_at=timezone.now(), + sso_user_info={ + "kaist_info": '{"ku_kname": "\\ud669"}', + "first_name": "FirstName", + "last_name": "LastName", + }, ) request.cls.api_client = APIClient() @@ -77,6 +83,11 @@ def set_user_client3(request): nickname="User3", group=UserProfile.UserGroup.KAIST_MEMBER, agree_terms_of_service_at=timezone.now(), + sso_user_info={ + "kaist_info": '{"ku_kname": "\\ud669"}', + "first_name": "FirstName", + "last_name": "LastName", + }, ) request.cls.api_client = APIClient() @@ -93,6 +104,11 @@ def set_user_client4(request): nickname="User4", group=UserProfile.UserGroup.KAIST_MEMBER, agree_terms_of_service_at=timezone.now(), + sso_user_info={ + "kaist_info": '{"ku_kname": "\\ud669"}', + "first_name": "FirstName", + "last_name": "LastName", + }, ) request.cls.api_client = APIClient() @@ -181,3 +197,45 @@ def setUpClass(cls): def tearDown(self): redis.flushall() super().tearDown() + + +class Utils: + @staticmethod + def create_user( + username: str = "User", + email: str = "user@sparcs.org", + nickname: str = "Nickname", + group: UserProfile.UserGroup = UserProfile.UserGroup.KAIST_MEMBER, + ) -> User: + user, created = User.objects.get_or_create(username=username, email=email) + if created: + UserProfile.objects.create( + user=user, + nickname=nickname, + group=group, + agree_terms_of_service_at=timezone.now(), + sso_user_info={ + "kaist_info": '{"ku_kname": "\\ud669"}', + "first_name": f"Firstname", + "last_name": f"Lastname", + }, + ) + return user + + @classmethod + def create_user_with_index(cls, idx: int, group: UserProfile.UserGroup) -> User: + user = cls.create_user( + username=f"User{idx}", + email=f"user{idx}@sparcs.org", + nickname=f"Nickname{idx}", + group=group, + ) + return user + + @classmethod + def create_users( + cls, + num: int, + group: UserProfile.UserGroup = UserProfile.UserGroup.KAIST_MEMBER, + ) -> list[User]: + return [cls.create_user_with_index(idx, group) for idx in range(num)] diff --git a/tests/test_article_search.py b/tests/test_article_search.py index 906aa4c6..847066f8 100644 --- a/tests/test_article_search.py +++ b/tests/test_article_search.py @@ -3,7 +3,7 @@ from django.core.management import call_command from apps.core.models import Article, Board -from apps.core.models.board import BoardNameType +from apps.core.models.board import NameType from apps.user.models import UserProfile from tests.conftest import RequestSetting, TestCase @@ -16,8 +16,6 @@ def set_board(request): slug="test board", ko_name="테스트 게시판", en_name="Test Board", - ko_description="테스트 게시판입니다", - en_description="This is a board for testing", ) @@ -30,7 +28,11 @@ def set_authors(request): username=f"User{i+1}", email=f"user{i+1}@sparcs.org" ) if not hasattr(new_user, "profile"): - UserProfile.objects.get_or_create(user=new_user, nickname=f"User{i+1}") + UserProfile.objects.get_or_create( + user=new_user, + nickname=f"User{i + 1}", + sso_user_info={}, + ) request.cls.authors.append(new_user) @@ -53,7 +55,7 @@ def set_posts(request): title=f"게시물 {i+1}", content=article_content, content_text=article_content, - name_type=BoardNameType.REGULAR, + name_type=NameType.REGULAR, is_content_sexual=False, is_content_social=False, created_by=request.cls.authors[i % 4], diff --git a/tests/test_articles.py b/tests/test_articles.py index fee03443..a2e29858 100644 --- a/tests/test_articles.py +++ b/tests/test_articles.py @@ -4,10 +4,10 @@ from rest_framework import status from apps.core.models import Article, Block, Board, Comment, Topic, Vote -from apps.core.models.board import BoardAccessPermissionType, BoardNameType +from apps.core.models.board import BoardAccessPermissionType, NameType from apps.user.models import UserProfile from ara.settings import MIN_TIME, SCHOOL_RESPONSE_VOTE_THRESHOLD -from tests.conftest import RequestSetting, TestCase +from tests.conftest import RequestSetting, TestCase, Utils @pytest.fixture(scope="class") @@ -16,35 +16,34 @@ def set_boards(request): slug="test board", ko_name="테스트 게시판", en_name="Test Board", - ko_description="테스트 게시판입니다", - en_description="This is a board for testing", - name_type=BoardNameType.REGULAR, + name_type=NameType.REGULAR, ) request.cls.anon_board = Board.objects.create( slug="anonymous", ko_name="익명 게시판", en_name="Anonymous", - ko_description="익명 게시판", - en_description="Anonymous", - name_type=BoardNameType.ANONYMOUS, + name_type=NameType.ANONYMOUS, + ) + + request.cls.free_board = Board.objects.create( + slug="free", + ko_name="자유 게시판", + en_name="Free", + name_type=NameType.ANONYMOUS | NameType.REGULAR, ) request.cls.realname_board = Board.objects.create( slug="test realname board", ko_name="테스트 실명 게시판", en_name="Test realname Board", - ko_description="테스트 실명 게시판입니다", - en_description="This is a realname board for testing", - name_type=BoardNameType.REALNAME, + name_type=NameType.REALNAME, ) request.cls.regular_access_board = Board.objects.create( slug="regular access", ko_name="일반 접근 권한 게시판", en_name="Regular Access Board", - ko_description="일반 접근 권한 게시판", - en_description="Regular Access Board", read_access_mask=0b11011110, write_access_mask=0b11011010, ) @@ -54,8 +53,6 @@ def set_boards(request): slug="advertiser accessible", ko_name="외부인(홍보 계정) 접근 가능 게시판", en_name="Advertiser Accessible Board", - ko_description="외부인(홍보 계정) 접근 가능 게시판", - en_description="Advertiser Accessible Board", read_access_mask=0b11111110, write_access_mask=0b11111110, ) @@ -64,8 +61,6 @@ def set_boards(request): slug="nonwritable", ko_name="글 작성 불가 게시판", en_name="Nonwritable Board", - ko_description="글 작성 불가 게시판", - en_description="Nonwritable Board", write_access_mask=0b00000000, ) @@ -73,8 +68,6 @@ def set_boards(request): slug="newsadmin writable", ko_name="뉴스게시판 관리인 글 작성 가능 게시판", en_name="Newsadmin Writable Board", - ko_description="뉴스게시판 관리인 글 작성 가능 게시판", - en_description="Newsadmin Writable Board", write_access_mask=0b10000000, ) @@ -82,8 +75,6 @@ def set_boards(request): slug="enterprise writable", ko_name="입주업체 글 작성 가능 게시판", en_name="Enterprise Writable Board", - ko_description="입주업체 글 작성 가능 게시판", - en_description="Enterprise Writable Board", write_access_mask=0b11011110, ) @@ -95,8 +86,6 @@ def set_topics(request): slug="test topic", ko_name="테스트 토픽", en_name="Test Topic", - ko_description="테스트용 토픽입니다", - en_description="This is topic for testing", parent_board=request.cls.board, ) @@ -104,8 +93,6 @@ def set_topics(request): slug="test realname topic", ko_name="테스트 실명 토픽", en_name="Test realname Topic", - ko_description="테스트용 실명 토픽입니다", - en_description="This is realname topic for testing", parent_board=request.cls.realname_board, ) @@ -117,7 +104,7 @@ def set_articles(request): title="example article", content="example content", content_text="example content text", - name_type=BoardNameType.REGULAR, + name_type=NameType.REGULAR, is_content_sexual=False, is_content_social=False, hit_count=0, @@ -153,7 +140,7 @@ def set_realname_article(request): title="Realname Test Article", content="Content of test realname article", content_text="Content of test article in text", - name_type=BoardNameType.REALNAME, + name_type=NameType.REALNAME, is_content_sexual=False, is_content_social=False, hit_count=0, @@ -176,6 +163,7 @@ def set_kaist_articles(request): user=request.cls.non_kaist_user, nickname="Not a KAIST User", agree_terms_of_service_at=timezone.now(), + sso_user_info={}, ) request.cls.kaist_user, _ = User.objects.get_or_create( username="KaistUser", email="kaist-user@sparcs.org" @@ -186,14 +174,13 @@ def set_kaist_articles(request): nickname="KAIST User", agree_terms_of_service_at=timezone.now(), group=UserProfile.UserGroup.KAIST_MEMBER, + sso_user_info={}, ) request.cls.kaist_board, _ = Board.objects.get_or_create( slug="kaist-only", ko_name="KAIST Board", en_name="KAIST Board", - ko_description="KAIST Board", - en_description="KAIST Board", read_access_mask=0b00000010, write_access_mask=0b00000010, ) @@ -201,7 +188,7 @@ def set_kaist_articles(request): title="example article", content="example content", content_text="example content text", - name_type=BoardNameType.REGULAR, + name_type=NameType.REGULAR, is_content_sexual=False, is_content_social=False, hit_count=0, @@ -222,8 +209,6 @@ def set_readonly_board(request): slug="readonly", ko_name="읽기전용 게시판", en_name="Read Only Board", - ko_description="테스트 게시판입니다", - en_description="This is a board for testing", is_readonly=True, ) yield None @@ -241,24 +226,6 @@ def set_readonly_board(request): "set_articles", ) class TestArticle(TestCase, RequestSetting): - def _create_user_by_group(self, group): - user, created = User.objects.get_or_create( - username=f"User in group {group}", email=f"group{group}user@sparcs.org" - ) - if created: - UserProfile.objects.create( - user=user, - nickname=f"Nickname in group {group}", - group=group, - agree_terms_of_service_at=timezone.now(), - sso_user_info={ - "kaist_info": '{"ku_kname": "\\ud669"}', - "first_name": f"Group{group}User_FirstName", - "last_name": f"Group{group}User_LastName", - }, - ) - return user - def test_list(self): # article 개수를 확인하는 테스트 res = self.http_request(self.user, "get", "articles") @@ -268,7 +235,7 @@ def test_list(self): title="example article", content="example content", content_text="example content text", - name_type=BoardNameType.REGULAR, + name_type=NameType.REGULAR, is_content_sexual=False, is_content_social=False, hit_count=0, @@ -284,7 +251,7 @@ def test_list(self): title="example article", content="example content", content_text="example content text", - name_type=BoardNameType.REGULAR, + name_type=NameType.REGULAR, is_content_sexual=False, is_content_social=False, hit_count=0, @@ -320,7 +287,7 @@ def test_anonymous_article(self): title="example anonymous article", content="example anonymous content", content_text="example anonymous content text", - name_type=BoardNameType.ANONYMOUS, + name_type=NameType.ANONYMOUS, is_content_sexual=False, is_content_social=False, hit_count=0, @@ -334,11 +301,11 @@ def test_anonymous_article(self): # 익명 게시글을 GET할 때, 작성자의 정보가 전달되지 않는 것 확인 res = self.http_request(self.user, "get", f"articles/{anon_article.id}").data - assert res.get("name_type") == BoardNameType.ANONYMOUS + assert res.get("name_type") == NameType.ANONYMOUS assert res.get("created_by")["username"] != anon_article.created_by.username res2 = self.http_request(self.user2, "get", f"articles/{anon_article.id}").data - assert res2.get("name_type") == BoardNameType.ANONYMOUS + assert res2.get("name_type") == NameType.ANONYMOUS assert res2.get("created_by")["username"] != anon_article.created_by.username def test_create(self): @@ -348,7 +315,7 @@ def test_create(self): "title": "article for test_create", "content": "content for test_create", "content_text": "content_text for test_create", - "name_type": BoardNameType.REGULAR, + "name_type": NameType.REGULAR.name, "is_content_sexual": False, "is_content_social": False, "parent_topic": self.topic.id, @@ -360,9 +327,12 @@ def test_create(self): # get request 시 user의 read 권한 확인 테스트 def test_check_read_permission_when_get(self): - group_users = [ - self._create_user_by_group(group) for group in UserProfile.UserGroup - ] + group_users = [] + for idx, group in enumerate(UserProfile.UserGroup): + user = Utils.create_user_with_index(idx, group) + group_users.append(user) + assert len(group_users) == len(UserProfile.UserGroup) + articles = [self.regular_access_article, self.advertiser_accessible_article] for user in group_users: @@ -379,9 +349,12 @@ def test_check_read_permission_when_get(self): # create 단계에서 user의 write 권한 확인 테스트 def test_check_write_permission_when_create(self): - group_users = [ - self._create_user_by_group(group) for group in UserProfile.UserGroup - ] + group_users = [] + for idx, group in enumerate(UserProfile.UserGroup): + user = Utils.create_user_with_index(idx, group) + group_users.append(user) + assert len(group_users) == len(UserProfile.UserGroup) + boards = [ self.regular_access_board, self.nonwritable_board, @@ -401,6 +374,7 @@ def test_check_write_permission_when_create(self): "content": "content in write permission test", "content_text": "content_text in write permission test", "parent_board": board.id, + "name_type": NameType.REGULAR.name, }, ) @@ -411,6 +385,22 @@ def test_check_write_permission_when_create(self): else: assert res.status_code == status.HTTP_403_FORBIDDEN + def test_create_regular(self): + user_data = { + "title": "article for test_create", + "content": "content for test_create", + "content_text": "content_text for test_create", + "is_content_sexual": False, + "is_content_social": False, + "parent_topic": self.topic.id, + "parent_board": self.board.id, + "name_type": NameType.REGULAR.name, + } + + result = self.http_request(self.user, "post", "articles", user_data) + + assert result.data["name_type"] == NameType.REGULAR + def test_create_anonymous(self): user_data = { "title": "article for test_create", @@ -420,15 +410,62 @@ def test_create_anonymous(self): "is_content_social": False, "parent_topic": None, "parent_board": self.anon_board.id, + "name_type": NameType.ANONYMOUS.name, } result = self.http_request(self.user, "post", "articles", user_data) - assert result.data["name_type"] == BoardNameType.ANONYMOUS + assert result.data["name_type"] == NameType.ANONYMOUS + + # 자유게시판에 익명, 닉네임 게시글 만들 수 있다 + def test_create_free(self): + for name_type in [NameType.ANONYMOUS, NameType.REGULAR]: + user_data = { + "title": "article for test_create", + "content": "content for test_create", + "content_text": "content_text for test_create", + "is_content_sexual": False, + "is_content_social": False, + "parent_topic": None, + "parent_board": self.free_board.id, + "name_type": name_type.name, + } + + result = self.http_request(self.user, "post", "articles", user_data) + assert result.data["name_type"] == name_type + + # 일반 게시판에 익명 게시글을 만들 수 없다 + def test_create_invalid1(self): + user_data = { + "title": "article for test_create", + "content": "content for test_create", + "content_text": "content_text for test_create", + "is_content_sexual": False, + "is_content_social": False, + "parent_topic": None, + "parent_board": self.board.id, + "name_type": NameType.ANONYMOUS.name, + } - user_data.update({"parent_topic": self.topic.id, "parent_board": self.board.id}) result = self.http_request(self.user, "post", "articles", user_data) - assert not result.data["name_type"] == BoardNameType.ANONYMOUS + assert result.status_code == status.HTTP_400_BAD_REQUEST + + # 실명 게시판에 익명 게시글, 닉네임 게시글을 만들 수 없다 + def test_create_invalid2(self): + for name_type in [NameType.ANONYMOUS, NameType.REGULAR]: + user_data = { + "title": "article for test_create", + "content": "content for test_create", + "content_text": "content_text for test_create", + "is_content_sexual": False, + "is_content_social": False, + "parent_topic": None, + "parent_board": self.realname_board.id, + "name_type": name_type.name, + } + + result = self.http_request(self.user, "post", "articles", user_data) + assert result.status_code == status.HTTP_400_BAD_REQUEST def test_update_cache_sync(self): new_title = "title changed!" @@ -437,7 +474,7 @@ def test_update_cache_sync(self): title="example article", content="example content", content_text="example content text", - name_type=BoardNameType.REGULAR, + name_type=NameType.REGULAR, is_content_sexual=False, is_content_social=False, hit_count=0, @@ -452,13 +489,13 @@ def test_update_cache_sync(self): self.http_request(self.user, "get", f"articles/{article.id}") response = self.http_request( self.user, - "put", + "patch", f"articles/{article.id}", {"title": new_title, "content": new_content}, ) - assert response.status_code == 200 + assert response.status_code == status.HTTP_200_OK response = self.http_request(self.user, "get", f"articles/{article.id}") - assert response.status_code == 200 + assert response.status_code == status.HTTP_200_OK assert response.data.get("title") == new_title assert response.data.get("content") == new_content @@ -571,7 +608,7 @@ def test_self_vote(self): resp = self.http_request( self.user, "post", f"articles/{self.article.id}/vote_positive" ) - assert resp.status_code == 403 + assert resp.status_code == status.HTTP_403_FORBIDDEN assert resp.data["message"] is not None article = Article.objects.get(id=self.article.id) assert article.positive_vote_count == 0 @@ -580,7 +617,7 @@ def test_self_vote(self): resp = self.http_request( self.user, "post", f"articles/{self.article.id}/vote_negative" ) - assert resp.status_code == 403 + assert resp.status_code == status.HTTP_403_FORBIDDEN assert resp.data["message"] is not None article = Article.objects.get(id=self.article.id) assert article.positive_vote_count == 0 @@ -592,13 +629,13 @@ def test_readonly_board(self): "title": "article for test_create", "content": "content for test_create", "content_text": "content_text for test_create", - "name_type": BoardNameType.REGULAR, + "name_type": NameType.REGULAR.name, "is_content_sexual": False, "is_content_social": False, "parent_board": self.readonly_board.id, } response = self.http_request(self.user, "post", "articles", user_data) - assert response.status_code == 400 + assert response.status_code == status.HTTP_400_BAD_REQUEST def test_read_status(self): # user1, user2 모두 아직 안읽음 @@ -637,7 +674,7 @@ def test_deleting_with_comments(self): self.article.save() Comment.objects.create( content="this is a test comment", - name_type=BoardNameType.REGULAR, + name_type=NameType.REGULAR, created_by=self.user, parent_article=self.article, ) @@ -653,6 +690,59 @@ def test_deleting_with_comments(self): ) assert self.article.comment_count == 0 + def test_being_topped(self): + """ + `Article.topped_at` is set when `Article.positive_vote_count >= + Board.top_threshold` + """ + THRESHOLD = 5 + board = Board.objects.create(top_threshold=THRESHOLD) + article = Article.objects.create(created_by=self.user, parent_board=board) + pk = article.pk + + users = Utils.create_users(THRESHOLD) + *users_ex_one, last_user = users + + for user in users_ex_one: + self.http_request(user, "post", f"articles/{pk}/vote_positive") + + article = Article.objects.get(pk=pk) + assert article.positive_vote_count == THRESHOLD - 1 + assert article.topped_at is None + + self.http_request(last_user, "post", f"articles/{pk}/vote_positive") + article = Article.objects.get(pk=pk) + assert article.positive_vote_count == THRESHOLD + assert article.topped_at is not None + + def test_top_ordered(self): + """ + The most recently topped article must come first. If the same, then + the most recent article must come first. + """ + board = Board.objects.create() + articles = [ + Article.objects.create(created_by=self.user, parent_board=board) + for _ in range(3) + ] + + time_early = timezone.datetime(2001, 10, 18) # retro's birthday + time_late = timezone.datetime(2003, 6, 17) # yuwol's birthday + + articles[0].topped_at = time_early + articles[1].topped_at = time_early + articles[2].topped_at = time_late + for article in articles: + article.save() + + response = self.http_request(self.user, "get", "articles/top") + assert response.status_code == status.HTTP_200_OK + assert response.data["num_items"] == 3 + + oracle_indices = [2, 1, 0] + for idx, res in zip(oracle_indices, response.data["results"]): + assert articles[idx].pk == res["id"] + @pytest.mark.usefixtures( "set_user_client", @@ -671,7 +761,7 @@ def test_get_realname_article(self): title="example realname article with kinfo", content="example realname content with kinfo", content_text="example realname content text with kinfo", - name_type=BoardNameType.REALNAME, + name_type=NameType.REALNAME, is_content_sexual=False, is_content_social=False, hit_count=0, @@ -688,7 +778,7 @@ def test_get_realname_article(self): title="example realname article without_kinfo", content="example realname content without_kinfo", content_text="example realname content text without_kinfo", - name_type=BoardNameType.REALNAME, + name_type=NameType.REALNAME, is_content_sexual=False, is_content_social=False, hit_count=0, @@ -705,7 +795,7 @@ def test_get_realname_article(self): "get", f"articles/{realname_article_with_kinfo.id}", ).data - assert res.get("name_type") == BoardNameType.REALNAME + assert res.get("name_type") == NameType.REALNAME assert ( res.get("created_by")["username"] == realname_article_with_kinfo.created_by.profile.realname @@ -716,7 +806,7 @@ def test_get_realname_article(self): "get", f"articles/{realname_article_without_kinfo.id}", ).data - assert res2.get("name_type") == BoardNameType.REALNAME + assert res2.get("name_type") == NameType.REALNAME assert ( res2.get("created_by")["username"] == realname_article_without_kinfo.created_by.profile.realname @@ -732,23 +822,22 @@ def test_create_realname_article(self): "is_content_social": False, "parent_topic": self.realname_topic.id, "parent_board": self.realname_board.id, + "name_type": NameType.REALNAME.name, } result = self.http_request( self.user_with_kaist_info, "post", "articles", article_data ).data - assert result.get("name_type") == BoardNameType.REALNAME - assert ( - Article.objects.get(title=article_title).name_type == BoardNameType.REALNAME - ) + assert result.get("name_type") == NameType.REALNAME + assert Article.objects.get(title=article_title).name_type == NameType.REALNAME def test_update_realname_article(self): article = Article.objects.create( title="realname article for test_create", content="realname content for test_create", content_text="realname content_text for test_create", - name_type=BoardNameType.REALNAME, + name_type=NameType.REALNAME, is_content_sexual=False, is_content_social=False, hit_count=0, @@ -770,8 +859,8 @@ def test_update_realname_article(self): {"title": new_title, "content": new_content}, ).data - assert result.get("name_type") == BoardNameType.REALNAME - assert Article.objects.get(title=new_title).name_type == BoardNameType.REALNAME + assert result.get("name_type") == NameType.REALNAME + assert Article.objects.get(title=new_title).name_type == NameType.REALNAME def test_ban_vote_cancellation_after_30(self): # SCHOOL_RESPONSE_VOTE_THRESHOLD is 3 in test @@ -820,6 +909,7 @@ def _user_factory(user_kwargs, profile_kwargs): "user": user_instance, "agree_terms_of_service_at": timezone.now(), "group": UserProfile.UserGroup.KAIST_MEMBER, + "sso_user_info": {}, } ) return user_instance @@ -829,11 +919,21 @@ def setUpClass(cls): super().setUpClass() cls.clean_mind_user = cls._user_factory( {"username": "clean-mind-user", "email": "iamclean@sparcs.org"}, - {"nickname": "clean", "see_social": False, "see_sexual": False}, + { + "nickname": "clean", + "see_social": False, + "see_sexual": False, + "sso_user_info": {}, + }, ) cls.dirty_mind_user = cls._user_factory( {"username": "dirty-mind-user", "email": "kbdwarrior@sparcs.org"}, - {"nickname": "kbdwarrior", "see_social": True, "see_sexual": True}, + { + "nickname": "kbdwarrior", + "see_social": True, + "see_sexual": True, + "sso_user_info": {}, + }, ) def _article_factory( @@ -843,7 +943,7 @@ def _article_factory( title="example article", content="example content", content_text="example content text", - name_type=BoardNameType.REGULAR, + name_type=NameType.REGULAR, hit_count=0, is_content_sexual=is_content_sexual, is_content_social=is_content_social, @@ -1016,7 +1116,7 @@ def test_modify_deleted_article(self): }, ) - assert res.status_code == 404 + assert res.status_code == status.HTTP_404_NOT_FOUND def test_modify_report_hidden_article(self): target_article = self._create_report_hidden_article() @@ -1033,7 +1133,7 @@ def test_modify_report_hidden_article(self): }, ) - assert res.status_code == 403 + assert res.status_code == status.HTTP_403_FORBIDDEN def test_get_deleted_article(self): target_article = self._create_deleted_article() @@ -1053,12 +1153,12 @@ def test_exclude_deleted_article_from_list(self): def test_delete_already_deleted_article(self): target_article = self._create_deleted_article() res = self.http_request(self.user, "delete", f"articles/{target_article.id}") - assert res.status_code == 404 + assert res.status_code == status.HTTP_404_NOT_FOUND def test_delete_report_hidden_article(self): target_article = self._create_report_hidden_article() res = self.http_request(self.user, "delete", f"articles/{target_article.id}") - assert res.status_code == 403 + assert res.status_code == status.HTTP_403_FORBIDDEN def test_vote_deleted_article(self): target_article = self._create_deleted_article() @@ -1066,17 +1166,17 @@ def test_vote_deleted_article(self): positive_vote_result = self.http_request( self.user2, "post", f"articles/{target_article.id}/vote_positive" ) - assert positive_vote_result.status_code == 404 + assert positive_vote_result.status_code == status.HTTP_404_NOT_FOUND negative_vote_result = self.http_request( self.user2, "post", f"articles/{target_article.id}/vote_negative" ) - assert negative_vote_result.status_code == 404 + assert negative_vote_result.status_code == status.HTTP_404_NOT_FOUND cancel_vote_result = self.http_request( self.user2, "post", f"articles/{target_article.id}/vote_positive" ) - assert cancel_vote_result.status_code == 404 + assert cancel_vote_result.status_code == status.HTTP_404_NOT_FOUND def test_vote_report_hidden_article(self): target_article = self._create_report_hidden_article() @@ -1084,12 +1184,12 @@ def test_vote_report_hidden_article(self): positive_vote_result = self.http_request( self.user2, "post", f"articles/{target_article.id}/vote_positive" ) - assert positive_vote_result.status_code == 403 + assert positive_vote_result.status_code == status.HTTP_403_FORBIDDEN negative_vote_result = self.http_request( self.user2, "post", f"articles/{target_article.id}/vote_negative" ) - assert negative_vote_result.status_code == 403 + assert negative_vote_result.status_code == status.HTTP_403_FORBIDDEN Vote.objects.create( voted_by=self.user2, @@ -1101,7 +1201,7 @@ def test_vote_report_hidden_article(self): cancel_vote_result = self.http_request( self.user2, "post", f"articles/{target_article.id}/vote_cancel" ) - assert cancel_vote_result.status_code == 403 + assert cancel_vote_result.status_code == status.HTTP_403_FORBIDDEN assert Article.objects.get(id=target_article.id).positive_vote_count == 1 def test_report_deleted_article(self): @@ -1117,7 +1217,7 @@ def test_report_deleted_article(self): }, ) - assert res.status_code == 403 + assert res.status_code == status.HTTP_403_FORBIDDEN def test_report_already_hidden_article(self): target_article = self._create_report_hidden_article() @@ -1132,4 +1232,4 @@ def test_report_already_hidden_article(self): }, ) - assert res.status_code == 403 + assert res.status_code == status.HTTP_403_FORBIDDEN diff --git a/tests/test_block.py b/tests/test_block.py index 9ace2836..6684e870 100644 --- a/tests/test_block.py +++ b/tests/test_block.py @@ -5,7 +5,7 @@ from django.utils import timezone from apps.core.models import Article, Block, Board, Comment, Topic -from apps.core.models.board import BoardNameType +from apps.core.models.board import NameType from tests.conftest import RequestSetting, TestCase @@ -15,8 +15,6 @@ def set_board(request): slug="test board", ko_name="테스트 게시판", en_name="Test Board", - ko_description="테스트 게시판입니다", - en_description="This is a board for testing", ) @@ -26,9 +24,7 @@ def set_anon_board(request): slug="anonymous", ko_name="익명 게시판", en_name="Anonymous", - ko_description="익명 게시판", - en_description="Anonymous", - name_type=BoardNameType.ANONYMOUS, + name_type=NameType.ANONYMOUS, ) @@ -39,8 +35,6 @@ def set_topic(request): slug="test topic", ko_name="테스트 토픽", en_name="Test Topic", - ko_description="테스트용 토픽입니다", - en_description="This is topic for testing", parent_board=request.cls.board, ) @@ -52,7 +46,7 @@ def set_articles(request): title="Test Article", content="Content of test article", content_text="Content of test article in text", - name_type=BoardNameType.REGULAR, + name_type=NameType.REGULAR, is_content_sexual=False, is_content_social=False, hit_count=0, @@ -68,7 +62,7 @@ def set_articles(request): title="Test Article 2", content="Content of test article 2", content_text="Content of test article in text 2", - name_type=BoardNameType.REGULAR, + name_type=NameType.REGULAR, is_content_sexual=False, is_content_social=False, hit_count=0, @@ -84,7 +78,7 @@ def set_articles(request): title="Test Article 3", content="Content of test article 3", content_text="Content of test article in text 3", - name_type=BoardNameType.REGULAR, + name_type=NameType.REGULAR, is_content_sexual=False, is_content_social=False, hit_count=0, @@ -228,7 +222,7 @@ def test_get_anonymous_articles_by_blocked_user(self): title="Test Article", content="Content of test article", content_text="Content of test article in text", - name_type=BoardNameType.ANONYMOUS, + name_type=NameType.ANONYMOUS, is_content_sexual=False, is_content_social=False, hit_count=0, @@ -260,14 +254,14 @@ def test_comment_by_blocked_user(self): # user2가 댓글을 씀 blocked_comment = Comment.objects.create( content="this is a test comment", - name_type=BoardNameType.REGULAR, + name_type=NameType.REGULAR, created_by=self.user2, parent_article=self.article, ) not_blocked_comment = Comment.objects.create( content="this is a test comment", - name_type=BoardNameType.REGULAR, + name_type=NameType.REGULAR, created_by=self.user3, parent_article=self.article, ) diff --git a/tests/test_board.py b/tests/test_board.py index a7ba0831..dc74f69a 100644 --- a/tests/test_board.py +++ b/tests/test_board.py @@ -11,8 +11,6 @@ def test_list(self): Board.objects.create( ko_name="자유 게시판", en_name="Free Board", - ko_description="자유 게시판 입니다.", - en_description="This is a free board.", ) boards = self.http_request(self.user, "get", "boards") diff --git a/tests/test_comments.py b/tests/test_comments.py index 13c7899f..3daf6bca 100644 --- a/tests/test_comments.py +++ b/tests/test_comments.py @@ -7,7 +7,7 @@ from rest_framework import status from apps.core.models import Article, Block, Board, Comment, Topic, Vote -from apps.core.models.board import BoardNameType +from apps.core.models.board import NameType from ara.settings import MIN_TIME from tests.conftest import RequestSetting, TestCase @@ -18,18 +18,14 @@ def set_boards(request): slug="test board", ko_name="테스트 게시판", en_name="Test Board", - name_type=BoardNameType.REGULAR, - ko_description="테스트 게시판입니다", - en_description="This is a board for testing", + name_type=NameType.REGULAR, ) request.cls.realname_board = Board.objects.create( slug="test realname board", ko_name="테스트 실명 게시판", en_name="Test realname Board", - name_type=BoardNameType.REALNAME, - ko_description="테스트 실명 게시판입니다", - en_description="This is a realname board for testing", + name_type=NameType.REALNAME, ) @@ -40,8 +36,6 @@ def set_topics(request): slug="test topic", ko_name="테스트 토픽", en_name="Test Topic", - ko_description="테스트용 토픽입니다", - en_description="This is topic for testing", parent_board=request.cls.board, ) @@ -49,8 +43,6 @@ def set_topics(request): slug="test realname topic", ko_name="테스트 실명 토픽", en_name="Test realname Topic", - ko_description="테스트용 실명 토픽입니다", - en_description="This is realname topic for testing", parent_board=request.cls.realname_board, ) @@ -62,7 +54,7 @@ def set_articles(request): title="Test Article", content="Content of test article", content_text="Content of test article in text", - name_type=BoardNameType.REGULAR, + name_type=NameType.REGULAR, is_content_sexual=False, is_content_social=False, hit_count=0, @@ -79,7 +71,7 @@ def set_articles(request): title="Anonymous Test Article", content="Content of test article", content_text="Content of test article in text", - name_type=BoardNameType.ANONYMOUS, + name_type=NameType.ANONYMOUS, is_content_sexual=False, is_content_social=False, hit_count=0, @@ -96,7 +88,7 @@ def set_articles(request): title="Realname Test Article", content="Content of test realname article", content_text="Content of test article in text", - name_type=BoardNameType.REALNAME, + name_type=NameType.REALNAME, is_content_sexual=False, is_content_social=False, hit_count=0, @@ -113,7 +105,7 @@ def set_articles(request): title="Realname Test Article", content="Content of test realname article", content_text="Content of test article in text", - name_type=BoardNameType.REALNAME, + name_type=NameType.REALNAME, is_content_sexual=False, is_content_social=False, hit_count=0, @@ -131,21 +123,21 @@ def set_comments(request): """set_article 먼저 적용""" request.cls.comment = Comment.objects.create( content="this is a test comment", - name_type=BoardNameType.REGULAR, + name_type=NameType.REGULAR, created_by=request.cls.user, parent_article=request.cls.article_regular, ) request.cls.comment_anonymous = Comment.objects.create( content="this is an anonymous test comment", - name_type=BoardNameType.ANONYMOUS, + name_type=NameType.ANONYMOUS, created_by=request.cls.user, parent_article=request.cls.article_anonymous, ) request.cls.realname_comment = Comment.objects.create( content="this is an realname test comment", - name_type=BoardNameType.REALNAME, + name_type=NameType.REALNAME, created_by=request.cls.user_with_kaist_info, parent_article=request.cls.realname_article, ) @@ -172,13 +164,13 @@ def test_comment_list(self): comment2 = Comment.objects.create( content="Test comment 2", - name_type=BoardNameType.REGULAR, + name_type=NameType.REGULAR, created_by=self.user, parent_article=self.article_regular, ) comment3 = Comment.objects.create( content="Test comment 3", - name_type=BoardNameType.REGULAR, + name_type=NameType.REGULAR, created_by=self.user, parent_article=self.article_regular, ) @@ -223,14 +215,13 @@ def test_article_comment_count(self): # 대댓글의 생성과 삭제에 따라서 article의 comment_count가 맞게 바뀌는지 확인 def test_article_comment_count_with_subcomments(self): - article = Article.objects.get(id=self.article_regular.id) print("comment set: ", article.comment_set) assert article.comment_count == 1 subcomment1 = Comment.objects.create( content="Test comment 2", - name_type=BoardNameType.REGULAR, + name_type=NameType.REGULAR, created_by=self.user, parent_comment=self.comment, ) @@ -241,7 +232,7 @@ def test_article_comment_count_with_subcomments(self): subcomment2 = Comment.objects.create( content="Test comment 3", - name_type=BoardNameType.REGULAR, + name_type=NameType.REGULAR, created_by=self.user, parent_comment=self.comment, ) @@ -280,7 +271,7 @@ def test_delete_comment_by_not_comment_writer(self): def test_delete_comment_with_subcomment(self): subcomment = Comment.objects.create( content="Test subcomment", - name_type=BoardNameType.REGULAR, + name_type=NameType.REGULAR, created_by=self.user, parent_comment=self.comment, ) @@ -316,18 +307,18 @@ def test_anonymous_comment(self): # 익명 댓글 생성 anon_comment = Comment.objects.create( content="Anonymous test comment", - name_type=BoardNameType.ANONYMOUS, + name_type=NameType.ANONYMOUS, created_by=self.user, parent_article=self.article_regular, ) # 익명 댓글을 GET할 때, 작성자의 정보가 전달되지 않는 것 확인 res = self.http_request(self.user, "get", f"comments/{anon_comment.id}").data - assert res.get("name_type") == BoardNameType.ANONYMOUS + assert res.get("name_type") == NameType.ANONYMOUS assert res.get("created_by")["username"] != anon_comment.created_by.username res2 = self.http_request(self.user2, "get", f"comments/{anon_comment.id}").data - assert res2.get("name_type") == BoardNameType.ANONYMOUS + assert res2.get("name_type") == NameType.ANONYMOUS assert res2.get("created_by")["username"] != anon_comment.created_by.username # 익명글의 글쓴이가 본인의 글에 남긴 댓글에 대해, user_id가 같은지 확인 @@ -335,7 +326,7 @@ def test_anonymous_comment_by_article_writer(self): # 익명 댓글 생성 Comment.objects.create( content="Anonymous test comment", - name_type=BoardNameType.ANONYMOUS, + name_type=NameType.ANONYMOUS, created_by=self.user, parent_article=self.article_anonymous, ) @@ -369,8 +360,8 @@ def test_comment_on_regular_parent_article(self): } res = self.http_request(self.user, "post", "comments", comment_data) - assert res.data["name_type"] == BoardNameType.REGULAR - assert Comment.objects.get(pk=res.data["id"]).name_type == BoardNameType.REGULAR + assert res.data["name_type"] == NameType.REGULAR + assert Comment.objects.get(pk=res.data["id"]).name_type == NameType.REGULAR def test_comment_on_regular_parent_comment(self): comment_str = "This is a comment on a regular parent comment" @@ -383,7 +374,7 @@ def test_comment_on_regular_parent_comment(self): self.http_request(self.user, "post", "comments", comment_data) assert ( Comment.objects.filter(content=comment_str).first().name_type - == BoardNameType.REGULAR + == NameType.REGULAR ) def test_comment_on_anonymous_parent_article(self): @@ -397,7 +388,7 @@ def test_comment_on_anonymous_parent_article(self): self.http_request(self.user, "post", "comments", comment_data) assert ( Comment.objects.filter(content=comment_str).first().name_type - == BoardNameType.ANONYMOUS + == NameType.ANONYMOUS ) def test_comment_on_anonymous_parent_comment(self): @@ -409,10 +400,8 @@ def test_comment_on_anonymous_parent_comment(self): } res = self.http_request(self.user, "post", "comments", comment_data) - assert res.data["name_type"] == BoardNameType.ANONYMOUS - assert ( - Comment.objects.get(pk=res.data["id"]).name_type == BoardNameType.ANONYMOUS - ) + assert res.data["name_type"] == NameType.ANONYMOUS + assert Comment.objects.get(pk=res.data["id"]).name_type == NameType.ANONYMOUS def test_comment_on_deleted_article(self): deleted_article = Article.objects.create( @@ -430,7 +419,7 @@ def test_comment_on_deleted_article(self): { "content": "deleted article comment content", "parent_article": deleted_article.id, - "name_type": BoardNameType.REGULAR, + "name_type": NameType.REGULAR, }, ) assert res.status_code == status.HTTP_404_NOT_FOUND @@ -452,7 +441,7 @@ def test_comment_on_report_hidden_article(self): { "content": "report hidden article comment content", "parent_article": report_hidden_article.id, - "name_type": BoardNameType.REGULAR, + "name_type": NameType.REGULAR, }, ) assert res.status_code == status.HTTP_201_CREATED @@ -532,14 +521,14 @@ class TestRealnameComments(TestCase, RequestSetting): def test_get_realname_comment(self): comment1 = Comment.objects.create( content="Realname test comment1", - name_type=BoardNameType.REALNAME, + name_type=NameType.REALNAME, created_by=self.user_without_kaist_info, parent_article=self.realname_article, ) comment2 = Comment.objects.create( content="Realname test comment2", - name_type=BoardNameType.REALNAME, + name_type=NameType.REALNAME, created_by=self.user_with_kaist_info, parent_article=self.realname_article_without_kinfo, ) @@ -547,7 +536,7 @@ def test_get_realname_comment(self): res1 = self.http_request( self.user_without_kaist_info, "get", f"comments/{comment1.id}" ).data - assert res1.get("name_type") == BoardNameType.REALNAME + assert res1.get("name_type") == NameType.REALNAME assert ( res1.get("created_by")["username"] == comment1.created_by.profile.realname ) @@ -555,7 +544,7 @@ def test_get_realname_comment(self): res2 = self.http_request( self.user_with_kaist_info, "get", f"comments/{comment2.id}" ).data - assert res2.get("name_type") == BoardNameType.REALNAME + assert res2.get("name_type") == NameType.REALNAME assert ( res2.get("created_by")["username"] == comment2.created_by.profile.realname ) @@ -564,7 +553,7 @@ def test_get_realname_comment_by_article_writer(self): res = self.http_request( self.user_with_kaist_info, "get", f"comments/{self.realname_comment.id}" ).data - assert res.get("name_type") == BoardNameType.REALNAME + assert res.get("name_type") == NameType.REALNAME assert res.get("created_by")["username"] == gettext("author") def test_create_realname_comment(self): @@ -579,10 +568,8 @@ def test_create_realname_comment(self): res = self.http_request( self.user_with_kaist_info, "post", "comments", comment_data ).data - assert res.get("name_type") == BoardNameType.REALNAME - assert ( - Comment.objects.get(content=comment_str).name_type == BoardNameType.REALNAME - ) + assert res.get("name_type") == NameType.REALNAME + assert Comment.objects.get(content=comment_str).name_type == NameType.REALNAME def test_create_realname_subcomment(self): comment_str = "This is a subcomment on a realname comment" @@ -596,10 +583,8 @@ def test_create_realname_subcomment(self): res = self.http_request( self.user_with_kaist_info, "post", "comments", comment_data ).data - assert res.get("name_type") == BoardNameType.REALNAME - assert ( - Comment.objects.get(content=comment_str).name_type == BoardNameType.REALNAME - ) + assert res.get("name_type") == NameType.REALNAME + assert Comment.objects.get(content=comment_str).name_type == NameType.REALNAME def test_create_school_admin_comment(self): comment_str = "This is a school_admin comment on a realname article" @@ -613,10 +598,8 @@ def test_create_school_admin_comment(self): res = self.http_request( self.school_admin, "post", "comments", comment_data ).data - assert res.get("name_type") == BoardNameType.REGULAR - assert ( - Comment.objects.get(content=comment_str).name_type == BoardNameType.REGULAR - ) + assert res.get("name_type") == NameType.REGULAR + assert Comment.objects.get(content=comment_str).name_type == NameType.REGULAR def test_create_school_admin_subcomment(self): comment_str = "This is a school_admin subcomment on a realname comment" @@ -630,10 +613,8 @@ def test_create_school_admin_subcomment(self): res = self.http_request( self.school_admin, "post", "comments", comment_data ).data - assert res.get("name_type") == BoardNameType.REGULAR - assert ( - Comment.objects.get(content=comment_str).name_type == BoardNameType.REGULAR - ) + assert res.get("name_type") == NameType.REGULAR + assert Comment.objects.get(content=comment_str).name_type == NameType.REGULAR @pytest.mark.usefixtures( @@ -650,7 +631,7 @@ class TestHiddenComments(TestCase, RequestSetting): def _comment_factory(self, **comment_kwargs): return Comment.objects.create( content="example comment", - name_type=BoardNameType.REGULAR, + name_type=NameType.REGULAR, created_by=self.user, parent_article=self.article_regular, **comment_kwargs, @@ -673,7 +654,7 @@ def test_blocked_user_block(self): Block.objects.create(blocked_by=self.user, user=self.user2) comment2 = Comment.objects.create( content="example comment", - name_type=BoardNameType.REGULAR, + name_type=NameType.REGULAR, created_by=self.user2, parent_article=self.article_regular, ) diff --git a/tests/test_communication_article.py b/tests/test_communication_article.py index 3b38e7c3..bd44fee5 100644 --- a/tests/test_communication_article.py +++ b/tests/test_communication_article.py @@ -3,13 +3,12 @@ from unittest.mock import patch import pytest -from django.contrib.auth.models import User from django.utils import timezone -from rest_framework.status import HTTP_200_OK +from rest_framework.status import HTTP_200_OK, HTTP_400_BAD_REQUEST from rest_framework.test import APIClient from apps.core.models import Article, Board -from apps.core.models.board import BoardNameType +from apps.core.models.board import NameType from apps.core.models.communication_article import ( CommunicationArticle, SchoolResponseStatus, @@ -17,7 +16,8 @@ from apps.user.models import UserProfile from ara.settings import ANSWER_PERIOD, MIN_TIME from ara.settings.dev import SCHOOL_RESPONSE_VOTE_THRESHOLD -from tests.conftest import RequestSetting, TestCase + +from .conftest import RequestSetting, TestCase, Utils @pytest.fixture(scope="class") @@ -26,10 +26,8 @@ def set_communication_board(request): slug="with-school", ko_name="학교와의 게시판 (테스트)", en_name="With School (Test)", - ko_description="학교와의 게시판 (테스트)", - en_description="With School (Test)", is_school_communication=True, - name_type=BoardNameType.REALNAME, + name_type=NameType.REALNAME, read_access_mask=0b11011110, write_access_mask=0b11011010, ) @@ -41,8 +39,6 @@ def set_non_communication_board(request): slug="not with-school", ko_name="학교 아닌 게시판 (테스트)", en_name="Not With School (Test)", - ko_description="학교 아닌 게시판 (테스트)", - en_description="Not With School (Test)", is_school_communication=False, ) @@ -56,7 +52,7 @@ def set_article(request): content_text="Communication Article Content Text", created_by=request.cls.user, parent_board=request.cls.communication_board, - name_type=BoardNameType.REALNAME, + name_type=NameType.REALNAME, ) @@ -80,7 +76,6 @@ def set_communication_article(request): "set_communication_article", ) class TestCommunicationArticle(TestCase, RequestSetting): - # ======================================================================= # # Helper Functions # # ======================================================================= # @@ -89,29 +84,8 @@ def _get_communication_article_status(self, article): res = self.http_request(self.user, "get", f"articles/{article.id}") return res.data.get("communication_article_status") - def _create_dummy_users(self, num): - dummy_users = [] - for i in range(num): - user, created = User.objects.get_or_create( - username=f"DummyUser{i}", email=f"dummy_user{i}@sparcs.org" - ) - if created: - UserProfile.objects.create( - user=user, - nickname=f"User{i} created at {timezone.now()}", - group=UserProfile.UserGroup.KAIST_MEMBER, - agree_terms_of_service_at=timezone.now(), - sso_user_info={ - "kaist_info": '{"ku_kname": "\\ud669"}', - "first_name": f"DummyUser{i}_FirstName", - "last_name": f"DummyUser{i}_LastName", - }, - ) - dummy_users.append(user) - return dummy_users - def _add_positive_votes(self, article, num): - dummy_users = self._create_dummy_users(num) + dummy_users = Utils.create_users(num) for user in dummy_users: self.http_request(user, "post", f"articles/{article.id}/vote_positive") @@ -135,7 +109,7 @@ def _create_article_with_status( "content_text": "Content Text made in factory", "created_by": self.user.id, "parent_board": self.communication_board.id, - "name_type": BoardNameType.REALNAME, + "name_type": NameType.REALNAME.name, } res = self.http_request(self.user, "post", "articles", article_data) @@ -164,6 +138,7 @@ def test_create_communication_article(self): "content_text": "test_create_communication_article", "creted_by": self.user.id, "parent_board": self.communication_board.id, + "name_type": NameType.REALNAME.name, } self.http_request(self.user, "post", "articles", user_data) @@ -195,6 +170,7 @@ def test_non_communication_article(self): "content_text": "test_non_communication_article", "creted_by": self.user.id, "parent_board": self.non_communication_board.id, + "name_type": NameType.REGULAR.name, } self.http_request(self.user, "post", "articles", user_data) @@ -401,10 +377,10 @@ def test_anonymous_article(self): "content_text": "Content text of anonymous article", "created_by": self.user.id, "parent_board": self.communication_board.id, - "name_type": BoardNameType.ANONYMOUS, + "name_type": NameType.ANONYMOUS.name, } - res = self.http_request(self.user, "post", "articles", article_data).data - assert res.get("name_type") == BoardNameType.REALNAME + result = self.http_request(self.user, "post", "articles", article_data) + assert result.status_code == HTTP_400_BAD_REQUEST # 익명 댓글 작성 불가 확인 def test_anonymous_comment(self): @@ -412,10 +388,10 @@ def test_anonymous_comment(self): "content": "Anonymous comment", "created_by": self.user.id, "parent_article": self.article.id, - "name_type": BoardNameType.ANONYMOUS, + "name_type": NameType.ANONYMOUS, } res = self.http_request(self.user, "post", "comments", comment_data).data - assert res.get("name_type") == BoardNameType.REALNAME + assert res.get("name_type") == NameType.REALNAME # ======================================================================= # # School Admin # diff --git a/tests/test_i18n.py b/tests/test_i18n.py index 6b14a541..c8908b95 100644 --- a/tests/test_i18n.py +++ b/tests/test_i18n.py @@ -10,7 +10,6 @@ def test_nickname_update(self): update_data = { "see_sexual": False, "see_social": False, - "extra_preferences": '{"test": 1}', "nickname": "foo", } r = self.http_request( diff --git a/tests/test_notification.py b/tests/test_notification.py index 2c7d9657..86467f9a 100644 --- a/tests/test_notification.py +++ b/tests/test_notification.py @@ -10,8 +10,6 @@ def set_board(request): slug="free", ko_name="자유 게시판", en_name="Free Board", - ko_description="자유 게시판 입니다.", - en_description="This is a free board.", ) diff --git a/tests/test_recent.py b/tests/test_recent.py index 11e0d045..060ec588 100644 --- a/tests/test_recent.py +++ b/tests/test_recent.py @@ -6,7 +6,7 @@ from django.utils import timezone from apps.core.models import Article, Board, Topic -from apps.core.models.board import BoardNameType +from apps.core.models.board import NameType from tests.conftest import RequestSetting, TestCase @@ -16,8 +16,6 @@ def set_board(request): slug="test board", ko_name="테스트 게시판", en_name="Test Board", - ko_description="테스트 게시판입니다", - en_description="This is a board for testing", ) @@ -28,8 +26,6 @@ def set_topic(request): slug="test topic", ko_name="테스트 토픽", en_name="Test Topic", - ko_description="테스트용 토픽입니다", - en_description="This is topic for testing", parent_board=request.cls.board, ) @@ -43,7 +39,7 @@ def create_article(n): title=f"Test Article{n}", content=f"Content of test article {n}", content_text=f"Content_text of test article {n}", - name_type=BoardNameType.REGULAR, + name_type=NameType.REGULAR, is_content_sexual=False, is_content_social=False, hit_count=0, @@ -65,7 +61,6 @@ def set_index(request): def generate_order(string): - length = 10 # number of articles seed = int( hashlib.sha224(string.encode("utf-8")).hexdigest(), base=16 @@ -175,7 +170,6 @@ def test_read_same_article_multiple_times(self): # 매우 복잡한 읽기 패턴에 대한 테스트 def test_read_article_complex_pattern(self): - order, expected_order = generate_order("foobarbaz") # read articles in created order @@ -192,7 +186,6 @@ def test_read_article_complex_pattern(self): # 매우 복잡한 읽기 패턴에 대한 side_article 테스트 def test_read_article_complex_pattern_side_article(self): - order, expected_order = generate_order("foobarbaz") for num in order: @@ -213,7 +206,6 @@ def test_read_article_complex_pattern_side_article(self): # 매우 복잡한 읽기 패턴에 대한 검색 테스트 def test_read_article_complex_pattern_search(self): - order, expected_order = generate_order("foobarbaz") for num in order: @@ -243,7 +235,6 @@ def test_read_article_complex_pattern_search(self): # 매우 복잡한 읽기 패턴에 대한 검색 및 side_article 테스트 def test_read_article_complex_pattern_search_side_article(self): - order, expected_order = generate_order("foobarbaz") for num in order: @@ -275,7 +266,6 @@ def test_read_article_complex_pattern_search_side_article(self): # 첫 번째 읽기가 from_view=recent일 경우 테스트 def test_read_first_article_from_recent(self): - resp = self.http_request( self.user, "get", diff --git a/tests/test_report.py b/tests/test_report.py index 30b3a155..3ff04750 100644 --- a/tests/test_report.py +++ b/tests/test_report.py @@ -3,7 +3,7 @@ from django.utils import timezone from apps.core.models import Article, Board, Comment, Report, Topic -from apps.core.models.board import BoardNameType +from apps.core.models.board import NameType from tests.conftest import RequestSetting, TestCase @@ -13,8 +13,6 @@ def set_board(request): slug="test board", ko_name="테스트 게시판", en_name="Test Board", - ko_description="테스트 게시판입니다", - en_description="This is a board for testing", ) @@ -25,8 +23,6 @@ def set_topic(request): slug="test topic", ko_name="테스트 토픽", en_name="Test Topic", - ko_description="테스트용 토픽입니다", - en_description="This is topic for testing", parent_board=request.cls.board, ) @@ -38,7 +34,7 @@ def set_article(request): title="Test Article", content="Content of test article", content_text="Content of test article in text", - name_type=BoardNameType.REGULAR, + name_type=NameType.REGULAR, is_content_sexual=False, is_content_social=False, hit_count=0, @@ -56,7 +52,7 @@ def set_comment(request): """set_article 먼저 적용""" request.cls.comment = Comment.objects.create( content="this is a test comment", - name_type=BoardNameType.REGULAR, + name_type=NameType.REGULAR, created_by=request.cls.user, parent_article=request.cls.article, ) diff --git a/tests/test_scrap.py b/tests/test_scrap.py index 84110ab0..32146634 100644 --- a/tests/test_scrap.py +++ b/tests/test_scrap.py @@ -11,8 +11,6 @@ def set_board(request): slug="free", ko_name="자유 게시판", en_name="Free Board", - ko_description="자유 게시판 입니다.", - en_description="This is a free board.", ) diff --git a/tests/test_user.py b/tests/test_user.py index 96674583..eddae31b 100644 --- a/tests/test_user.py +++ b/tests/test_user.py @@ -6,7 +6,7 @@ from django.utils import timezone from apps.core.models import Article, Board, Comment -from apps.core.models.board import BoardNameType +from apps.core.models.board import NameType from ara.settings import MIN_TIME from tests.conftest import RequestSetting, TestCase @@ -17,17 +17,13 @@ def set_boards(request): slug="test board", ko_name="테스트 게시판", en_name="Test Board", - ko_description="테스트 게시판입니다", - en_description="This is a board for testing", ) request.cls.realname_board = Board.objects.create( slug="realname", ko_name="실명 게시판", en_name="Realname Board", - ko_description="실명 게시판", - en_description="Realname Board", - name_type=BoardNameType.REALNAME, + name_type=NameType.REALNAME, ) @@ -37,7 +33,7 @@ def set_articles(request): common_kwargs = { "content": "example content", "content_text": "example content text", - "name_type": BoardNameType.REGULAR, + "name_type": NameType.REGULAR, "created_by": request.cls.user2, "parent_board": request.cls.board, "hit_count": 0, @@ -80,7 +76,7 @@ def set_anonymous_article(request): title="익명글", is_content_sexual=False, is_content_social=False, - name_type=BoardNameType.ANONYMOUS, + name_type=NameType.ANONYMOUS, content="example content", content_text="example content text", created_by=request.cls.user2, @@ -96,7 +92,7 @@ def set_realname_article(request): title="실명글", is_content_sexual=False, is_content_social=False, - name_type=BoardNameType.REALNAME, + name_type=NameType.REALNAME, content="example content", content_text="example content text", created_by=request.cls.user_with_kaist_info, @@ -110,7 +106,7 @@ def set_anonymous_comment(request): """set_anonymous_articles 먼저 적용""" request.cls.comment_anonymous = Comment.objects.create( content="example comment", - name_type=BoardNameType.ANONYMOUS, + name_type=NameType.ANONYMOUS, created_by=request.cls.user, parent_article=request.cls.article_anonymous, ) @@ -121,7 +117,7 @@ def set_realname_comment(request): """set_realname_article, set_user_with_kaist_info 먼저 적용""" request.cls.realname_comment = Comment.objects.create( content="example comment", - name_type=BoardNameType.REALNAME, + name_type=NameType.REALNAME, created_by=request.cls.user_with_kaist_info, parent_article=request.cls.realname_article, ) @@ -142,12 +138,10 @@ def test_profile_edit(self): assert res.data.get("see_sexual") == self.user.profile.see_sexual assert res.data.get("see_social") == self.user.profile.see_social assert res.data.get("nickname") == self.user.profile.nickname - assert res.data.get("extra_preferences") == self.user.profile.extra_preferences update_data = { "see_sexual": True, "see_social": True, - "extra_preferences": '{"test": 1}', } res = self.http_request( self.user, "put", f"user_profiles/{self.user.id}", data=update_data @@ -156,7 +150,6 @@ def test_profile_edit(self): res = self.http_request(self.user, "get", f"user_profiles/{self.user.id}") assert res.data.get("see_sexual") assert res.data.get("see_social") - assert res.data.get("extra_preferences") == '{"test": 1}' def test_filter_articles_list(self): # 사용자의 게시물 필터에 따라 게시물 목록에서 필터링이 잘 되는지 테스트합니다. @@ -218,7 +211,6 @@ def test_nickname_update(self): update_data = { "see_sexual": False, "see_social": False, - "extra_preferences": '{"test": 1}', "nickname": "foo", } r = self.http_request(