diff --git a/AHC_app/.env.template b/.env.template similarity index 90% rename from AHC_app/.env.template rename to .env.template index 6fe5166..fcf11b7 100644 --- a/AHC_app/.env.template +++ b/.env.template @@ -1,3 +1,8 @@ +# Django core +SECRET_KEY= +DEBUG=True +ALLOWED_HOSTS=localhost,127.0.0.1 + # PostgresDB for docker-compose.yml - dev POSTGRES_DB= POSTGRES_USER= diff --git a/.gitattributes b/.gitattributes index dfe0770..6915582 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,6 @@ # Auto detect text files and perform LF normalization * text=auto + +# Vendor static files — preserve LF line endings as published +static/**/* text eol=lf +static_collected/**/* text eol=lf diff --git a/.github/workflows/django.yml b/.github/workflows/django.yml index 37ee701..65986f7 100644 --- a/.github/workflows/django.yml +++ b/.github/workflows/django.yml @@ -8,7 +8,7 @@ on: jobs: test: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest env: POSTGRES_DB: ${{ secrets.POSTGRES_DB }} POSTGRES_USER: ${{ secrets.POSTGRES_USER }} @@ -34,51 +34,26 @@ jobs: EMAIL_HOST_PASSWORD: ${{ secrets.EMAIL_HOST_PASSWORD }} DISCORD_TOKEN: ${{ secrets.DISCORD_TOKEN }} PYTHONUNBUFFERED: "1" - PYTHONPATH: "/home/runner/work/Animals_Healthcare_Application/Animals_Healthcare_Application/AHC_app" -# strategy: -# max-parallel: 4 steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - - name: Setup Python - uses: actions/setup-python@v5 + - name: Setup uv + uses: astral-sh/setup-uv@v3 with: - python-version: 3.12 - - - name: Install PostgreSQL dependencies - run: sudo apt-get install -y libpq-dev - - - name: Install pipenv - run: pip install pipenv - - - name: Prepare environment - run: | - cd ./AHC_app - pipenv install --dev - pipenv graph + enable-cache: true + cache-dependency-glob: "uv.lock" + python-version: "3.14" - - name: Show Python version - run: python --version - working-directory: ./AHC_app + - name: Install dependencies + run: uv sync - - name: Show pip version - run: pip --version - working-directory: ./AHC_app + - name: Run tests (Django runner) + run: PYTHONPATH=src uv run python manage.py test - - name: Show pipenv version - run: pipenv --version - working-directory: ./AHC_app - - - name: List installed packages - run: pipenv run pip list - working-directory: ./AHC_app - - - name: Prepare environment and run tests - run: | - PYTHONPATH=$(pwd) pipenv run python manage.py test - working-directory: ./AHC_app + - name: Run tests (pytest) + run: uv run pytest -m "not slow" build-and-push: name: Build and Push to ECR @@ -87,7 +62,7 @@ jobs: if: ${{ github.ref == 'refs/heads/main' }} steps: - name: Checkout Repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v1 @@ -106,8 +81,8 @@ jobs: ECR_URI: ${{ secrets.ECR_URI_APPENDIXES_DB }} IMAGE_TAG: latest run: | - docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG . - docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG + docker build -t $ECR_URI:$IMAGE_TAG . + docker push $ECR_URI:$IMAGE_TAG - name: Build, tag and push the celery-flower image to ECR id: build-image-celery-flower diff --git a/.gitignore b/.gitignore index f3464e5..afebe7a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,165 +1,63 @@ -# Byte-compiled / optimized / DLL files +# Python __pycache__/ *.py[cod] -*$py.class - -# C extensions *.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -share/python-wheels/ -*.egg-info/ -.installed.cfg *.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt +*.egg-info/ +.Python -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ +# Testing .coverage .coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py,cover -.hypothesis/ +htmlcov/ .pytest_cache/ -cover/ - -# Translations -*.mo -*.pot +.hypothesis/ -# Django stuff: +# Django *.log local_settings.py db.sqlite3 db.sqlite3-journal -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -.pybuilder/ -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# poetry -# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control -#poetry.lock - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - # Environments .env -.venv +.venv/ env/ venv/ -ENV/ -env.bak/ -venv.bak/ -# Spyder project settings -.spyderproject -.spyproject +# uv — commit uv.lock, do NOT add it here +# .python-version is intentionally tracked -# Rope project settings -.ropeproject +# Build / packaging +build/ +dist/ +wheels/ -# mkdocs documentation -/site +# Celery +celerybeat-schedule +celerybeat.pid -# mypy +# Type checkers .mypy_cache/ .dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ +.ty_cache/ -# Cython debug symbols -cython_debug/ +# Claude Code — not tracked in this repository +.claude/ +CLAUDE.md -# PyCharm -# JetBrains specific template is maintainted in a separate JetBrains.gitignore that can -# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore -# and can be added to the global gitignore or merged into this file. For a more nuclear -# option (not recommended) you can uncomment the following to ignore the entire idea folder. +# IDE .idea/ -# Collected static files - temporary -/AHC_app/static_collected/ -/AHC_app/static/media/profile_pics/animals/ -/AHC_app/static/media/attachments/ +# Project-specific +/static_collected/ +/static/media/profile_pics/animals/ +/static/media/attachments/ -# Kubernetes configuration -/AHC_app/tars/ +# Kubernetes +/tars/ /kubernetes/**/*.tar secret.yaml -# volumens +# Volumes /db/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..c3e1185 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,41 @@ +exclude: 'static/|static_collected/' + +repos: +- repo: local + hooks: + - id: uv-lock-check + name: uv lock --check + entry: uv lock --check + language: system + pass_filenames: false + files: ^pyproject\.toml$ + +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: end-of-file-fixer + exclude: '\.sh$' + - id: trailing-whitespace + +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.15.14 + hooks: + - id: ruff-check + args: [--fix] + - id: ruff-format + +- repo: https://github.com/codespell-project/codespell + rev: v2.4.2 + hooks: + - id: codespell + types_or: [python, markdown, yaml] + +- repo: local + hooks: + - id: bandit + name: bandit + entry: bandit -r src -c pyproject.toml -q + language: python + additional_dependencies: ["bandit[toml]==1.9.4"] + pass_filenames: false + always_run: true diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..6324d40 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.14 diff --git a/AHC_app/.dockerignore b/AHC_app/.dockerignore deleted file mode 100644 index 1b1aaee..0000000 --- a/AHC_app/.dockerignore +++ /dev/null @@ -1,2 +0,0 @@ -./tars/* -*.tar diff --git a/AHC_app/.pre-commit-config.yaml b/AHC_app/.pre-commit-config.yaml deleted file mode 100644 index 7f61623..0000000 --- a/AHC_app/.pre-commit-config.yaml +++ /dev/null @@ -1,29 +0,0 @@ -repos: -- repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 - hooks: - - id: end-of-file-fixer - exclude: '\.sh$' - - id: trailing-whitespace -- repo: https://github.com/PyCQA/autoflake - rev: v2.1.1 - hooks: - - id: autoflake - name: autoflake - entry: autoflake - language: python - types: [python] - require_serial: true - args: ['--in-place', '--remove-all-unused-imports'] - exclude: '^requirements\.txt$|^setup_couchdb\.sh$|^.yaml$' -- repo: https://github.com/PyCQA/isort - rev: 5.12.0 - hooks: - - id: isort - args: ['--profile', 'black', '--lines-between-types', '1', '--filter-files'] -- repo: https://github.com/psf/black - rev: 22.3.0 - hooks: - - id: black - language_version: python3.12 - args: ['--line-length', '120'] diff --git a/AHC_app/Dockerfile-queue b/AHC_app/Dockerfile-queue deleted file mode 100644 index 0cc351b..0000000 --- a/AHC_app/Dockerfile-queue +++ /dev/null @@ -1,10 +0,0 @@ -FROM python:3.12 -LABEL authors="AM" -WORKDIR /app -COPY Pipfile Pipfile.lock ./ - -RUN python -m pip install --upgrade pip && \ - pip install --no-cache-dir pipenv && \ - pipenv install --dev --system --deploy - -COPY . . diff --git a/AHC_app/Dockerfile-web b/AHC_app/Dockerfile-web deleted file mode 100644 index a664b69..0000000 --- a/AHC_app/Dockerfile-web +++ /dev/null @@ -1,13 +0,0 @@ -FROM python:3.12 -LABEL authors="AM" -WORKDIR /app -COPY Pipfile Pipfile.lock ./ - -RUN python -m pip install --upgrade pip && \ - pip install --no-cache-dir pipenv && \ - pipenv install --dev --system --deploy - -RUN apt-get update && \ - apt-get install -y cron - -COPY . . diff --git a/AHC_app/Pipfile b/AHC_app/Pipfile deleted file mode 100644 index 8fa3083..0000000 --- a/AHC_app/Pipfile +++ /dev/null @@ -1,81 +0,0 @@ -[[source]] -url = "https://pypi.org/simple" -verify_ssl = true -name = "pypi" - -[packages] -amqp = "==5.1.1" -billiard = "==4.1.0" -cachetools = "==5.3.2" -certifi = "==2023.7.22" -cffi = "==1.16.0" -charset-normalizer = "==3.3.1" -click = "==8.1.7" -click-didyoumean = "==0.3.0" -click-plugins = "==1.1.1" -click-repl = "==0.3.0" -colorama = "==0.4.6" -contourpy = "==1.0.7" -couchdb = "==1.2" -crispy-bootstrap4 = "==2022.1" -cryptography = "==41.0.5" -cycler = "==0.11.0" -defusedxml = "==0.7.1" -django-appconf = "==1.0.5" -django-bootstrap-modal-forms = "==3.0.4" -django-compressor = "==4.4" -django-crispy-forms = "==2.0" -django-crontab = "==0.7.1" -django-libsass = "==0.9" -django-taggit = "==4.0.0" -django-timezone-field = "==6.0.1" -djangorestframework = "==3.14.0" -fonttools = "==4.39.4" -httplib2 = "==0.22.0" -idna = "==3.4" -kiwisolver = "==1.4.4" -kombu = "==5.3.2" -libsass = "==0.22.0" -oauthlib = "==3.2.2" -packaging = "==23.1" -pillow = "==9.5.0" -prompt-toolkit = "==3.0.39" -psycopg2 = "==2.9.6" -pyasn1 = "==0.5.0" -pyasn1-modules = "==0.3.0" -pycparser = "==2.21" -pyjwt = "==2.8.0" -pyparsing = "==3.0.9" -python-dateutil = "==2.8.2" -python3-openid = "==3.2.0" -pytz = "==2023.3" -rcssmin = "==1.1.1" -redis = "==5.0.1" -requests = "==2.31.0" -requests-oauthlib = "==1.3.1" -rjsmin = "==1.2.1" -rsa = "==4.9" -six = "==1.16.0" -sqlparse = "==0.4.4" -tzdata = "==2023.3" -urllib3 = "==2.0.7" -vine = "==5.0.0" -wcwidth = "==0.2.8" -icecream = "*" -flower = "*" -django-cron = "*" -python-decouple = "*" -pycouchdb = "*" -discord = "*" -django-ajax = "*" -psycopg2-binary = "*" -django = "==4.2.11" -celery = "5.3.4" - -[dev-packages] -pre-commit = "*" -isort = "*" -black = "*" - -[requires] -python_version = "3.12" diff --git a/AHC_app/Pipfile.lock b/AHC_app/Pipfile.lock deleted file mode 100644 index ddf2690..0000000 --- a/AHC_app/Pipfile.lock +++ /dev/null @@ -1,1786 +0,0 @@ -{ - "_meta": { - "hash": { - - "sha256": "adc7b4e1a58ad54950df7b0133e5a7ddaa4bd8dbcb727885188ac9528a5c3c24" - - }, - "pipfile-spec": 6, - "requires": { - "python_version": "3.12" - }, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "aiohttp": { - "hashes": [ - - "sha256:0605cc2c0088fcaae79f01c913a38611ad09ba68ff482402d3410bf59039bfb8", - "sha256:0a158704edf0abcac8ac371fbb54044f3270bdbc93e254a82b6c82be1ef08f3c", - "sha256:0cbf56238f4bbf49dab8c2dc2e6b1b68502b1e88d335bea59b3f5b9f4c001475", - "sha256:1732102949ff6087589408d76cd6dea656b93c896b011ecafff418c9661dc4ed", - "sha256:18f634d540dd099c262e9f887c8bbacc959827cfe5da7a0e2e1cf3f14dbf2daf", - "sha256:239f975589a944eeb1bad26b8b140a59a3a320067fb3cd10b75c3092405a1372", - "sha256:2faa61a904b83142747fc6a6d7ad8fccff898c849123030f8e75d5d967fd4a81", - "sha256:320e8618eda64e19d11bdb3bd04ccc0a816c17eaecb7e4945d01deee2a22f95f", - "sha256:38d80498e2e169bc61418ff36170e0aad0cd268da8b38a17c4cf29d254a8b3f1", - "sha256:3916c8692dbd9d55c523374a3b8213e628424d19116ac4308e434dbf6d95bbdd", - "sha256:393c7aba2b55559ef7ab791c94b44f7482a07bf7640d17b341b79081f5e5cd1a", - "sha256:3b7b30258348082826d274504fbc7c849959f1989d86c29bc355107accec6cfb", - "sha256:3fcb4046d2904378e3aeea1df51f697b0467f2aac55d232c87ba162709478c46", - "sha256:4109adee842b90671f1b689901b948f347325045c15f46b39797ae1bf17019de", - "sha256:4558e5012ee03d2638c681e156461d37b7a113fe13970d438d95d10173d25f78", - "sha256:45731330e754f5811c314901cebdf19dd776a44b31927fa4b4dbecab9e457b0c", - "sha256:4715a9b778f4293b9f8ae7a0a7cef9829f02ff8d6277a39d7f40565c737d3771", - "sha256:471f0ef53ccedec9995287f02caf0c068732f026455f07db3f01a46e49d76bbb", - "sha256:4d3ebb9e1316ec74277d19c5f482f98cc65a73ccd5430540d6d11682cd857430", - "sha256:4ff550491f5492ab5ed3533e76b8567f4b37bd2995e780a1f46bca2024223233", - "sha256:52c27110f3862a1afbcb2af4281fc9fdc40327fa286c4625dfee247c3ba90156", - "sha256:55b39c8684a46e56ef8c8d24faf02de4a2b2ac60d26cee93bc595651ff545de9", - "sha256:5a7ee16aab26e76add4afc45e8f8206c95d1d75540f1039b84a03c3b3800dd59", - "sha256:5ca51eadbd67045396bc92a4345d1790b7301c14d1848feaac1d6a6c9289e888", - "sha256:5d6b3f1fabe465e819aed2c421a6743d8debbde79b6a8600739300630a01bf2c", - "sha256:60cdbd56f4cad9f69c35eaac0fbbdf1f77b0ff9456cebd4902f3dd1cf096464c", - "sha256:6380c039ec52866c06d69b5c7aad5478b24ed11696f0e72f6b807cfb261453da", - "sha256:639d0042b7670222f33b0028de6b4e2fad6451462ce7df2af8aee37dcac55424", - "sha256:66331d00fb28dc90aa606d9a54304af76b335ae204d1836f65797d6fe27f1ca2", - "sha256:67c3119f5ddc7261d47163ed86d760ddf0e625cd6246b4ed852e82159617b5fb", - "sha256:694d828b5c41255e54bc2dddb51a9f5150b4eefa9886e38b52605a05d96566e8", - "sha256:6ae79c1bc12c34082d92bf9422764f799aee4746fd7a392db46b7fd357d4a17a", - "sha256:702e2c7c187c1a498a4e2b03155d52658fdd6fda882d3d7fbb891a5cf108bb10", - "sha256:714d4e5231fed4ba2762ed489b4aec07b2b9953cf4ee31e9871caac895a839c0", - "sha256:7b179eea70833c8dee51ec42f3b4097bd6370892fa93f510f76762105568cf09", - "sha256:7f64cbd44443e80094309875d4f9c71d0401e966d191c3d469cde4642bc2e031", - "sha256:82a6a97d9771cb48ae16979c3a3a9a18b600a8505b1115cfe354dfb2054468b4", - "sha256:84dabd95154f43a2ea80deffec9cb44d2e301e38a0c9d331cc4aa0166fe28ae3", - "sha256:8676e8fd73141ded15ea586de0b7cda1542960a7b9ad89b2b06428e97125d4fa", - "sha256:88e311d98cc0bf45b62fc46c66753a83445f5ab20038bcc1b8a1cc05666f428a", - "sha256:8b4f72fbb66279624bfe83fd5eb6aea0022dad8eec62b71e7bf63ee1caadeafe", - "sha256:8c64a6dc3fe5db7b1b4d2b5cb84c4f677768bdc340611eca673afb7cf416ef5a", - "sha256:8cf142aa6c1a751fcb364158fd710b8a9be874b81889c2bd13aa8893197455e2", - "sha256:8d1964eb7617907c792ca00b341b5ec3e01ae8c280825deadbbd678447b127e1", - "sha256:93e22add827447d2e26d67c9ac0161756007f152fdc5210277d00a85f6c92323", - "sha256:9c69e77370cce2d6df5d12b4e12bdcca60c47ba13d1cbbc8645dd005a20b738b", - "sha256:9dbc053ac75ccc63dc3a3cc547b98c7258ec35a215a92bd9f983e0aac95d3d5b", - "sha256:9e3a1ae66e3d0c17cf65c08968a5ee3180c5a95920ec2731f53343fac9bad106", - "sha256:a6ea1a5b409a85477fd8e5ee6ad8f0e40bf2844c270955e09360418cfd09abac", - "sha256:a81b1143d42b66ffc40a441379387076243ef7b51019204fd3ec36b9f69e77d6", - "sha256:ad7f2919d7dac062f24d6f5fe95d401597fbb015a25771f85e692d043c9d7832", - "sha256:afc52b8d969eff14e069a710057d15ab9ac17cd4b6753042c407dcea0e40bf75", - "sha256:b3df71da99c98534be076196791adca8819761f0bf6e08e07fd7da25127150d6", - "sha256:c088c4d70d21f8ca5c0b8b5403fe84a7bc8e024161febdd4ef04575ef35d474d", - "sha256:c26959ca7b75ff768e2776d8055bf9582a6267e24556bb7f7bd29e677932be72", - "sha256:c413016880e03e69d166efb5a1a95d40f83d5a3a648d16486592c49ffb76d0db", - "sha256:c6021d296318cb6f9414b48e6a439a7f5d1f665464da507e8ff640848ee2a58a", - "sha256:c671dc117c2c21a1ca10c116cfcd6e3e44da7fcde37bf83b2be485ab377b25da", - "sha256:c7a4b7a6cf5b6eb11e109a9755fd4fda7d57395f8c575e166d363b9fc3ec4678", - "sha256:c8a02fbeca6f63cb1f0475c799679057fc9268b77075ab7cf3f1c600e81dd46b", - "sha256:cd2adf5c87ff6d8b277814a28a535b59e20bfea40a101db6b3bdca7e9926bc24", - "sha256:d1469f228cd9ffddd396d9948b8c9cd8022b6d1bf1e40c6f25b0fb90b4f893ed", - "sha256:d153f652a687a8e95ad367a86a61e8d53d528b0530ef382ec5aaf533140ed00f", - "sha256:d5ab8e1f6bee051a4bf6195e38a5c13e5e161cb7bad83d8854524798bd9fcd6e", - "sha256:da00da442a0e31f1c69d26d224e1efd3a1ca5bcbf210978a2ca7426dfcae9f58", - "sha256:da22dab31d7180f8c3ac7c7635f3bcd53808f374f6aa333fe0b0b9e14b01f91a", - "sha256:e0ae53e33ee7476dd3d1132f932eeb39bf6125083820049d06edcdca4381f342", - "sha256:e7a6a8354f1b62e15d48e04350f13e726fa08b62c3d7b8401c0a1314f02e3558", - "sha256:e9a3d838441bebcf5cf442700e3963f58b5c33f015341f9ea86dcd7d503c07e2", - "sha256:edea7d15772ceeb29db4aff55e482d4bcfb6ae160ce144f2682de02f6d693551", - "sha256:f22eb3a6c1080d862befa0a89c380b4dafce29dc6cd56083f630073d102eb595", - "sha256:f26383adb94da5e7fb388d441bf09c61e5e35f455a3217bfd790c6b6bc64b2ee", - "sha256:f3c2890ca8c59ee683fd09adf32321a40fe1cf164e3387799efb2acebf090c11", - "sha256:f64fd07515dad67f24b6ea4a66ae2876c01031de91c93075b8093f07c0a2d93d", - "sha256:fcde4c397f673fdec23e6b05ebf8d4751314fa7c24f93334bf1f1364c1c69ac7", - "sha256:ff84aeb864e0fac81f676be9f4685f0527b660f1efdc40dcede3c251ef1e867f" - ], - "markers": "python_version >= '3.8'", - "version": "==3.9.5" - - }, - "aiosignal": { - "hashes": [ - "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc", - "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17" - ], - "markers": "python_version >= '3.7'", - "version": "==1.3.1" - }, - "amqp": { - "hashes": [ - "sha256:2c1b13fecc0893e946c65cbd5f36427861cffa4ea2201d8f6fca22e2a373b5e2", - "sha256:6f0956d2c23d8fa6e7691934d8c3930eadb44972cbbd1a7ae3a520f735d43359" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==5.1.1" - }, - "asgiref": { - "hashes": [ - "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47", - "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590" - ], - - "markers": "python_version >= '3.8'", - "version": "==3.8.1" - - }, - "asttokens": { - "hashes": [ - "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24", - "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0" - ], - "version": "==2.4.1" - }, - "attrs": { - "hashes": [ - "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30", - "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1" - ], - "markers": "python_version >= '3.7'", - "version": "==23.2.0" - }, - "billiard": { - "hashes": [ - "sha256:0f50d6be051c6b2b75bfbc8bfd85af195c5739c281d3f5b86a5640c65563614a", - "sha256:1ad2eeae8e28053d729ba3373d34d9d6e210f6e4d8bf0a9c64f92bd053f1edf5" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==4.1.0" - }, - "cachetools": { - "hashes": [ - "sha256:086ee420196f7b2ab9ca2db2520aca326318b68fe5ba8bc4d49cca91add450f2", - "sha256:861f35a13a451f94e301ce2bec7cac63e881232ccce7ed67fab9b5df4d3beaa1" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==5.3.2" - }, - "celery": { - "hashes": [ - "sha256:1e6ed40af72695464ce98ca2c201ad0ef8fd192246f6c9eac8bba343b980ad34", - "sha256:9023df6a8962da79eb30c0c84d5f4863d9793a466354cc931d7f72423996de28" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==5.3.4" - }, - "certifi": { - "hashes": [ - "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082", - "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==2023.7.22" - }, - "cffi": { - "hashes": [ - "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc", - "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a", - "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417", - "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab", - "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520", - "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36", - "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743", - "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8", - "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed", - "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684", - "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56", - "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324", - "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d", - "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235", - "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e", - "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088", - "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000", - "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7", - "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e", - "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673", - "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c", - "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe", - "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2", - "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098", - "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8", - "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a", - "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0", - "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b", - "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896", - "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e", - "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9", - "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2", - "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b", - "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6", - "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404", - "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f", - "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0", - "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4", - "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc", - "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936", - "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba", - "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872", - "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb", - "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614", - "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1", - "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d", - "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969", - "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b", - "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4", - "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627", - "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956", - "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==1.16.0" - }, - "charset-normalizer": { - "hashes": [ - "sha256:06cf46bdff72f58645434d467bf5228080801298fbba19fe268a01b4534467f5", - "sha256:0c8c61fb505c7dad1d251c284e712d4e0372cef3b067f7ddf82a7fa82e1e9a93", - "sha256:10b8dd31e10f32410751b3430996f9807fc4d1587ca69772e2aa940a82ab571a", - "sha256:1171ef1fc5ab4693c5d151ae0fdad7f7349920eabbaca6271f95969fa0756c2d", - "sha256:17a866d61259c7de1bdadef418a37755050ddb4b922df8b356503234fff7932c", - "sha256:1d6bfc32a68bc0933819cfdfe45f9abc3cae3877e1d90aac7259d57e6e0f85b1", - "sha256:1ec937546cad86d0dce5396748bf392bb7b62a9eeb8c66efac60e947697f0e58", - "sha256:223b4d54561c01048f657fa6ce41461d5ad8ff128b9678cfe8b2ecd951e3f8a2", - "sha256:2465aa50c9299d615d757c1c888bc6fef384b7c4aec81c05a0172b4400f98557", - "sha256:28f512b9a33235545fbbdac6a330a510b63be278a50071a336afc1b78781b147", - "sha256:2c092be3885a1b7899cd85ce24acedc1034199d6fca1483fa2c3a35c86e43041", - "sha256:2c4c99f98fc3a1835af8179dcc9013f93594d0670e2fa80c83aa36346ee763d2", - "sha256:31445f38053476a0c4e6d12b047b08ced81e2c7c712e5a1ad97bc913256f91b2", - "sha256:31bbaba7218904d2eabecf4feec0d07469284e952a27400f23b6628439439fa7", - "sha256:34d95638ff3613849f473afc33f65c401a89f3b9528d0d213c7037c398a51296", - "sha256:352a88c3df0d1fa886562384b86f9a9e27563d4704ee0e9d56ec6fcd270ea690", - "sha256:39b70a6f88eebe239fa775190796d55a33cfb6d36b9ffdd37843f7c4c1b5dc67", - "sha256:3c66df3f41abee950d6638adc7eac4730a306b022570f71dd0bd6ba53503ab57", - "sha256:3f70fd716855cd3b855316b226a1ac8bdb3caf4f7ea96edcccc6f484217c9597", - "sha256:3f9bc2ce123637a60ebe819f9fccc614da1bcc05798bbbaf2dd4ec91f3e08846", - "sha256:3fb765362688821404ad6cf86772fc54993ec11577cd5a92ac44b4c2ba52155b", - "sha256:45f053a0ece92c734d874861ffe6e3cc92150e32136dd59ab1fb070575189c97", - "sha256:46fb9970aa5eeca547d7aa0de5d4b124a288b42eaefac677bde805013c95725c", - "sha256:4cb50a0335382aac15c31b61d8531bc9bb657cfd848b1d7158009472189f3d62", - "sha256:4e12f8ee80aa35e746230a2af83e81bd6b52daa92a8afaef4fea4a2ce9b9f4fa", - "sha256:4f3100d86dcd03c03f7e9c3fdb23d92e32abbca07e7c13ebd7ddfbcb06f5991f", - "sha256:4f6e2a839f83a6a76854d12dbebde50e4b1afa63e27761549d006fa53e9aa80e", - "sha256:4f861d94c2a450b974b86093c6c027888627b8082f1299dfd5a4bae8e2292821", - "sha256:501adc5eb6cd5f40a6f77fbd90e5ab915c8fd6e8c614af2db5561e16c600d6f3", - "sha256:520b7a142d2524f999447b3a0cf95115df81c4f33003c51a6ab637cbda9d0bf4", - "sha256:548eefad783ed787b38cb6f9a574bd8664468cc76d1538215d510a3cd41406cb", - "sha256:555fe186da0068d3354cdf4bbcbc609b0ecae4d04c921cc13e209eece7720727", - "sha256:55602981b2dbf8184c098bc10287e8c245e351cd4fdcad050bd7199d5a8bf514", - "sha256:58e875eb7016fd014c0eea46c6fa92b87b62c0cb31b9feae25cbbe62c919f54d", - "sha256:5a3580a4fdc4ac05f9e53c57f965e3594b2f99796231380adb2baaab96e22761", - "sha256:5b70bab78accbc672f50e878a5b73ca692f45f5b5e25c8066d748c09405e6a55", - "sha256:5ceca5876032362ae73b83347be8b5dbd2d1faf3358deb38c9c88776779b2e2f", - "sha256:61f1e3fb621f5420523abb71f5771a204b33c21d31e7d9d86881b2cffe92c47c", - "sha256:633968254f8d421e70f91c6ebe71ed0ab140220469cf87a9857e21c16687c034", - "sha256:63a6f59e2d01310f754c270e4a257426fe5a591dc487f1983b3bbe793cf6bac6", - "sha256:63accd11149c0f9a99e3bc095bbdb5a464862d77a7e309ad5938fbc8721235ae", - "sha256:6db3cfb9b4fcecb4390db154e75b49578c87a3b9979b40cdf90d7e4b945656e1", - "sha256:71ef3b9be10070360f289aea4838c784f8b851be3ba58cf796262b57775c2f14", - "sha256:7ae8e5142dcc7a49168f4055255dbcced01dc1714a90a21f87448dc8d90617d1", - "sha256:7b6cefa579e1237ce198619b76eaa148b71894fb0d6bcf9024460f9bf30fd228", - "sha256:800561453acdecedaac137bf09cd719c7a440b6800ec182f077bb8e7025fb708", - "sha256:82ca51ff0fc5b641a2d4e1cc8c5ff108699b7a56d7f3ad6f6da9dbb6f0145b48", - "sha256:851cf693fb3aaef71031237cd68699dded198657ec1e76a76eb8be58c03a5d1f", - "sha256:854cc74367180beb327ab9d00f964f6d91da06450b0855cbbb09187bcdb02de5", - "sha256:87071618d3d8ec8b186d53cb6e66955ef2a0e4fa63ccd3709c0c90ac5a43520f", - "sha256:871d045d6ccc181fd863a3cd66ee8e395523ebfbc57f85f91f035f50cee8e3d4", - "sha256:8aee051c89e13565c6bd366813c386939f8e928af93c29fda4af86d25b73d8f8", - "sha256:8af5a8917b8af42295e86b64903156b4f110a30dca5f3b5aedea123fbd638bff", - "sha256:8ec8ef42c6cd5856a7613dcd1eaf21e5573b2185263d87d27c8edcae33b62a61", - "sha256:91e43805ccafa0a91831f9cd5443aa34528c0c3f2cc48c4cb3d9a7721053874b", - "sha256:9505dc359edb6a330efcd2be825fdb73ee3e628d9010597aa1aee5aa63442e97", - "sha256:985c7965f62f6f32bf432e2681173db41336a9c2611693247069288bcb0c7f8b", - "sha256:9a74041ba0bfa9bc9b9bb2cd3238a6ab3b7618e759b41bd15b5f6ad958d17605", - "sha256:9edbe6a5bf8b56a4a84533ba2b2f489d0046e755c29616ef8830f9e7d9cf5728", - "sha256:a15c1fe6d26e83fd2e5972425a772cca158eae58b05d4a25a4e474c221053e2d", - "sha256:a66bcdf19c1a523e41b8e9d53d0cedbfbac2e93c649a2e9502cb26c014d0980c", - "sha256:ae4070f741f8d809075ef697877fd350ecf0b7c5837ed68738607ee0a2c572cf", - "sha256:ae55d592b02c4349525b6ed8f74c692509e5adffa842e582c0f861751701a673", - "sha256:b578cbe580e3b41ad17b1c428f382c814b32a6ce90f2d8e39e2e635d49e498d1", - "sha256:b891a2f68e09c5ef989007fac11476ed33c5c9994449a4e2c3386529d703dc8b", - "sha256:baec8148d6b8bd5cee1ae138ba658c71f5b03e0d69d5907703e3e1df96db5e41", - "sha256:bb06098d019766ca16fc915ecaa455c1f1cd594204e7f840cd6258237b5079a8", - "sha256:bc791ec3fd0c4309a753f95bb6c749ef0d8ea3aea91f07ee1cf06b7b02118f2f", - "sha256:bd28b31730f0e982ace8663d108e01199098432a30a4c410d06fe08fdb9e93f4", - "sha256:be4d9c2770044a59715eb57c1144dedea7c5d5ae80c68fb9959515037cde2008", - "sha256:c0c72d34e7de5604df0fde3644cc079feee5e55464967d10b24b1de268deceb9", - "sha256:c0e842112fe3f1a4ffcf64b06dc4c61a88441c2f02f373367f7b4c1aa9be2ad5", - "sha256:c15070ebf11b8b7fd1bfff7217e9324963c82dbdf6182ff7050519e350e7ad9f", - "sha256:c2000c54c395d9e5e44c99dc7c20a64dc371f777faf8bae4919ad3e99ce5253e", - "sha256:c30187840d36d0ba2893bc3271a36a517a717f9fd383a98e2697ee890a37c273", - "sha256:cb7cd68814308aade9d0c93c5bd2ade9f9441666f8ba5aa9c2d4b389cb5e2a45", - "sha256:cd805513198304026bd379d1d516afbf6c3c13f4382134a2c526b8b854da1c2e", - "sha256:d0bf89afcbcf4d1bb2652f6580e5e55a840fdf87384f6063c4a4f0c95e378656", - "sha256:d9137a876020661972ca6eec0766d81aef8a5627df628b664b234b73396e727e", - "sha256:dbd95e300367aa0827496fe75a1766d198d34385a58f97683fe6e07f89ca3e3c", - "sha256:dced27917823df984fe0c80a5c4ad75cf58df0fbfae890bc08004cd3888922a2", - "sha256:de0b4caa1c8a21394e8ce971997614a17648f94e1cd0640fbd6b4d14cab13a72", - "sha256:debb633f3f7856f95ad957d9b9c781f8e2c6303ef21724ec94bea2ce2fcbd056", - "sha256:e372d7dfd154009142631de2d316adad3cc1c36c32a38b16a4751ba78da2a397", - "sha256:ecd26be9f112c4f96718290c10f4caea6cc798459a3a76636b817a0ed7874e42", - "sha256:edc0202099ea1d82844316604e17d2b175044f9bcb6b398aab781eba957224bd", - "sha256:f194cce575e59ffe442c10a360182a986535fd90b57f7debfaa5c845c409ecc3", - "sha256:f5fb672c396d826ca16a022ac04c9dce74e00a1c344f6ad1a0fdc1ba1f332213", - "sha256:f6a02a3c7950cafaadcd46a226ad9e12fc9744652cc69f9e5534f98b47f3bbcf", - "sha256:fe81b35c33772e56f4b6cf62cf4aedc1762ef7162a31e6ac7fe5e40d0149eb67" - ], - "index": "pypi", - "markers": "python_full_version >= '3.7.0'", - "version": "==3.3.1" - }, - "click": { - "hashes": [ - "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", - "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==8.1.7" - }, - "click-didyoumean": { - "hashes": [ - "sha256:a0713dc7a1de3f06bc0df5a9567ad19ead2d3d5689b434768a6145bff77c0667", - "sha256:f184f0d851d96b6d29297354ed981b7dd71df7ff500d82fa6d11f0856bee8035" - ], - "index": "pypi", - "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" - ], - "index": "pypi", - "version": "==1.1.1" - }, - "click-repl": { - "hashes": [ - "sha256:17849c23dba3d667247dc4defe1757fff98694e90fe37474f3feebb69ced26a9", - "sha256:fb7e06deb8da8de86180a33a9da97ac316751c094c6899382da7feeeeb51b812" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==0.3.0" - }, - "colorama": { - "hashes": [ - "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", - "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" - ], - "index": "pypi", - "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": "==0.4.6" - }, - "contourpy": { - "hashes": [ - "sha256:031154ed61f7328ad7f97662e48660a150ef84ee1bc8876b6472af88bf5a9b98", - "sha256:0f9d350b639db6c2c233d92c7f213d94d2e444d8e8fc5ca44c9706cf72193772", - "sha256:130230b7e49825c98edf0b428b7aa1125503d91732735ef897786fe5452b1ec2", - "sha256:152fd8f730c31fd67fe0ffebe1df38ab6a669403da93df218801a893645c6ccc", - "sha256:1c71fdd8f1c0f84ffd58fca37d00ca4ebaa9e502fb49825484da075ac0b0b803", - "sha256:24847601071f740837aefb730e01bd169fbcaa610209779a78db7ebb6e6a7051", - "sha256:2e9ebb4425fc1b658e13bace354c48a933b842d53c458f02c86f371cecbedecc", - "sha256:30676ca45084ee61e9c3da589042c24a57592e375d4b138bd84d8709893a1ba4", - "sha256:31a55dccc8426e71817e3fe09b37d6d48ae40aae4ecbc8c7ad59d6893569c436", - "sha256:366a0cf0fc079af5204801786ad7a1c007714ee3909e364dbac1729f5b0849e5", - "sha256:38e2e577f0f092b8e6774459317c05a69935a1755ecfb621c0a98f0e3c09c9a5", - "sha256:3c184ad2433635f216645fdf0493011a4667e8d46b34082f5a3de702b6ec42e3", - "sha256:3caea6365b13119626ee996711ab63e0c9d7496f65641f4459c60a009a1f3e80", - "sha256:3e927b3868bd1e12acee7cc8f3747d815b4ab3e445a28d2e5373a7f4a6e76ba1", - "sha256:4ee3ee247f795a69e53cd91d927146fb16c4e803c7ac86c84104940c7d2cabf0", - "sha256:54d43960d809c4c12508a60b66cb936e7ed57d51fb5e30b513934a4a23874fae", - "sha256:57119b0116e3f408acbdccf9eb6ef19d7fe7baf0d1e9aaa5381489bc1aa56556", - "sha256:58569c491e7f7e874f11519ef46737cea1d6eda1b514e4eb5ac7dab6aa864d02", - "sha256:5a011cf354107b47c58ea932d13b04d93c6d1d69b8b6dce885e642531f847566", - "sha256:5caeacc68642e5f19d707471890f037a13007feba8427eb7f2a60811a1fc1350", - "sha256:5dd34c1ae752515318224cba7fc62b53130c45ac6a1040c8b7c1a223c46e8967", - "sha256:60835badb5ed5f4e194a6f21c09283dd6e007664a86101431bf870d9e86266c4", - "sha256:62398c80ef57589bdbe1eb8537127321c1abcfdf8c5f14f479dbbe27d0322e66", - "sha256:6381fa66866b0ea35e15d197fc06ac3840a9b2643a6475c8fff267db8b9f1e69", - "sha256:64757f6460fc55d7e16ed4f1de193f362104285c667c112b50a804d482777edd", - "sha256:69f8ff4db108815addd900a74df665e135dbbd6547a8a69333a68e1f6e368ac2", - "sha256:6c180d89a28787e4b73b07e9b0e2dac7741261dbdca95f2b489c4f8f887dd810", - "sha256:71b0bf0c30d432278793d2141362ac853859e87de0a7dee24a1cea35231f0d50", - "sha256:769eef00437edf115e24d87f8926955f00f7704bede656ce605097584f9966dc", - "sha256:7f6979d20ee5693a1057ab53e043adffa1e7418d734c1532e2d9e915b08d8ec2", - "sha256:87f4d8941a9564cda3f7fa6a6cd9b32ec575830780677932abdec7bcb61717b0", - "sha256:89ba9bb365446a22411f0673abf6ee1fea3b2cf47b37533b970904880ceb72f3", - "sha256:8acf74b5d383414401926c1598ed77825cd530ac7b463ebc2e4f46638f56cce6", - "sha256:9056c5310eb1daa33fc234ef39ebfb8c8e2533f088bbf0bc7350f70a29bde1ac", - "sha256:95c3acddf921944f241b6773b767f1cbce71d03307270e2d769fd584d5d1092d", - "sha256:9e20e5a1908e18aaa60d9077a6d8753090e3f85ca25da6e25d30dc0a9e84c2c6", - "sha256:a1e97b86f73715e8670ef45292d7cc033548266f07d54e2183ecb3c87598888f", - "sha256:a877ada905f7d69b2a31796c4b66e31a8068b37aa9b78832d41c82fc3e056ddd", - "sha256:a9d7587d2fdc820cc9177139b56795c39fb8560f540bba9ceea215f1f66e1566", - "sha256:abf298af1e7ad44eeb93501e40eb5a67abbf93b5d90e468d01fc0c4451971afa", - "sha256:ae90d5a8590e5310c32a7630b4b8618cef7563cebf649011da80874d0aa8f414", - "sha256:b6d0f9e1d39dbfb3977f9dd79f156c86eb03e57a7face96f199e02b18e58d32a", - "sha256:b8d587cc39057d0afd4166083d289bdeff221ac6d3ee5046aef2d480dc4b503c", - "sha256:c5210e5d5117e9aec8c47d9156d1d3835570dd909a899171b9535cb4a3f32693", - "sha256:cc331c13902d0f50845099434cd936d49d7a2ca76cb654b39691974cb1e4812d", - "sha256:ce41676b3d0dd16dbcfabcc1dc46090aaf4688fd6e819ef343dbda5a57ef0161", - "sha256:d8165a088d31798b59e91117d1f5fc3df8168d8b48c4acc10fc0df0d0bdbcc5e", - "sha256:e7281244c99fd7c6f27c1c6bfafba878517b0b62925a09b586d88ce750a016d2", - "sha256:e96a08b62bb8de960d3a6afbc5ed8421bf1a2d9c85cc4ea73f4bc81b4910500f", - "sha256:ed33433fc3820263a6368e532f19ddb4c5990855e4886088ad84fd7c4e561c71", - "sha256:efb8f6d08ca7998cf59eaf50c9d60717f29a1a0a09caa46460d33b2924839dbd", - "sha256:efe99298ba37e37787f6a2ea868265465410822f7bea163edcc1bd3903354ea9", - "sha256:f99e9486bf1bb979d95d5cffed40689cb595abb2b841f2991fc894b3452290e8", - "sha256:fc1464c97579da9f3ab16763c32e5c5d5bb5fa1ec7ce509a4ca6108b61b84fab", - "sha256:fd7dc0e6812b799a34f6d12fcb1000539098c249c8da54f3566c6a6461d0dbad" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==1.0.7" - }, - "couchdb": { - "hashes": [ - "sha256:1386a1a43f25bed3667e3b805222054940d674fa1967fa48e9d2012a18630ab7", - "sha256:13a28a1159c49f8346732e8724b9a4d65cba54bec017c4a7eeb1499fe88151d1" - ], - "index": "pypi", - "version": "==1.2" - }, - "crispy-bootstrap4": { - "hashes": [ - "sha256:5241ab1dc2188c95560aa786439bcbedec7416e6b0f5a52dded82380810367ec", - "sha256:f18386c4d96180c1bb1212487d6e8f5a3dd1a9bb58d3032183973d4d130b55f9" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==2022.1" - }, - "cryptography": { - "hashes": [ - "sha256:0c327cac00f082013c7c9fb6c46b7cc9fa3c288ca702c74773968173bda421bf", - "sha256:0d2a6a598847c46e3e321a7aef8af1436f11c27f1254933746304ff014664d84", - "sha256:227ec057cd32a41c6651701abc0328135e472ed450f47c2766f23267b792a88e", - "sha256:22892cc830d8b2c89ea60148227631bb96a7da0c1b722f2aac8824b1b7c0b6b8", - "sha256:392cb88b597247177172e02da6b7a63deeff1937fa6fec3bbf902ebd75d97ec7", - "sha256:3be3ca726e1572517d2bef99a818378bbcf7d7799d5372a46c79c29eb8d166c1", - "sha256:573eb7128cbca75f9157dcde974781209463ce56b5804983e11a1c462f0f4e88", - "sha256:580afc7b7216deeb87a098ef0674d6ee34ab55993140838b14c9b83312b37b86", - "sha256:5a70187954ba7292c7876734183e810b728b4f3965fbe571421cb2434d279179", - "sha256:73801ac9736741f220e20435f84ecec75ed70eda90f781a148f1bad546963d81", - "sha256:7d208c21e47940369accfc9e85f0de7693d9a5d843c2509b3846b2db170dfd20", - "sha256:8254962e6ba1f4d2090c44daf50a547cd5f0bf446dc658a8e5f8156cae0d8548", - "sha256:88417bff20162f635f24f849ab182b092697922088b477a7abd6664ddd82291d", - "sha256:a48e74dad1fb349f3dc1d449ed88e0017d792997a7ad2ec9587ed17405667e6d", - "sha256:b948e09fe5fb18517d99994184854ebd50b57248736fd4c720ad540560174ec5", - "sha256:c707f7afd813478e2019ae32a7c49cd932dd60ab2d2a93e796f68236b7e1fbf1", - "sha256:d38e6031e113b7421db1de0c1b1f7739564a88f1684c6b89234fbf6c11b75147", - "sha256:d3977f0e276f6f5bf245c403156673db103283266601405376f075c849a0b936", - "sha256:da6a0ff8f1016ccc7477e6339e1d50ce5f59b88905585f77193ebd5068f1e797", - "sha256:e270c04f4d9b5671ebcc792b3ba5d4488bf7c42c3c241a3748e2599776f29696", - "sha256:e886098619d3815e0ad5790c973afeee2c0e6e04b4da90b88e6bd06e2a0b1b72", - "sha256:ec3b055ff8f1dce8e6ef28f626e0972981475173d7973d63f271b29c8a2897da", - "sha256:fba1e91467c65fe64a82c689dc6cf58151158993b13eb7a7f3f4b7f395636723" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==41.0.5" - }, - "cycler": { - "hashes": [ - "sha256:3a27e95f763a428a739d2add979fa7494c912a32c17c4c38c4d5f082cad165a3", - "sha256:9c87405839a19696e837b3b818fed3f5f69f16f1eec1a1ad77e043dcea9c772f" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==0.11.0" - }, - "defusedxml": { - "hashes": [ - "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", - "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61" - ], - "index": "pypi", - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==0.7.1" - }, - "discord": { - "hashes": [ - "sha256:cc1ee2dbe6df218ca51519af355b97e87309f8230f58c7f34885feb8e8a76145", - "sha256:d7959418799dd3b1e896685812d880169c193468b061b3431fa2a4664febd3da" - ], - "index": "pypi", - "version": "==2.3.2" - }, - "discord.py": { - "hashes": [ - "sha256:4560f70f2eddba7e83370ecebd237ac09fbb4980dc66507482b0c0e5b8f76b9c", - "sha256:9da4679fc3cb10c64b388284700dc998663e0e57328283bbfcfc2525ec5960a6" - ], - "markers": "python_full_version >= '3.8.0'", - "version": "==2.3.2" - }, - "django": { - "hashes": [ - "sha256:6e6ff3db2d8dd0c986b4eec8554c8e4f919b5c1ff62a5b4390c17aff2ed6e5c4", - "sha256:ddc24a0a8280a0430baa37aff11f28574720af05888c62b7cfe71d219f4599d3" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==4.2.11" - }, - "django-ajax": { - "hashes": [ - "sha256:f45a4c5b0240a0c5e0e088e056e71ec3b381bbd8fa2e6b2bc307c9ff6b64bf33" - ], - "index": "pypi", - "version": "==0.3.0" - }, - "django-appconf": { - "hashes": [ - "sha256:ae9f864ee1958c815a965ed63b3fba4874eec13de10236ba063a788f9a17389d", - "sha256:be3db0be6c81fa84742000b89a81c016d70ae66a7ccb620cdef592b1f1a6aaa4" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==1.0.5" - }, - "django-bootstrap-modal-forms": { - "hashes": [ - "sha256:47a4f303724182a5e4958da94772f5a6a7359fac6d6ae204442aadfd56c03133", - "sha256:ff33b9b89608c8bcb9eba811524e9fb7ec1c843a73bd78a7d38fbb94cc9bdd4a" - ], - "index": "pypi", - "version": "==3.0.4" - }, - "django-compressor": { - "hashes": [ - "sha256:1b0acc9cfba9f69bc38e7c41da9b0d70a20bc95587b643ffef9609cf46064f67", - "sha256:6e2b0c0becb9607f5099c2546a824c5b84a6918a34bc37a8a622ffa250313596" - ], - "index": "pypi", - "version": "==4.4" - }, - "django-crispy-forms": { - "hashes": [ - "sha256:90193b068bf948d9c68449bc8260afed1a8e2afe11ee0bac8c4ebfaeb175b322", - "sha256:d1d4e585929058a9ab3b797666ea5b69320b9ba7937f9d146d32173246a6fd13" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==2.0" - }, - "django-cron": { - "hashes": [ - "sha256:016203554748512b7f19d7363b4fde8741c6ff63fe8a15051f3031f4a0506a41", - "sha256:dc3c0d3433a2e4e7012f77f6d8415ad90367ba068649db2674325bc36f935841" - ], - "index": "pypi", - "version": "==0.6.0" - }, - "django-crontab": { - "hashes": [ - "sha256:1201810a212460aaaa48eb6a766738740daf42c1a4f6aafecfb1525036929236" - ], - "index": "pypi", - "version": "==0.7.1" - }, - "django-libsass": { - "hashes": [ - "sha256:5234d29100889cac79e36a0f44207ec6d275adfd2da1acb6a94b55c89fe2bd97", - "sha256:bfbbb55a8950bb40fa04dd416605f92da34ad1f303b10a41abc3232386ec27b5" - ], - "index": "pypi", - "version": "==0.9" - }, - "django-taggit": { - "hashes": [ - "sha256:4d52de9d37245a9b9f98c0ec71fdccf1d2283e38e8866d40a7ae6a3b6787a161", - "sha256:eb800dabef5f0a4e047ab0751f82cf805bc4a9e972037ef12bf519f52cd92480" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==4.0.0" - }, - "django-timezone-field": { - "hashes": [ - "sha256:916d0fd924443462f099f02122cc38d6a6e901ea17f1206c343836199df8bc49", - "sha256:ed28d3ff8e3500f2bc173cdf1aab7a3244ef607d06ad890611512de1bae6074d" - ], - "index": "pypi", - "markers": "python_version >= '3.8' and python_version < '4.0'", - "version": "==6.0.1" - }, - "djangorestframework": { - "hashes": [ - "sha256:579a333e6256b09489cbe0a067e66abe55c6595d8926be6b99423786334350c8", - "sha256:eb63f58c9f218e1a7d064d17a70751f528ed4e1d35547fdade9aaf4cd103fd08" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==3.14.0" - }, - "executing": { - "hashes": [ - "sha256:35afe2ce3affba8ee97f2d69927fa823b08b472b7b994e36a52a964b93d16147", - "sha256:eac49ca94516ccc753f9fb5ce82603156e590b27525a8bc32cce8ae302eb61bc" - ], - "markers": "python_version >= '3.5'", - "version": "==2.0.1" - }, - "flower": { - "hashes": [ - "sha256:5ab717b979530770c16afb48b50d2a98d23c3e9fe39851dcf6bc4d01845a02a0", - "sha256:9db2c621eeefbc844c8dd88be64aef61e84e2deb29b271e02ab2b5b9f01068e2" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==2.0.1" - }, - "fonttools": { - "hashes": [ - "sha256:106caf6167c4597556b31a8d9175a3fdc0356fdcd70ab19973c3b0d4c893c461", - "sha256:dba8d7cdb8e2bac1b3da28c5ed5960de09e59a2fe7e63bb73f5a59e57b0430d2" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==4.39.4" - }, - "frozenlist": { - "hashes": [ - "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7", - "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98", - "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad", - "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5", - "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae", - "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e", - "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a", - "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701", - "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d", - "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6", - "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6", - "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106", - "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75", - "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868", - "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a", - "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0", - "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1", - "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826", - "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec", - "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6", - "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950", - "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19", - "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0", - "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8", - "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a", - "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09", - "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86", - "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c", - "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5", - "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b", - "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b", - "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d", - "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0", - "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea", - "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776", - "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a", - "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897", - "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7", - "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09", - "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9", - "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe", - "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd", - "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742", - "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09", - "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0", - "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932", - "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1", - "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a", - "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49", - "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d", - "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7", - "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480", - "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89", - "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e", - "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b", - "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82", - "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb", - "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068", - "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8", - "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b", - "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb", - "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2", - "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11", - "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b", - "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc", - "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0", - "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497", - "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17", - "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0", - "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2", - "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439", - "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5", - "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac", - "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825", - "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887", - "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced", - "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74" - ], - "markers": "python_version >= '3.8'", - "version": "==1.4.1" - }, - "httplib2": { - "hashes": [ - "sha256:14ae0a53c1ba8f3d37e9e27cf37eabb0fb9980f435ba405d546948b009dd64dc", - "sha256:d7a10bc5ef5ab08322488bde8c726eeee5c8618723fdb399597ec58f3d82df81" - ], - "index": "pypi", - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==0.22.0" - }, - "humanize": { - "hashes": [ - "sha256:582a265c931c683a7e9b8ed9559089dea7edcf6cc95be39a3cbc2c5d5ac2bcfa", - "sha256:ce284a76d5b1377fd8836733b983bfb0b76f1aa1c090de2566fcf008d7f6ab16" - ], - "markers": "python_version >= '3.8'", - "version": "==4.9.0" - }, - "icecream": { - "hashes": [ - "sha256:0aa4a7c3374ec36153a1d08f81e3080e83d8ac1eefd97d2f4fe9544e8f9b49de", - "sha256:757aec31ad4488b949bc4f499d18e6e5973c40cc4d4fc607229e78cfaec94c34" - ], - "index": "pypi", - "version": "==2.1.3" - }, - "idna": { - "hashes": [ - "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4", - "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2" - ], - "index": "pypi", - "markers": "python_version >= '3.5'", - "version": "==3.4" - }, - "kiwisolver": { - "hashes": [ - "sha256:02f79693ec433cb4b5f51694e8477ae83b3205768a6fb48ffba60549080e295b", - "sha256:03baab2d6b4a54ddbb43bba1a3a2d1627e82d205c5cf8f4c924dc49284b87166", - "sha256:1041feb4cda8708ce73bb4dcb9ce1ccf49d553bf87c3954bdfa46f0c3f77252c", - "sha256:10ee06759482c78bdb864f4109886dff7b8a56529bc1609d4f1112b93fe6423c", - "sha256:1d1573129aa0fd901076e2bfb4275a35f5b7aa60fbfb984499d661ec950320b0", - "sha256:283dffbf061a4ec60391d51e6155e372a1f7a4f5b15d59c8505339454f8989e4", - "sha256:28bc5b299f48150b5f822ce68624e445040595a4ac3d59251703779836eceff9", - "sha256:2a66fdfb34e05b705620dd567f5a03f239a088d5a3f321e7b6ac3239d22aa286", - "sha256:2e307eb9bd99801f82789b44bb45e9f541961831c7311521b13a6c85afc09767", - "sha256:2e407cb4bd5a13984a6c2c0fe1845e4e41e96f183e5e5cd4d77a857d9693494c", - "sha256:2f5e60fabb7343a836360c4f0919b8cd0d6dbf08ad2ca6b9cf90bf0c76a3c4f6", - "sha256:36dafec3d6d6088d34e2de6b85f9d8e2324eb734162fba59d2ba9ed7a2043d5b", - "sha256:3fe20f63c9ecee44560d0e7f116b3a747a5d7203376abeea292ab3152334d004", - "sha256:41dae968a94b1ef1897cb322b39360a0812661dba7c682aa45098eb8e193dbdf", - "sha256:4bd472dbe5e136f96a4b18f295d159d7f26fd399136f5b17b08c4e5f498cd494", - "sha256:4ea39b0ccc4f5d803e3337dd46bcce60b702be4d86fd0b3d7531ef10fd99a1ac", - "sha256:5853eb494c71e267912275e5586fe281444eb5e722de4e131cddf9d442615626", - "sha256:5bce61af018b0cb2055e0e72e7d65290d822d3feee430b7b8203d8a855e78766", - "sha256:6295ecd49304dcf3bfbfa45d9a081c96509e95f4b9d0eb7ee4ec0530c4a96514", - "sha256:62ac9cc684da4cf1778d07a89bf5f81b35834cb96ca523d3a7fb32509380cbf6", - "sha256:70e7c2e7b750585569564e2e5ca9845acfaa5da56ac46df68414f29fea97be9f", - "sha256:7577c1987baa3adc4b3c62c33bd1118c3ef5c8ddef36f0f2c950ae0b199e100d", - "sha256:75facbe9606748f43428fc91a43edb46c7ff68889b91fa31f53b58894503a191", - "sha256:787518a6789009c159453da4d6b683f468ef7a65bbde796bcea803ccf191058d", - "sha256:78d6601aed50c74e0ef02f4204da1816147a6d3fbdc8b3872d263338a9052c51", - "sha256:7c43e1e1206cd421cd92e6b3280d4385d41d7166b3ed577ac20444b6995a445f", - "sha256:81e38381b782cc7e1e46c4e14cd997ee6040768101aefc8fa3c24a4cc58e98f8", - "sha256:841293b17ad704d70c578f1f0013c890e219952169ce8a24ebc063eecf775454", - "sha256:872b8ca05c40d309ed13eb2e582cab0c5a05e81e987ab9c521bf05ad1d5cf5cb", - "sha256:877272cf6b4b7e94c9614f9b10140e198d2186363728ed0f701c6eee1baec1da", - "sha256:8c808594c88a025d4e322d5bb549282c93c8e1ba71b790f539567932722d7bd8", - "sha256:8ed58b8acf29798b036d347791141767ccf65eee7f26bde03a71c944449e53de", - "sha256:91672bacaa030f92fc2f43b620d7b337fd9a5af28b0d6ed3f77afc43c4a64b5a", - "sha256:968f44fdbf6dd757d12920d63b566eeb4d5b395fd2d00d29d7ef00a00582aac9", - "sha256:9f85003f5dfa867e86d53fac6f7e6f30c045673fa27b603c397753bebadc3008", - "sha256:a553dadda40fef6bfa1456dc4be49b113aa92c2a9a9e8711e955618cd69622e3", - "sha256:a68b62a02953b9841730db7797422f983935aeefceb1679f0fc85cbfbd311c32", - "sha256:abbe9fa13da955feb8202e215c4018f4bb57469b1b78c7a4c5c7b93001699938", - "sha256:ad881edc7ccb9d65b0224f4e4d05a1e85cf62d73aab798943df6d48ab0cd79a1", - "sha256:b1792d939ec70abe76f5054d3f36ed5656021dcad1322d1cc996d4e54165cef9", - "sha256:b428ef021242344340460fa4c9185d0b1f66fbdbfecc6c63eff4b7c29fad429d", - "sha256:b533558eae785e33e8c148a8d9921692a9fe5aa516efbdff8606e7d87b9d5824", - "sha256:ba59c92039ec0a66103b1d5fe588fa546373587a7d68f5c96f743c3396afc04b", - "sha256:bc8d3bd6c72b2dd9decf16ce70e20abcb3274ba01b4e1c96031e0c4067d1e7cd", - "sha256:bc9db8a3efb3e403e4ecc6cd9489ea2bac94244f80c78e27c31dcc00d2790ac2", - "sha256:bf7d9fce9bcc4752ca4a1b80aabd38f6d19009ea5cbda0e0856983cf6d0023f5", - "sha256:c2dbb44c3f7e6c4d3487b31037b1bdbf424d97687c1747ce4ff2895795c9bf69", - "sha256:c79ebe8f3676a4c6630fd3f777f3cfecf9289666c84e775a67d1d358578dc2e3", - "sha256:c97528e64cb9ebeff9701e7938653a9951922f2a38bd847787d4a8e498cc83ae", - "sha256:d0611a0a2a518464c05ddd5a3a1a0e856ccc10e67079bb17f265ad19ab3c7597", - "sha256:d06adcfa62a4431d404c31216f0f8ac97397d799cd53800e9d3efc2fbb3cf14e", - "sha256:d41997519fcba4a1e46eb4a2fe31bc12f0ff957b2b81bac28db24744f333e955", - "sha256:d5b61785a9ce44e5a4b880272baa7cf6c8f48a5180c3e81c59553ba0cb0821ca", - "sha256:da152d8cdcab0e56e4f45eb08b9aea6455845ec83172092f09b0e077ece2cf7a", - "sha256:da7e547706e69e45d95e116e6939488d62174e033b763ab1496b4c29b76fabea", - "sha256:db5283d90da4174865d520e7366801a93777201e91e79bacbac6e6927cbceede", - "sha256:db608a6757adabb32f1cfe6066e39b3706d8c3aa69bbc353a5b61edad36a5cb4", - "sha256:e0ea21f66820452a3f5d1655f8704a60d66ba1191359b96541eaf457710a5fc6", - "sha256:e7da3fec7408813a7cebc9e4ec55afed2d0fd65c4754bc376bf03498d4e92686", - "sha256:e92a513161077b53447160b9bd8f522edfbed4bd9759e4c18ab05d7ef7e49408", - "sha256:ecb1fa0db7bf4cff9dac752abb19505a233c7f16684c5826d1f11ebd9472b871", - "sha256:efda5fc8cc1c61e4f639b8067d118e742b812c930f708e6667a5ce0d13499e29", - "sha256:f0a1dbdb5ecbef0d34eb77e56fcb3e95bbd7e50835d9782a45df81cc46949750", - "sha256:f0a71d85ecdd570ded8ac3d1c0f480842f49a40beb423bb8014539a9f32a5897", - "sha256:f4f270de01dd3e129a72efad823da90cc4d6aafb64c410c9033aba70db9f1ff0", - "sha256:f6cb459eea32a4e2cf18ba5fcece2dbdf496384413bc1bae15583f19e567f3b2", - "sha256:f8ad8285b01b0d4695102546b342b493b3ccc6781fc28c8c6a1bb63e95d22f09", - "sha256:f9f39e2f049db33a908319cf46624a569b36983c7c78318e9726a4cb8923b26c" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==1.4.4" - }, - "kombu": { - "hashes": [ - "sha256:0ba213f630a2cb2772728aef56ac6883dc3a2f13435e10048f6e97d48506dbbd", - "sha256:b753c9cfc9b1e976e637a7cbc1a65d446a22e45546cd996ea28f932082b7dc9e" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==5.3.2" - }, - "libsass": { - "hashes": [ - "sha256:081e256ab3c5f3f09c7b8dea3bf3bf5e64a97c6995fd9eea880639b3f93a9f9a", - "sha256:3ab5ad18e47db560f4f0c09e3d28cf3bb1a44711257488ac2adad69f4f7f8425", - "sha256:5fb2297a4754a6c8e25cfe5c015a3b51a2b6b9021b333f989bb8ce9d60eb5828", - "sha256:65455a2728b696b62100eb5932604aa13a29f4ac9a305d95773c14aaa7200aaf", - "sha256:89c5ce497fcf3aba1dd1b19aae93b99f68257e5f2026b731b00a872f13324c7f", - "sha256:f1efc1b612299c88aec9e39d6ca0c266d360daa5b19d9430bdeaffffa86993f9" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==0.22.0" - }, - "multidict": { - "hashes": [ - "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556", - "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c", - "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29", - "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b", - "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8", - "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7", - "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd", - "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40", - "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6", - "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3", - "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c", - "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9", - "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5", - "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae", - "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442", - "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9", - "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc", - "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c", - "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea", - "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5", - "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50", - "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182", - "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453", - "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e", - "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600", - "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733", - "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda", - "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241", - "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461", - "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e", - "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e", - "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b", - "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e", - "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7", - "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386", - "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd", - "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9", - "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf", - "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee", - "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5", - "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a", - "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271", - "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54", - "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4", - "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496", - "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb", - "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319", - "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3", - "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f", - "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527", - "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed", - "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604", - "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef", - "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8", - "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5", - "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5", - "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626", - "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c", - "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d", - "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c", - "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc", - "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc", - "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b", - "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38", - "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450", - "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1", - "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f", - "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3", - "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755", - "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226", - "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a", - "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046", - "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf", - "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479", - "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e", - "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1", - "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a", - "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83", - "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929", - "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93", - "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a", - "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c", - "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44", - "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89", - "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba", - "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e", - "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da", - "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24", - "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423", - "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef" - ], - "markers": "python_version >= '3.7'", - "version": "==6.0.5" - }, - "numpy": { - "hashes": [ - "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b", - "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818", - "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20", - "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0", - "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010", - "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a", - "sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea", - "sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c", - "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71", - "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110", - "sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be", - "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a", - "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a", - "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5", - "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed", - "sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd", - "sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c", - "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e", - "sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0", - "sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c", - "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a", - "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b", - "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0", - "sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6", - "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2", - "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a", - "sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30", - "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218", - "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5", - "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07", - "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2", - "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4", - "sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764", - "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef", - "sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3", - "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f" - ], - "markers": "python_version >= '3.9'", - "version": "==1.26.4" - }, - "oauthlib": { - "hashes": [ - "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca", - "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==3.2.2" - }, - "packaging": { - "hashes": [ - "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61", - "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==23.1" - }, - "pillow": { - "hashes": [ - "sha256:07999f5834bdc404c442146942a2ecadd1cb6292f5229f4ed3b31e0a108746b1", - "sha256:0852ddb76d85f127c135b6dd1f0bb88dbb9ee990d2cd9aa9e28526c93e794fba", - "sha256:1781a624c229cb35a2ac31cc4a77e28cafc8900733a864870c49bfeedacd106a", - "sha256:1e7723bd90ef94eda669a3c2c19d549874dd5badaeefabefd26053304abe5799", - "sha256:229e2c79c00e85989a34b5981a2b67aa079fd08c903f0aaead522a1d68d79e51", - "sha256:22baf0c3cf0c7f26e82d6e1adf118027afb325e703922c8dfc1d5d0156bb2eeb", - "sha256:252a03f1bdddce077eff2354c3861bf437c892fb1832f75ce813ee94347aa9b5", - "sha256:2dfaaf10b6172697b9bceb9a3bd7b951819d1ca339a5ef294d1f1ac6d7f63270", - "sha256:322724c0032af6692456cd6ed554bb85f8149214d97398bb80613b04e33769f6", - "sha256:35f6e77122a0c0762268216315bf239cf52b88865bba522999dc38f1c52b9b47", - "sha256:375f6e5ee9620a271acb6820b3d1e94ffa8e741c0601db4c0c4d3cb0a9c224bf", - "sha256:3ded42b9ad70e5f1754fb7c2e2d6465a9c842e41d178f262e08b8c85ed8a1d8e", - "sha256:432b975c009cf649420615388561c0ce7cc31ce9b2e374db659ee4f7d57a1f8b", - "sha256:482877592e927fd263028c105b36272398e3e1be3269efda09f6ba21fd83ec66", - "sha256:489f8389261e5ed43ac8ff7b453162af39c3e8abd730af8363587ba64bb2e865", - "sha256:54f7102ad31a3de5666827526e248c3530b3a33539dbda27c6843d19d72644ec", - "sha256:560737e70cb9c6255d6dcba3de6578a9e2ec4b573659943a5e7e4af13f298f5c", - "sha256:5671583eab84af046a397d6d0ba25343c00cd50bce03787948e0fff01d4fd9b1", - "sha256:5ba1b81ee69573fe7124881762bb4cd2e4b6ed9dd28c9c60a632902fe8db8b38", - "sha256:5d4ebf8e1db4441a55c509c4baa7a0587a0210f7cd25fcfe74dbbce7a4bd1906", - "sha256:60037a8db8750e474af7ffc9faa9b5859e6c6d0a50e55c45576bf28be7419705", - "sha256:608488bdcbdb4ba7837461442b90ea6f3079397ddc968c31265c1e056964f1ef", - "sha256:6608ff3bf781eee0cd14d0901a2b9cc3d3834516532e3bd673a0a204dc8615fc", - "sha256:662da1f3f89a302cc22faa9f14a262c2e3951f9dbc9617609a47521c69dd9f8f", - "sha256:7002d0797a3e4193c7cdee3198d7c14f92c0836d6b4a3f3046a64bd1ce8df2bf", - "sha256:763782b2e03e45e2c77d7779875f4432e25121ef002a41829d8868700d119392", - "sha256:77165c4a5e7d5a284f10a6efaa39a0ae8ba839da344f20b111d62cc932fa4e5d", - "sha256:7c9af5a3b406a50e313467e3565fc99929717f780164fe6fbb7704edba0cebbe", - "sha256:7ec6f6ce99dab90b52da21cf0dc519e21095e332ff3b399a357c187b1a5eee32", - "sha256:833b86a98e0ede388fa29363159c9b1a294b0905b5128baf01db683672f230f5", - "sha256:84a6f19ce086c1bf894644b43cd129702f781ba5751ca8572f08aa40ef0ab7b7", - "sha256:8507eda3cd0608a1f94f58c64817e83ec12fa93a9436938b191b80d9e4c0fc44", - "sha256:85ec677246533e27770b0de5cf0f9d6e4ec0c212a1f89dfc941b64b21226009d", - "sha256:8aca1152d93dcc27dc55395604dcfc55bed5f25ef4c98716a928bacba90d33a3", - "sha256:8d935f924bbab8f0a9a28404422da8af4904e36d5c33fc6f677e4c4485515625", - "sha256:8f36397bf3f7d7c6a3abdea815ecf6fd14e7fcd4418ab24bae01008d8d8ca15e", - "sha256:91ec6fe47b5eb5a9968c79ad9ed78c342b1f97a091677ba0e012701add857829", - "sha256:965e4a05ef364e7b973dd17fc765f42233415974d773e82144c9bbaaaea5d089", - "sha256:96e88745a55b88a7c64fa49bceff363a1a27d9a64e04019c2281049444a571e3", - "sha256:99eb6cafb6ba90e436684e08dad8be1637efb71c4f2180ee6b8f940739406e78", - "sha256:9adf58f5d64e474bed00d69bcd86ec4bcaa4123bfa70a65ce72e424bfb88ed96", - "sha256:9b1af95c3a967bf1da94f253e56b6286b50af23392a886720f563c547e48e964", - "sha256:a0aa9417994d91301056f3d0038af1199eb7adc86e646a36b9e050b06f526597", - "sha256:a0f9bb6c80e6efcde93ffc51256d5cfb2155ff8f78292f074f60f9e70b942d99", - "sha256:a127ae76092974abfbfa38ca2d12cbeddcdeac0fb71f9627cc1135bedaf9d51a", - "sha256:aaf305d6d40bd9632198c766fb64f0c1a83ca5b667f16c1e79e1661ab5060140", - "sha256:aca1c196f407ec7cf04dcbb15d19a43c507a81f7ffc45b690899d6a76ac9fda7", - "sha256:ace6ca218308447b9077c14ea4ef381ba0b67ee78d64046b3f19cf4e1139ad16", - "sha256:b416f03d37d27290cb93597335a2f85ed446731200705b22bb927405320de903", - "sha256:bf548479d336726d7a0eceb6e767e179fbde37833ae42794602631a070d630f1", - "sha256:c1170d6b195555644f0616fd6ed929dfcf6333b8675fcca044ae5ab110ded296", - "sha256:c380b27d041209b849ed246b111b7c166ba36d7933ec6e41175fd15ab9eb1572", - "sha256:c446d2245ba29820d405315083d55299a796695d747efceb5717a8b450324115", - "sha256:c830a02caeb789633863b466b9de10c015bded434deb3ec87c768e53752ad22a", - "sha256:cb841572862f629b99725ebaec3287fc6d275be9b14443ea746c1dd325053cbd", - "sha256:cfa4561277f677ecf651e2b22dc43e8f5368b74a25a8f7d1d4a3a243e573f2d4", - "sha256:cfcc2c53c06f2ccb8976fb5c71d448bdd0a07d26d8e07e321c103416444c7ad1", - "sha256:d3c6b54e304c60c4181da1c9dadf83e4a54fd266a99c70ba646a9baa626819eb", - "sha256:d3d403753c9d5adc04d4694d35cf0391f0f3d57c8e0030aac09d7678fa8030aa", - "sha256:d9c206c29b46cfd343ea7cdfe1232443072bbb270d6a46f59c259460db76779a", - "sha256:e49eb4e95ff6fd7c0c402508894b1ef0e01b99a44320ba7d8ecbabefddcc5569", - "sha256:f8286396b351785801a976b1e85ea88e937712ee2c3ac653710a4a57a8da5d9c", - "sha256:f8fc330c3370a81bbf3f88557097d1ea26cd8b019d6433aa59f71195f5ddebbf", - "sha256:fbd359831c1657d69bb81f0db962905ee05e5e9451913b18b831febfe0519082", - "sha256:fe7e1c262d3392afcf5071df9afa574544f28eac825284596ac6db56e6d11062", - "sha256:fed1e1cf6a42577953abbe8e6cf2fe2f566daebde7c34724ec8803c4c0cda579" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==9.5.0" - }, - "prometheus-client": { - "hashes": [ - "sha256:287629d00b147a32dcb2be0b9df905da599b2d82f80377083ec8463309a4bb89", - "sha256:cde524a85bce83ca359cc837f28b8c0db5cac7aa653a588fd7e84ba061c329e7" - ], - "markers": "python_version >= '3.8'", - "version": "==0.20.0" - }, - "prompt-toolkit": { - "hashes": [ - "sha256:04505ade687dc26dc4284b1ad19a83be2f2afe83e7a828ace0c72f3a1df72aac", - "sha256:9dffbe1d8acf91e3de75f3b544e4842382fc06c6babe903ac9acb74dc6e08d88" - ], - "index": "pypi", - "markers": "python_full_version >= '3.7.0'", - "version": "==3.0.39" - }, - "psycopg2": { - "hashes": [ - "sha256:11aca705ec888e4f4cea97289a0bf0f22a067a32614f6ef64fcf7b8bfbc53744", - "sha256:1861a53a6a0fd248e42ea37c957d36950da00266378746588eab4f4b5649e95f", - "sha256:2362ee4d07ac85ff0ad93e22c693d0f37ff63e28f0615a16b6635a645f4b9214", - "sha256:36c941a767341d11549c0fbdbb2bf5be2eda4caf87f65dfcd7d146828bd27f39", - "sha256:53f4ad0a3988f983e9b49a5d9765d663bbe84f508ed655affdb810af9d0972ad", - "sha256:869776630c04f335d4124f120b7fb377fe44b0a7645ab3c34b4ba42516951889", - "sha256:a8ad4a47f42aa6aec8d061fdae21eaed8d864d4bb0f0cade5ad32ca16fcd6258", - "sha256:b81fcb9ecfc584f661b71c889edeae70bae30d3ef74fa0ca388ecda50b1222b7", - "sha256:d24ead3716a7d093b90b27b3d73459fe8cd90fd7065cf43b3c40966221d8c394", - "sha256:ded2faa2e6dfb430af7713d87ab4abbfc764d8d7fb73eafe96a24155f906ebf5", - "sha256:f15158418fd826831b28585e2ab48ed8df2d0d98f502a2b4fe619e7d5ca29011", - "sha256:f75001a1cbbe523e00b0ef896a5a1ada2da93ccd752b7636db5a99bc57c44494", - "sha256:f7a7a5ee78ba7dc74265ba69e010ae89dae635eea0e97b055fb641a01a31d2b1" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==2.9.6" - }, - "psycopg2-binary": { - "hashes": [ - "sha256:03ef7df18daf2c4c07e2695e8cfd5ee7f748a1d54d802330985a78d2a5a6dca9", - "sha256:0a602ea5aff39bb9fac6308e9c9d82b9a35c2bf288e184a816002c9fae930b77", - "sha256:0c009475ee389757e6e34611d75f6e4f05f0cf5ebb76c6037508318e1a1e0d7e", - "sha256:0ef4854e82c09e84cc63084a9e4ccd6d9b154f1dbdd283efb92ecd0b5e2b8c84", - "sha256:1236ed0952fbd919c100bc839eaa4a39ebc397ed1c08a97fc45fee2a595aa1b3", - "sha256:143072318f793f53819048fdfe30c321890af0c3ec7cb1dfc9cc87aa88241de2", - "sha256:15208be1c50b99203fe88d15695f22a5bed95ab3f84354c494bcb1d08557df67", - "sha256:1873aade94b74715be2246321c8650cabf5a0d098a95bab81145ffffa4c13876", - "sha256:18d0ef97766055fec15b5de2c06dd8e7654705ce3e5e5eed3b6651a1d2a9a152", - "sha256:1ea665f8ce695bcc37a90ee52de7a7980be5161375d42a0b6c6abedbf0d81f0f", - "sha256:2293b001e319ab0d869d660a704942c9e2cce19745262a8aba2115ef41a0a42a", - "sha256:246b123cc54bb5361588acc54218c8c9fb73068bf227a4a531d8ed56fa3ca7d6", - "sha256:275ff571376626195ab95a746e6a04c7df8ea34638b99fc11160de91f2fef503", - "sha256:281309265596e388ef483250db3640e5f414168c5a67e9c665cafce9492eda2f", - "sha256:2d423c8d8a3c82d08fe8af900ad5b613ce3632a1249fd6a223941d0735fce493", - "sha256:2e5afae772c00980525f6d6ecf7cbca55676296b580c0e6abb407f15f3706996", - "sha256:30dcc86377618a4c8f3b72418df92e77be4254d8f89f14b8e8f57d6d43603c0f", - "sha256:31a34c508c003a4347d389a9e6fcc2307cc2150eb516462a7a17512130de109e", - "sha256:323ba25b92454adb36fa425dc5cf6f8f19f78948cbad2e7bc6cdf7b0d7982e59", - "sha256:34eccd14566f8fe14b2b95bb13b11572f7c7d5c36da61caf414d23b91fcc5d94", - "sha256:3a58c98a7e9c021f357348867f537017057c2ed7f77337fd914d0bedb35dace7", - "sha256:3f78fd71c4f43a13d342be74ebbc0666fe1f555b8837eb113cb7416856c79682", - "sha256:4154ad09dac630a0f13f37b583eae260c6aa885d67dfbccb5b02c33f31a6d420", - "sha256:420f9bbf47a02616e8554e825208cb947969451978dceb77f95ad09c37791dae", - "sha256:4686818798f9194d03c9129a4d9a702d9e113a89cb03bffe08c6cf799e053291", - "sha256:57fede879f08d23c85140a360c6a77709113efd1c993923c59fde17aa27599fe", - "sha256:60989127da422b74a04345096c10d416c2b41bd7bf2a380eb541059e4e999980", - "sha256:64cf30263844fa208851ebb13b0732ce674d8ec6a0c86a4e160495d299ba3c93", - "sha256:68fc1f1ba168724771e38bee37d940d2865cb0f562380a1fb1ffb428b75cb692", - "sha256:6e6f98446430fdf41bd36d4faa6cb409f5140c1c2cf58ce0bbdaf16af7d3f119", - "sha256:729177eaf0aefca0994ce4cffe96ad3c75e377c7b6f4efa59ebf003b6d398716", - "sha256:72dffbd8b4194858d0941062a9766f8297e8868e1dd07a7b36212aaa90f49472", - "sha256:75723c3c0fbbf34350b46a3199eb50638ab22a0228f93fb472ef4d9becc2382b", - "sha256:77853062a2c45be16fd6b8d6de2a99278ee1d985a7bd8b103e97e41c034006d2", - "sha256:78151aa3ec21dccd5cdef6c74c3e73386dcdfaf19bced944169697d7ac7482fc", - "sha256:7f01846810177d829c7692f1f5ada8096762d9172af1b1a28d4ab5b77c923c1c", - "sha256:804d99b24ad523a1fe18cc707bf741670332f7c7412e9d49cb5eab67e886b9b5", - "sha256:81ff62668af011f9a48787564ab7eded4e9fb17a4a6a74af5ffa6a457400d2ab", - "sha256:8359bf4791968c5a78c56103702000105501adb557f3cf772b2c207284273984", - "sha256:83791a65b51ad6ee6cf0845634859d69a038ea9b03d7b26e703f94c7e93dbcf9", - "sha256:8532fd6e6e2dc57bcb3bc90b079c60de896d2128c5d9d6f24a63875a95a088cf", - "sha256:876801744b0dee379e4e3c38b76fc89f88834bb15bf92ee07d94acd06ec890a0", - "sha256:8dbf6d1bc73f1d04ec1734bae3b4fb0ee3cb2a493d35ede9badbeb901fb40f6f", - "sha256:8f8544b092a29a6ddd72f3556a9fcf249ec412e10ad28be6a0c0d948924f2212", - "sha256:911dda9c487075abd54e644ccdf5e5c16773470a6a5d3826fda76699410066fb", - "sha256:977646e05232579d2e7b9c59e21dbe5261f403a88417f6a6512e70d3f8a046be", - "sha256:9dba73be7305b399924709b91682299794887cbbd88e38226ed9f6712eabee90", - "sha256:a148c5d507bb9b4f2030a2025c545fccb0e1ef317393eaba42e7eabd28eb6041", - "sha256:a6cdcc3ede532f4a4b96000b6362099591ab4a3e913d70bcbac2b56c872446f7", - "sha256:ac05fb791acf5e1a3e39402641827780fe44d27e72567a000412c648a85ba860", - "sha256:b0605eaed3eb239e87df0d5e3c6489daae3f7388d455d0c0b4df899519c6a38d", - "sha256:b58b4710c7f4161b5e9dcbe73bb7c62d65670a87df7bcce9e1faaad43e715245", - "sha256:b6356793b84728d9d50ead16ab43c187673831e9d4019013f1402c41b1db9b27", - "sha256:b76bedd166805480ab069612119ea636f5ab8f8771e640ae103e05a4aae3e417", - "sha256:bc7bb56d04601d443f24094e9e31ae6deec9ccb23581f75343feebaf30423359", - "sha256:c2470da5418b76232f02a2fcd2229537bb2d5a7096674ce61859c3229f2eb202", - "sha256:c332c8d69fb64979ebf76613c66b985414927a40f8defa16cf1bc028b7b0a7b0", - "sha256:c6af2a6d4b7ee9615cbb162b0738f6e1fd1f5c3eda7e5da17861eacf4c717ea7", - "sha256:c77e3d1862452565875eb31bdb45ac62502feabbd53429fdc39a1cc341d681ba", - "sha256:ca08decd2697fdea0aea364b370b1249d47336aec935f87b8bbfd7da5b2ee9c1", - "sha256:ca49a8119c6cbd77375ae303b0cfd8c11f011abbbd64601167ecca18a87e7cdd", - "sha256:cb16c65dcb648d0a43a2521f2f0a2300f40639f6f8c1ecbc662141e4e3e1ee07", - "sha256:d2997c458c690ec2bc6b0b7ecbafd02b029b7b4283078d3b32a852a7ce3ddd98", - "sha256:d3f82c171b4ccd83bbaf35aa05e44e690113bd4f3b7b6cc54d2219b132f3ae55", - "sha256:dc4926288b2a3e9fd7b50dc6a1909a13bbdadfc67d93f3374d984e56f885579d", - "sha256:ead20f7913a9c1e894aebe47cccf9dc834e1618b7aa96155d2091a626e59c972", - "sha256:ebdc36bea43063116f0486869652cb2ed7032dbc59fbcb4445c4862b5c1ecf7f", - "sha256:ed1184ab8f113e8d660ce49a56390ca181f2981066acc27cf637d5c1e10ce46e", - "sha256:ee825e70b1a209475622f7f7b776785bd68f34af6e7a46e2e42f27b659b5bc26", - "sha256:f7ae5d65ccfbebdfa761585228eb4d0df3a8b15cfb53bd953e713e09fbb12957", - "sha256:f7fc5a5acafb7d6ccca13bfa8c90f8c51f13d8fb87d95656d3950f0158d3ce53", - "sha256:f9b5571d33660d5009a8b3c25dc1db560206e2d2f89d3df1cb32d72c0d117d52" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==2.9.9" - }, - "pyasn1": { - "hashes": [ - "sha256:87a2121042a1ac9358cabcaf1d07680ff97ee6404333bacca15f76aa8ad01a57", - "sha256:97b7290ca68e62a832558ec3976f15cbf911bf5d7c7039d8b861c2a0ece69fde" - ], - "index": "pypi", - "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" - ], - "index": "pypi", - "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" - }, - "pycouchdb": { - "hashes": [ - "sha256:00bc6c7dd4744895920b9153cb9537bc5ecaff72002ea10209c05580e186e0eb", - "sha256:434758aa6b49c6a67fcf89e71a11c36e2ec2df51e2998c38bcd570eab94cc288" - ], - "index": "pypi", - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==1.14.2" - }, - "pycparser": { - "hashes": [ - "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", - "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206" - ], - "index": "pypi", - "version": "==2.21" - }, - "pygments": { - "hashes": [ - "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199", - "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a" - ], - "markers": "python_version >= '3.8'", - "version": "==2.18.0" - }, - "pyjwt": { - "hashes": [ - "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de", - "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==2.8.0" - }, - "pyparsing": { - "hashes": [ - "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb", - "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc" - ], - "index": "pypi", - "markers": "python_full_version >= '3.6.8'", - "version": "==3.0.9" - }, - "python-dateutil": { - "hashes": [ - "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", - "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" - ], - "index": "pypi", - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==2.8.2" - }, - "python-decouple": { - "hashes": [ - "sha256:ba6e2657d4f376ecc46f77a3a615e058d93ba5e465c01bbe57289bfb7cce680f", - "sha256:d0d45340815b25f4de59c974b855bb38d03151d81b037d9e3f463b0c9f8cbd66" - ], - "index": "pypi", - "version": "==3.8" - }, - "python3-openid": { - "hashes": [ - "sha256:33fbf6928f401e0b790151ed2b5290b02545e8775f982485205a066f874aaeaf", - "sha256:6626f771e0417486701e0b4daff762e7212e820ca5b29fcc0d05f6f8736dfa6b" - ], - "index": "pypi", - "version": "==3.2.0" - }, - "pytz": { - "hashes": [ - "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588", - "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb" - ], - "index": "pypi", - "version": "==2023.3" - }, - "rcssmin": { - "hashes": [ - "sha256:271e3d2f8614a6d4637ed8fff3d90007f03e2a654cd9444f37d888797662ba72", - "sha256:35da6a6999e9e2c5b0e691b42ed56cc479373e0ecab33ef5277dfecce625e44a", - "sha256:42576d95dfad53d77df2e68dfdec95b89b10fad320f241f1af3ca1438578254a", - "sha256:4f9400b4366d29f5f5446f58e78549afa8338e6a59740c73115e9f6ac413dc64", - "sha256:705c9112d0ed54ea40aecf97e7fd29bdf0f1c46d278a32d8f957f31dde90778a", - "sha256:79421230dd67c37ec61ed9892813d2b839b68f2f48ef55c75f976e81701d60b4", - "sha256:868215e1fd0e92a6122e0ed5973dfc7bb8330fe1e92274d05b2585253b38c0ca", - "sha256:8a26fec3c1e6b7a3765ccbaccc20fbb5c0ed3422cc381e01a2607f08d7621c44", - "sha256:8fcfd10ae2a1c4ce231a33013f2539e07c3836bf17cc945cc25cc30bf8e68e45", - "sha256:908fe072efd2432fb0975a61124609a8e05021367f6a3463d45f5e3e74c4fdda", - "sha256:914e589f40573035006913861ed2adc28fbe70082a8b6bff5be7ee430b7b5c2e", - "sha256:a04d58a2a21e9a089306d3f99c4b12bf5b656a79c198ef2321e80f8fd9afab06", - "sha256:a417735d4023d47d048a6288c88dbceadd20abaaf65a11bb4fda1e8458057019", - "sha256:c30f8bc839747b6da59274e0c6e4361915d66532e26448d589cb2b1846d7bf11", - "sha256:c7278c1c25bb90d8e554df92cfb3b6a1195004ead50f764653d3093933ee0877", - "sha256:c7728e3b546b1b6ea08cab721e8e21409dbcc11b881d0b87d10b0be8930af2a2", - "sha256:cf74d7ea5e191f0f344b354eed8b7c83eeafbd9a97bec3a579c3d26edf11b005", - "sha256:d0afc6e7b64ef30d6dcde88830ec1a237b9f16a39f920a8fd159928684ccf8db", - "sha256:d4e263fa9428704fd94c2cb565c7519ca1d225217943f71caffe6741ab5b9df1", - "sha256:e923c105100ab70abde1c01d3196ddd6b07255e32073685542be4e3a60870c8e", - "sha256:ee386bec6d62f8c814d65c011d604a7c82d24aa3f718facd66e850eea8d6a5a1", - "sha256:f15673e97f0a68b4c378c4d15b088fe96d60bc106d278c88829923118833c20f", - "sha256:f7a1fcdbafaacac0530da04edca4a44303baab430ea42e7d59aece4b3f3e9a51" - ], - "index": "pypi", - "version": "==1.1.1" - }, - "redis": { - "hashes": [ - "sha256:0dab495cd5753069d3bc650a0dde8a8f9edde16fc5691b689a566eda58100d0f", - "sha256:ed4802971884ae19d640775ba3b03aa2e7bd5e8fb8dfaed2decce4d0fc48391f" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==5.0.1" - }, - "requests": { - "hashes": [ - "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f", - "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==2.31.0" - }, - "requests-oauthlib": { - "hashes": [ - "sha256:2577c501a2fb8d05a304c09d090d6e47c306fef15809d102b327cf8364bddab5", - "sha256:75beac4a47881eeb94d5ea5d6ad31ef88856affe2332b9aafb52c6452ccf0d7a" - ], - "index": "pypi", - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.3.1" - }, - "rjsmin": { - "hashes": [ - "sha256:113132a40ce7d03b2ced4fac215f0297338ed1c207394b739266efab7831988b", - "sha256:122aa52bcf7ad9f12728d309012d1308c6ecfe4d6b09ea867a110dcad7b7728c", - "sha256:145c6af8df42d8af102d0d39a6de2e5fa66aef9e38947cfb9d65377d1b9940b2", - "sha256:1f982be8e011438777a94307279b40134a3935fc0f079312ee299725b8af5411", - "sha256:3453ee6d5e7a2723ec45c2909e2382371783400e8d51952b692884c6d850a3d0", - "sha256:35827844d2085bd59d34214dfba6f1fc42a215c455887437b07dbf9c73019cc1", - "sha256:35f21046504544e2941e04190ce24161255479133751550e36ddb3f4af0ecdca", - "sha256:5d67ec09da46a492186e35cabca02a0d092eda5ef5b408a419b99ee4acf28d5c", - "sha256:747bc9d3bc8a220f40858e6aad50b2ae2eb7f69c924d4fa3803b81be1c1ddd02", - "sha256:7dd58b5ed88233bc61dc80b0ed87b93a1786031d9977c70d335221ef1ac5581a", - "sha256:812af25c08d6a5ae98019a2e1b47ebb47f7469abd351670c353d619eaeae4064", - "sha256:8a6710e358c661dcdcfd027e67de3afd72a6af4c88101dcf110de39e9bbded39", - "sha256:8c340e251619c97571a5ade20f147f1f7e8664f66a2d6d7319e05e3ef6a4423c", - "sha256:99c074cd6a8302ff47118a9c3d086f89328dc8e5c4b105aa1f348fb85c765a30", - "sha256:b8464629a18fe69f70677854c93a3707976024b226a0ce62707c618f923e1346", - "sha256:bbd7a0abaa394afd951f5d4e05249d306fec1c9674bfee179787674dddd0bdb7", - "sha256:bc5bc2f94e59bc81562c572b7f1bdd6bcec4f61168dc68a2993bad2d355b6e19", - "sha256:bd1faedc425006d9e86b23837d164f01d105b7a8b66b767a9766d0014773db2a", - "sha256:ca90630b84fe94bb07739c3e3793e87d30c6ee450dde08653121f0d9153c8d0d", - "sha256:d332e44a1b21ad63401cc7eebc81157e3d982d5fb503bb4faaea5028068d71e9", - "sha256:eb770aaf637919b0011c4eb87b9ac6317079fb9800eb17c90dda05fc9de4ebc3", - "sha256:f0895b360dccf7e2d6af8762a52985e3fbaa56778de1bf6b20dbc96134253807", - "sha256:f7cd33602ec0f393a0058e883284496bb4dbbdd34e0bbe23b594c8933ddf9b65" - ], - "index": "pypi", - "version": "==1.2.1" - }, - "rsa": { - "hashes": [ - "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7", - "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21" - ], - "index": "pypi", - "markers": "python_version >= '3.6' and python_version < '4'", - "version": "==4.9" - }, - "six": { - "hashes": [ - "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", - "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" - ], - "index": "pypi", - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.16.0" - }, - "sqlparse": { - "hashes": [ - "sha256:5430a4fe2ac7d0f93e66f1efc6e1338a41884b7ddf2a350cedd20ccc4d9d28f3", - "sha256:d446183e84b8349fa3061f0fe7f06ca94ba65b426946ffebe6e3e8295332420c" - ], - "index": "pypi", - "markers": "python_version >= '3.5'", - "version": "==0.4.4" - }, - "tornado": { - "hashes": [ - "sha256:02ccefc7d8211e5a7f9e8bc3f9e5b0ad6262ba2fbb683a6443ecc804e5224ce0", - "sha256:10aeaa8006333433da48dec9fe417877f8bcc21f48dda8d661ae79da357b2a63", - "sha256:27787de946a9cffd63ce5814c33f734c627a87072ec7eed71f7fc4417bb16263", - "sha256:6f8a6c77900f5ae93d8b4ae1196472d0ccc2775cc1dfdc9e7727889145c45052", - "sha256:71ddfc23a0e03ef2df1c1397d859868d158c8276a0603b96cf86892bff58149f", - "sha256:72291fa6e6bc84e626589f1c29d90a5a6d593ef5ae68052ee2ef000dfd273dee", - "sha256:88b84956273fbd73420e6d4b8d5ccbe913c65d31351b4c004ae362eba06e1f78", - "sha256:e43bc2e5370a6a8e413e1e1cd0c91bedc5bd62a74a532371042a18ef19e10579", - "sha256:f0251554cdd50b4b44362f73ad5ba7126fc5b2c2895cc62b14a1c2d7ea32f212", - "sha256:f7894c581ecdcf91666a0912f18ce5e757213999e183ebfc2c3fdbf4d5bd764e", - "sha256:fd03192e287fbd0899dd8f81c6fb9cbbc69194d2074b38f384cb6fa72b80e9c2" - ], - "markers": "python_version >= '3.8'", - "version": "==6.4" - }, - "tzdata": { - "hashes": [ - "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a", - "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda" - ], - "index": "pypi", - "markers": "python_version >= '2'", - "version": "==2023.3" - }, - "urllib3": { - "hashes": [ - "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84", - "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==2.0.7" - }, - "vine": { - "hashes": [ - "sha256:4c9dceab6f76ed92105027c49c823800dd33cacce13bdedc5b914e3514b7fb30", - "sha256:7d3b1624a953da82ef63462013bbd271d3eb75751489f9807598e8f340bd637e" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==5.0.0" - }, - "wcwidth": { - "hashes": [ - "sha256:77f719e01648ed600dfa5402c347481c0992263b81a027344f3e1ba25493a704", - "sha256:8705c569999ffbb4f6a87c6d1b80f324bd6db952f5eb0b95bc07517f4c1813d4" - ], - "index": "pypi", - "version": "==0.2.8" - }, - "yarl": { - "hashes": [ - "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51", - "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce", - "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559", - "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0", - "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81", - "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc", - "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4", - "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c", - "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130", - "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136", - "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e", - "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec", - "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7", - "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1", - "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455", - "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099", - "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129", - "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10", - "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142", - "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98", - "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa", - "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7", - "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525", - "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c", - "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9", - "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c", - "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8", - "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b", - "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf", - "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23", - "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd", - "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27", - "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f", - "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece", - "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434", - "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec", - "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff", - "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78", - "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d", - "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863", - "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53", - "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31", - "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15", - "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5", - "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b", - "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57", - "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3", - "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1", - "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f", - "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad", - "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c", - "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7", - "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2", - "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b", - "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2", - "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b", - "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9", - "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be", - "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e", - "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984", - "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4", - "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074", - "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2", - "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392", - "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91", - "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541", - "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf", - "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572", - "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66", - "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575", - "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14", - "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5", - "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1", - "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e", - "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551", - "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17", - "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead", - "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0", - "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe", - "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234", - "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0", - "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7", - "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34", - "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42", - "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385", - "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78", - "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be", - "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958", - "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749", - "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec" - ], - "markers": "python_version >= '3.7'", - "version": "==1.9.4" - } - }, - "develop": { - "black": { - "hashes": [ - - "sha256:257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474", - "sha256:37aae07b029fa0174d39daf02748b379399b909652a806e5708199bd93899da1", - "sha256:415e686e87dbbe6f4cd5ef0fbf764af7b89f9057b97c908742b6008cc554b9c0", - "sha256:48a85f2cb5e6799a9ef05347b476cce6c182d6c71ee36925a6c194d074336ef8", - "sha256:7768a0dbf16a39aa5e9a3ded568bb545c8c2727396d063bbaf847df05b08cd96", - "sha256:7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1", - "sha256:88c57dc656038f1ab9f92b3eb5335ee9b021412feaa46330d5eba4e51fe49b04", - "sha256:8e537d281831ad0e71007dcdcbe50a71470b978c453fa41ce77186bbe0ed6021", - "sha256:98e123f1d5cfd42f886624d84464f7756f60ff6eab89ae845210631714f6db94", - "sha256:accf49e151c8ed2c0cdc528691838afd217c50412534e876a19270fea1e28e2d", - "sha256:b1530ae42e9d6d5b670a34db49a94115a64596bc77710b1d05e9801e62ca0a7c", - "sha256:b9176b9832e84308818a99a561e90aa479e73c523b3f77afd07913380ae2eab7", - "sha256:bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c", - "sha256:be8bef99eb46d5021bf053114442914baeb3649a89dc5f3a555c88737e5e98fc", - "sha256:bf10f7310db693bb62692609b397e8d67257c55f949abde4c67f9cc574492cc7", - "sha256:c872b53057f000085da66a19c55d68f6f8ddcac2642392ad3a355878406fbd4d", - "sha256:d36ed1124bb81b32f8614555b34cc4259c3fbc7eec17870e8ff8ded335b58d8c", - "sha256:da33a1a5e49c4122ccdfd56cd021ff1ebc4a1ec4e2d01594fef9b6f267a9e741", - "sha256:dd1b5a14e417189db4c7b64a6540f31730713d173f0b63e55fabd52d61d8fdce", - "sha256:e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb", - "sha256:eaea3008c281f1038edb473c1aa8ed8143a5535ff18f978a318f10302b254063", - "sha256:ef703f83fc32e131e9bcc0a5094cfe85599e7109f896fe8bc96cc402f3eb4b6e" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==24.4.2" - - }, - "cfgv": { - "hashes": [ - "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", - "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560" - ], - "markers": "python_version >= '3.8'", - "version": "==3.4.0" - }, - "click": { - "hashes": [ - "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", - "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==8.1.7" - }, - "colorama": { - "hashes": [ - "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", - "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" - ], - "index": "pypi", - "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": "==0.4.6" - }, - "distlib": { - "hashes": [ - "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784", - "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64" - ], - "version": "==0.3.8" - }, - "filelock": { - "hashes": [ - "sha256:43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f", - "sha256:6ea72da3be9b8c82afd3edcf99f2fffbb5076335a5ae4d03248bb5b6c3eae78a" - ], - "markers": "python_version >= '3.8'", - "version": "==3.14.0" - }, - "identify": { - "hashes": [ - - "sha256:37d93f380f4de590500d9dba7db359d0d3da95ffe7f9de1753faa159e71e7dfa", - "sha256:e5e00f54165f9047fbebeb4a560f9acfb8af4c88232be60a488e9b68d122745d" - ], - "markers": "python_version >= '3.8'", - "version": "==2.5.36" - - }, - "isort": { - "hashes": [ - "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109", - "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6" - ], - "index": "pypi", - "markers": "python_full_version >= '3.8.0'", - "version": "==5.13.2" - }, - "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" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==23.1" - }, - "pathspec": { - "hashes": [ - "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", - "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712" - ], - "markers": "python_version >= '3.8'", - "version": "==0.12.1" - }, - "platformdirs": { - "hashes": [ - - "sha256:031cd18d4ec63ec53e82dceaac0417d218a6863f7745dfcc9efe7793b7039bdf", - "sha256:17d5a1161b3fd67b390023cb2d3b026bbd40abde6fdb052dfbd3a29c3ba22ee1" - ], - "markers": "python_version >= '3.8'", - "version": "==4.2.1" - }, - "pre-commit": { - "hashes": [ - "sha256:5eae9e10c2b5ac51577c3452ec0a490455c45a0533f7960f993a0d01e59decab", - "sha256:e209d61b8acdcf742404408531f0c37d49d2c734fd7cff2d6076083d191cb060" - ], - "index": "pypi", - "markers": "python_version >= '3.9'", - "version": "==3.7.0" - - }, - "pyyaml": { - "hashes": [ - "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5", - "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc", - "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df", - "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741", - "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206", - "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27", - "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595", - "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62", - "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98", - "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696", - "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290", - "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9", - "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d", - "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6", - "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867", - "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47", - "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486", - "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6", - "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3", - "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007", - "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938", - "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0", - "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c", - "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735", - "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d", - "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28", - "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4", - "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba", - "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8", - "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef", - "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5", - "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd", - "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3", - "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0", - "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515", - "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c", - "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c", - "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924", - "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34", - "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43", - "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859", - "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673", - "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54", - "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a", - "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b", - "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab", - "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa", - "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c", - "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585", - "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d", - "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f" - ], - "markers": "python_version >= '3.6'", - "version": "==6.0.1" - }, - "setuptools": { - "hashes": [ - - "sha256:6c1fccdac05a97e598fb0ae3bbed5904ccb317337a51139dcd51453611bbb987", - "sha256:c636ac361bc47580504644275c9ad802c50415c7522212252c033bd15f301f32" - ], - "markers": "python_version >= '3.8'", - "version": "==69.5.1" - }, - "virtualenv": { - "hashes": [ - "sha256:604bfdceaeece392802e6ae48e69cec49168b9c5f4a44e483963f9242eb0e78b", - "sha256:7aa9982a728ae5892558bff6a2839c00b9ed145523ece2274fad6f414690ae75" - ], - "markers": "python_version >= '3.7'", - "version": "==20.26.1" - - } - } -} diff --git a/AHC_app/animals/tests.py b/AHC_app/animals/tests.py deleted file mode 100644 index a39b155..0000000 --- a/AHC_app/animals/tests.py +++ /dev/null @@ -1 +0,0 @@ -# Create your tests here. diff --git a/AHC_app/homepage/admin.py b/AHC_app/homepage/admin.py deleted file mode 100644 index 23fc0d8..0000000 --- a/AHC_app/homepage/admin.py +++ /dev/null @@ -1,26 +0,0 @@ -from django.contrib import admin -from homepage.models import AnimalTitle, CronJob - -admin.site.register(AnimalTitle) - - -class CronJobAdmin(admin.ModelAdmin): - list_display = ("name", "schedule", "last_execution", "next_execution") - readonly_fields = ( - "name", - "command", - "schedule", - "last_execution", - "next_execution", - ) - - def changelist_view(self, request, extra_context=None): - extra_context = extra_context or {} - extra_context["cronjobs"] = CronJob.objects.all() - return super().changelist_view(request, extra_context=extra_context) - - def has_add_permission(self, request): - return False - - -admin.site.register(CronJob, CronJobAdmin) diff --git a/AHC_app/homepage/management/__init__.py b/AHC_app/homepage/management/__init__.py deleted file mode 100644 index cb65698..0000000 --- a/AHC_app/homepage/management/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .commands.sync_cronjobs import Command diff --git a/AHC_app/homepage/management/commands/sync_cronjobs.py b/AHC_app/homepage/management/commands/sync_cronjobs.py deleted file mode 100644 index 80ccaa6..0000000 --- a/AHC_app/homepage/management/commands/sync_cronjobs.py +++ /dev/null @@ -1,23 +0,0 @@ -import subprocess - -from django.core.management.base import BaseCommand -from homepage.models import CronJob - - -class Command(BaseCommand): - help = "Sync cronjobs with the actual cron configuration" - - def handle(self, *args, **options): - cronjob_info = subprocess.run(["crontab", "-l"], stdout=subprocess.PIPE, text=True).stdout.splitlines() - - CronJob.objects.all().delete() - - for job_info in cronjob_info: - schedule, command = job_info.split(" /", 1) - function_name = command.strip().split(".")[-1] - cron_job = CronJob(schedule=schedule, command=command) - - cron_job.name = f"Cron Job: {function_name}" - cron_job.last_execution = None - cron_job.next_execution = None - cron_job.save() diff --git a/AHC_app/medical_notes/admin.py b/AHC_app/medical_notes/admin.py deleted file mode 100644 index 8c38f3f..0000000 --- a/AHC_app/medical_notes/admin.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.contrib import admin - -# Register your models here. diff --git a/AHC_app/medical_notes/tests.py b/AHC_app/medical_notes/tests.py deleted file mode 100644 index 7ce503c..0000000 --- a/AHC_app/medical_notes/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/AHC_app/users/tests.py b/AHC_app/users/tests.py deleted file mode 100644 index 7ce503c..0000000 --- a/AHC_app/users/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/README.md b/README.md index 9fceab6..8bc0102 100644 --- a/README.md +++ b/README.md @@ -22,12 +22,12 @@
- - + + - - + +

Animal profile

Full timeline of notes

Animal profile

Full timeline of notes

Diet note details

User registration

Diet note details

User registration

@@ -44,11 +44,13 @@ --- ### Requirements: -- Python 3.12.2 +- Python 3.14 +- [uv](https://docs.astral.sh/uv/) (package manager) +- [just](https://just.systems/) (task runner, optional) - Docker & Docker Compose - PostgreSQL 15 (instance for volumes) - Apache CouchDB 3.3.3 (instance for volumes) -- [Packages](AHC_app/Pipfile) +- [Packages](pyproject.toml) - [pico-1.5.10](https://github.com/picocss/pico/archive/refs/tags/v1.5.10.zip) --- @@ -56,7 +58,7 @@ 1. Download repository. 2. Set .env file based on template. 3. Install Docker Desktop. -4. Run containters: +4. Run containers: ``` docker-compose up -d --build ``` @@ -65,24 +67,28 @@ ### Dev-instance steps: 1. Download repository. 2. Set .env file based on the template. -3. Install Python, Docker Desktop, PostgreSQL and CouchDB as in _Requirements_. -4. Install pipenv: +3. Install Python 3.14, Docker Desktop, PostgreSQL and CouchDB as in _Requirements_. +4. Install uv and sync dependencies: ``` - pipenv install + pip install uv + uv sync ``` -5. Deploy vevn and synch requirements: +5. Install pre-commit hooks: ``` - pipenv install --dev + uv run pre-commit install ``` -6. Install precommit hooks: - ``` - pre-commit install - ``` -7. Run containters: +6. Run containers: ``` docker-compose up -d --build ``` +With `just` installed, steps 4–6 simplify to: +``` +just install +just precommit +just docker-up +``` + --- ### Kubernetes Deploy steps (alternative deploy): 1. Download repository. @@ -97,7 +103,7 @@ docker image save -o ahc_app-web.tar ahc_app-web:latest docker image save -o ahc_app-queue.tar ahc_app-queue:latest docker image save -o ahc_app-couch_db.tar ahc_app-couch_db:latest - docker image save -o postgres.tar postgres:15-alpine + docker image save -o postgres.tar postgres:18-alpine ``` 5. Push Docker images to a registry: @@ -107,7 +113,7 @@ minikube image load ahc_app-web.tar minikube image load ahc_app-queue.tar minikube image load ahc_app-couch_db.tar - minikube image load postgres.tar + minikube image load postgres.tar # postgres:18-alpine ``` 6. Deploy to Kubernetes using kustom files: @@ -127,8 +133,17 @@ --- ### Test running: -- by now tests are only reachable by terminal in main container's terminal (container_name: web) -- simply run command "python manage.py test" or use with needed flags +```bash +# pytest (recommended) +uv run pytest -m integration + +# or with just +just test +just test-integration + +# Django runner (legacy, still supported) +uv run python manage.py test +``` --- ### Sources: diff --git a/conftest.py b/conftest.py new file mode 100644 index 0000000..72922e2 --- /dev/null +++ b/conftest.py @@ -0,0 +1,34 @@ +from unittest.mock import MagicMock, patch + +import pytest +from django.contrib.auth.models import User + + +@pytest.fixture +def user_profile(db): + """Create a User + Profile pair, mocking image processing in Profile.save().""" + from ahc.apps.users.models import Profile + + user = User.objects.create_user(username="testuser", password="testpass123") + with patch("ahc.apps.users.models.Image.open") as mock_open: + mock_img = MagicMock() + mock_img.height = 100 + mock_img.width = 100 + mock_open.return_value = mock_img + profile = Profile.objects.create(user=user) + return user, profile + + +@pytest.fixture +def second_user_profile(db): + """A second User + Profile for multi-user permission tests.""" + from ahc.apps.users.models import Profile + + user = User.objects.create_user(username="otheruser", password="testpass123") + with patch("ahc.apps.users.models.Image.open") as mock_open: + mock_img = MagicMock() + mock_img.height = 100 + mock_img.width = 100 + mock_open.return_value = mock_img + profile = Profile.objects.create(user=user) + return user, profile diff --git a/doc/01_adr_functionality.md b/doc/01_adr_functionality.md index dff92df..b4f56c0 100644 --- a/doc/01_adr_functionality.md +++ b/doc/01_adr_functionality.md @@ -5,15 +5,15 @@ `2023-06-04` -### Status +### Status In-building -### Context +### Context We need to create a list of main functions to define business justification of first version of an application and decide what functionality should be canceled or suspended to further implementation in next releases. -### Decision +### Decision A first brainstorm created a list of basic functions expectted to implement: - Create a databases to contain at least data like: @@ -25,18 +25,18 @@ A first brainstorm created a list of basic functions expectted to implement: - Generate static diagrams on button demand, like a charts of weight and consumed amount of medicines, - Creat sticky notes kanboard to manage a feeding period per purchased food, - Sending visit notifications via at least one of: sms, whatsap, messenger, e-mail, discord, -- Printable notes and charts into pdf reports, +- Printable notes and charts into pdf reports, - Synchronization into a google calendar, - Basic API to consider a transfer of charts into Dash-Plotly. List to-do's suspended until next iterations of application: - Interactive dashboards, -- Implementation all of proposed notification methods, +- Implementation all of proposed notification methods, - Direct chat between users, without using animal's notes. -### Consequences -An effortful list of functionality has been created to exercise a building process of web applications. +### Consequences +An effortful list of functionality has been created to exercise a building process of web applications. The demands have been divided into quickly attainable goals, leaving a basic draft of a further development. diff --git a/doc/02_adr_django.md b/doc/02_adr_django.md index adb99b8..454a427 100644 --- a/doc/02_adr_django.md +++ b/doc/02_adr_django.md @@ -5,35 +5,35 @@ `2023-06-05` -### Status +### Status Done -### Context +### Context We need to choose a main web framework for the project to create the core of the application.\ Considered technologies: -- [x] Django, +- [x] Django, - [ ] Flask, - [ ] Dash Plotly. -### Decision +### Decision Django was selected. The developer has the most recent experience and the desire to systematize knowledge. Flask, as a microframework, could extend the time to the first working prototype. -Dash is a derivative framework for Flask with extensive features for generating interactive dashboards. +Dash is a derivative framework for Flask with extensive features for generating interactive dashboards. This functionality has been postponed to a later stage of the application development. -### Consequences +### Consequences An expected short time to prepare the first working prototype. With good community support, plugins supporting specific functionalities should be available (ORM, logging, api, etc.). ### Keywords - Django, -- Flask, +- Flask, - Dash Plotly, - web framework. diff --git a/doc/03_adr_monolit.md b/doc/03_adr_monolit.md index 4f42667..fbd98a4 100644 --- a/doc/03_adr_monolit.md +++ b/doc/03_adr_monolit.md @@ -5,23 +5,23 @@ `2023-06-05` -### Status +### Status Done -### Context +### Context We need to choose an approach to building the project's application structure.\ -Considered approaches: +Considered approaches: - [x] Monolith, - [ ] Microservices. -### Decision -Due to the selection of Django as the main framework, an application in the monolithic architecture will be created, +### Decision +Due to the selection of Django as the main framework, an application in the monolithic architecture will be created, open via APIs to the possibility of adding selective functionalities in the form of microservices. -### Consequences +### Consequences Each new functionality will need to be considered to determine it will be easier to implement as a fragment of the monolith or as a new microservice. diff --git a/doc/04_adr_monorepo.md b/doc/04_adr_monorepo.md index 86d7b64..a9da6d9 100644 --- a/doc/04_adr_monorepo.md +++ b/doc/04_adr_monorepo.md @@ -5,13 +5,13 @@ `2023-06-05` -### Status +### Status Done -### Context +### Context We need to choose an approach to building and maintaining the repositories and branches.\ -Considered approaches: +Considered approaches: - [x] Monorepo, - [ ] Polirepo, --- @@ -21,14 +21,14 @@ Considered approaches: - [ ] Trunk-based development. -### Decision +### Decision The Monorepo approach will be used due to the small number of developers and the expected number of parallel branches. -The number of developers also affects the decision to manage branches and approach to deployment. -GitHub-Flow was selected. In a small organization, a least detailed approach will suffice. +The number of developers also affects the decision to manage branches and approach to deployment. +GitHub-Flow was selected. In a small organization, a least detailed approach will suffice. -### Consequences +### Consequences Possible future migrations will be easier in the direction from simpler to more complicated. diff --git a/doc/05_adr_matlibplot.md b/doc/05_adr_matlibplot.md index cc3f0fa..8f171bc 100644 --- a/doc/05_adr_matlibplot.md +++ b/doc/05_adr_matlibplot.md @@ -5,13 +5,13 @@ `2023-06-05` -### Status +### Status Proposed -### Context +### Context We need to choose a technology to create charts for the application.\ -Considered approaches: +Considered approaches: - [x] Static charts: - [x] Matplotlib, @@ -21,12 +21,12 @@ Considered approaches: - [x] Chart.js, -### Decision -To avoid the proliferation of microservices, a decision has been made to prototype using a static method of generating charts. +### Decision +To avoid the proliferation of microservices, a decision has been made to prototype using a static method of generating charts. The presented data is not expected to require frequent refreshing and filtering of the range. -### Consequences +### Consequences A faster development process and the possibility of future functionality replacement. After preparing the static prototype, tests with Chart.js will be carried out and the cost of implementation will be estimated. diff --git a/doc/06_adr_html_template.md b/doc/06_adr_html_template.md index 9caf563..62dc2db 100644 --- a/doc/06_adr_html_template.md +++ b/doc/06_adr_html_template.md @@ -5,19 +5,19 @@ `2023-06-05` -### Status +### Status Done -### Context +### Context We need to choose a main template for frontend part of the project. -### Decision +### Decision pass -### Consequences +### Consequences pass ### Keywords diff --git a/doc/07_adr_drf.md b/doc/07_adr_drf.md index 5e2c3db..45335b2 100644 --- a/doc/07_adr_drf.md +++ b/doc/07_adr_drf.md @@ -5,23 +5,23 @@ `2023-06-05` -### Status +### Status Proposed -### Context +### Context We need to choose a basic API framework to inside and outside communication.\ -Considered approaches: +Considered approaches: - Django REST Framework, - Django Ninja, - FastAPI, - GraphQL. -### Decision +### Decision pass -### Consequences +### Consequences pass diff --git a/doc/08_adr_databases.md b/doc/08_adr_databases.md index 18d6162..9c7e12a 100644 --- a/doc/08_adr_databases.md +++ b/doc/08_adr_databases.md @@ -5,13 +5,13 @@ `2023-06-05` -### Status +### Status In-building -### Context +### Context We need to choose a database for a specific task within the application.\ -Considered DBMS: +Considered DBMS: - [x] PostgreSQL, - [ ] MS SQL, - [ ] MySQL, @@ -22,7 +22,7 @@ Considered DBMS: - [x] CouchDB. -### Decision +### Decision Tree databases have been selected for routing testing. PostgreSQL - quick database creation and configuration with a good SQL interface. It has many use cases with Django. @@ -32,8 +32,8 @@ CouchDB - native support for files as attachments. Non-relational database, inte Redis - default broker for Celery queue. -### Consequences -In basic form database routing is required. +### Consequences +In basic form database routing is required. The implementation should be quick, as the second database will be used only for storing attachment files. @@ -53,11 +53,11 @@ Homepages: https://www.sqlite.org/index.html https://www.mongodb.com/ - + https://redis.io/ - + https://firebirdsql.org/ - + https://couchdb.apache.org/ *[2023-01-24]*\ diff --git a/doc/09_adr_user_data.md b/doc/09_adr_user_data.md index 49839c4..257e8df 100644 --- a/doc/09_adr_user_data.md +++ b/doc/09_adr_user_data.md @@ -5,13 +5,13 @@ `2023-07-09` -### Status +### Status In-building -### Context +### Context We need to set up a place in documentation to list all collect all data about users and group them by correct place in databases and direct tables. -Main sections of data by sources: +Main sections of data by sources: - user, - animal, - medical record note, @@ -19,14 +19,14 @@ Main sections of data by sources: - medicines, - medical facility, - veterinarian, -- dates sheduling, +- dates scheduling, - costs counting. -### Decision +### Decision User datatables: - collected by the registration process: - - basic provided by user informations: + - basic provided by user information: - name, - email, - password, @@ -34,21 +34,21 @@ User datatables: - date of registration, - default profile image, - default background image, - - default user priviliges (viever, owner, creator, moderator, admin etc.) + - default user privileges (viewer, owner, creator, moderator, admin etc.) - collected after the registration process: - provided in profil page: - profile image, - - bacground image choosen, + - background image chosen, - email-change, - password-change, - date of birthday, - stable view(compedium of animals: owned and cared) - connections other models: - - animal - ovner, viewer, - - medical record nove - participation in visit + - animal - owner, viewer, + - medical record note - participation in visit - medical_place_id, - note_ - - + - Medical records (animal timeline) @@ -73,7 +73,7 @@ Medical records (animal timeline) -### Consequences +### Consequences ##### _Placeholder_ diff --git a/doc/10_adr_notification_trigger.md b/doc/10_adr_notification_trigger.md index fc9047c..72f9713 100644 --- a/doc/10_adr_notification_trigger.md +++ b/doc/10_adr_notification_trigger.md @@ -5,11 +5,11 @@ `2023-12-19` -### Status +### Status In-building -### Context +### Context We need to choose a technology for sending set by users notifications. The basic channel for sending notifications include: - e-mail, @@ -25,11 +25,11 @@ Options: - django-cron. -### Decision +### Decision Django-crontab -### Consequences +### Consequences 1. **Integration with Django:** django-crontab is a Django extension, making it a natural choice for seamlessly scheduling tasks in a Django-based application. This integration facilitates code maintenance and management. @@ -43,7 +43,7 @@ Django-crontab ### Keywords - Celery, - Cronjobs, -- queue, +- queue, - broker, - subscriptions,. diff --git a/docker/.dockerignore b/docker/.dockerignore new file mode 100644 index 0000000..1f45f28 --- /dev/null +++ b/docker/.dockerignore @@ -0,0 +1,9 @@ +./tars/* +*.tar +.venv/ +__pycache__/ +*.py[cod] +db.sqlite3 +static_collected/ +static/media/profile_pics/ +static/media/attachments/ diff --git a/AHC_app/Dockerfile-couchdb b/docker/Dockerfile-couchdb similarity index 76% rename from AHC_app/Dockerfile-couchdb rename to docker/Dockerfile-couchdb index 1e71bdb..bf03851 100644 --- a/AHC_app/Dockerfile-couchdb +++ b/docker/Dockerfile-couchdb @@ -5,6 +5,6 @@ ARG COUCHDB_PASSWORD ARG COUCHDB_PORT EXPOSE ${COUCHDB_PORT} -COPY setup_couchdb.sh setup_couchdb.sh +COPY docker/setup_couchdb.sh setup_couchdb.sh RUN chmod +x setup_couchdb.sh RUN sh setup_couchdb.sh diff --git a/docker/Dockerfile-queue b/docker/Dockerfile-queue new file mode 100644 index 0000000..c4ca1d3 --- /dev/null +++ b/docker/Dockerfile-queue @@ -0,0 +1,16 @@ +# syntax=docker/dockerfile:1.7 +FROM python:3.14-slim AS builder +WORKDIR /app +RUN pip install uv --break-system-packages +COPY pyproject.toml uv.lock ./ +ENV UV_PYTHON_PREFERENCE=only-system \ + UV_PROJECT_ENVIRONMENT=/opt/venv +RUN --mount=type=cache,target=/root/.cache/uv,sharing=locked \ + uv sync --no-group dev + +FROM python:3.14-slim AS runtime +LABEL authors="AM" +WORKDIR /app +COPY --from=builder /opt/venv /opt/venv +ENV PATH="/opt/venv/bin:$PATH" +COPY . . diff --git a/docker/Dockerfile-web b/docker/Dockerfile-web new file mode 100644 index 0000000..c4ca1d3 --- /dev/null +++ b/docker/Dockerfile-web @@ -0,0 +1,16 @@ +# syntax=docker/dockerfile:1.7 +FROM python:3.14-slim AS builder +WORKDIR /app +RUN pip install uv --break-system-packages +COPY pyproject.toml uv.lock ./ +ENV UV_PYTHON_PREFERENCE=only-system \ + UV_PROJECT_ENVIRONMENT=/opt/venv +RUN --mount=type=cache,target=/root/.cache/uv,sharing=locked \ + uv sync --no-group dev + +FROM python:3.14-slim AS runtime +LABEL authors="AM" +WORKDIR /app +COPY --from=builder /opt/venv /opt/venv +ENV PATH="/opt/venv/bin:$PATH" +COPY . . diff --git a/AHC_app/docker-compose.yml b/docker/docker-compose.yml similarity index 74% rename from AHC_app/docker-compose.yml rename to docker/docker-compose.yml index fdd7181..380ed09 100644 --- a/AHC_app/docker-compose.yml +++ b/docker/docker-compose.yml @@ -2,13 +2,13 @@ version: "3.9" services: web: build: - context: . - dockerfile: Dockerfile-web + context: .. + dockerfile: docker/Dockerfile-web image: ahc_app-web:latest ports: - "8000:8000" volumes: - - .:/app + - ..:/app depends_on: postgres_db: condition: service_healthy @@ -18,21 +18,17 @@ services: condition: service_healthy environment: - PYTHONUNBUFFERED=1 - - PYTHONPATH=/app + - PYTHONPATH=/app/src entrypoint: ["/bin/bash", "-c"] command: - | python manage.py makemigrations python manage.py migrate python manage.py collectstatic --noinput - python manage.py crontab remove - python manage.py crontab add - python manage.py sync_cronjobs - python manage.py runcrons python manage.py runserver 0.0.0.0:8000 postgres_db: - image: postgres:15-alpine + image: postgres:18-alpine container_name: main-db environment: - POSTGRES_DB=${POSTGRES_DB} @@ -51,8 +47,8 @@ services: couch_db: build: - context: . - dockerfile: Dockerfile-couchdb + context: .. + dockerfile: docker/Dockerfile-couchdb args: COUCHDB_USER: ${COUCHDB_USER} COUCHDB_PASSWORD: ${COUCHDB_PASSWORD} @@ -74,9 +70,9 @@ services: queue: build: - context: . - dockerfile: Dockerfile-queue - command: celery -A AHC_app.celery_notifications.config:celery_obj worker -l info + context: .. + dockerfile: docker/Dockerfile-queue + command: celery -A celery_notifications.config:celery_obj worker -l info depends_on: redis: condition: service_healthy @@ -87,9 +83,26 @@ services: ports: - "5000:5000" environment: - - DJANGO_SETTINGS_MODULE=AHC_app.settings + - DJANGO_SETTINGS_MODULE=ahc.settings - PYTHONUNBUFFERED=1 - - PYTHONPATH=/app + - PYTHONPATH=/app/src + + celery_beat: + build: + context: .. + dockerfile: docker/Dockerfile-queue + command: celery -A celery_notifications.config:celery_obj beat -l info + depends_on: + redis: + condition: service_healthy + postgres_db: + condition: service_healthy + environment: + - DJANGO_SETTINGS_MODULE=ahc.settings + - PYTHONUNBUFFERED=1 + - PYTHONPATH=/app/src + env_file: + - ../.env redis: image: redis:7-alpine diff --git a/AHC_app/setup_couchdb.sh b/docker/setup_couchdb.sh similarity index 100% rename from AHC_app/setup_couchdb.sh rename to docker/setup_couchdb.sh diff --git a/justfile b/justfile new file mode 100644 index 0000000..7cebea3 --- /dev/null +++ b/justfile @@ -0,0 +1,56 @@ +set shell := ["pwsh", "-NoLogo", "-Command"] + +# List all available recipes +help: + @just --list + +# Install all dependencies including dev group +install: + uv sync + +# Run all linters (ruff check, codespell, bandit) +lint: + uv run ruff check . + uv run codespell + uv run bandit -r . -c pyproject.toml -q + +# Format code and auto-fix lint issues +format: + uv run ruff format . + uv run ruff check --fix . + +# Run all tests excluding slow +test: + uv run pytest -m "not slow" + +# Run only unit tests +test-unit: + uv run pytest -m unit -v + +# Run only integration tests +test-integration: + uv run pytest -m integration -v + +# Start Django development server +runserver: + uv run python manage.py runserver + +# Apply database migrations +migrate: + uv run python manage.py migrate + +# Open Django shell +shell: + uv run python manage.py shell + +# Start all Docker services +docker-up: + docker-compose -f docker/docker-compose.yml up -d --build + +# Stop all Docker services +docker-down: + docker-compose -f docker/docker-compose.yml down + +# Run pre-commit hooks on all files +precommit: + uv run pre-commit run --all-files diff --git a/kubernetes/backend/web/secret.yaml.template b/kubernetes/backend/web/secret.yaml.template index 879694f..9b64c58 100644 --- a/kubernetes/backend/web/secret.yaml.template +++ b/kubernetes/backend/web/secret.yaml.template @@ -22,7 +22,7 @@ stringData: COUCH_CONNECTOR: "Server(\"http://127.0.0.1:5982\")" CELERY_BACKEND: "redis://redis:6379/0" - DJANGO_SETTINGS_MODULE: "AHC_app" + DJANGO_SETTINGS_MODULE: "ahc.settings" EMAIL_BACKEND: "django.core.mail.backends.smtp.EmailBackend" EMAIL_HOST: "sandbox.smtp.mailtrap.io" diff --git a/kubernetes/db/postgres/deployment.yaml b/kubernetes/db/postgres/deployment.yaml index 886dd56..19dc611 100644 --- a/kubernetes/db/postgres/deployment.yaml +++ b/kubernetes/db/postgres/deployment.yaml @@ -17,7 +17,7 @@ spec: spec: containers: - name: postgres-db - image: postgres:16 + image: postgres:18-alpine imagePullPolicy: IfNotPresent ports: - containerPort: 5433 diff --git a/kubernetes/queue/celery-beat/deployment.yaml b/kubernetes/queue/celery-beat/deployment.yaml new file mode 100644 index 0000000..5952f2e --- /dev/null +++ b/kubernetes/queue/celery-beat/deployment.yaml @@ -0,0 +1,42 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: celery-beat + labels: + app: celery-beat +spec: + replicas: 1 + selector: + matchLabels: + app: celery-beat + template: + metadata: + name: celery-beat + labels: + app: celery-beat + spec: + initContainers: + - name: init-myservice + image: busybox + command: [ 'sh', '-c', 'env' ] + envFrom: + - secretRef: + name: web-secrets + containers: + - name: celery-beat + image: ahc_app-queue:latest + imagePullPolicy: Never + command: [ "celery", "-A", "celery_notifications.config:celery_obj", "beat", "-l", "info" ] + env: + - name: PYTHONUNBUFFERED + value: "1" + - name: PYTHONPATH + value: "/app/src" + envFrom: + - secretRef: + name: web-secrets + resources: + limits: + memory: "128Mi" + cpu: "250m" + restartPolicy: Always diff --git a/kubernetes/queue/celery-beat/kustomization.yaml b/kubernetes/queue/celery-beat/kustomization.yaml new file mode 100644 index 0000000..9519a26 --- /dev/null +++ b/kubernetes/queue/celery-beat/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - deployment.yaml diff --git a/kubernetes/queue/celery/configmap.yaml b/kubernetes/queue/celery/configmap.yaml index f5c5e73..4b28051 100644 --- a/kubernetes/queue/celery/configmap.yaml +++ b/kubernetes/queue/celery/configmap.yaml @@ -3,4 +3,4 @@ #metadata: # name: celery-config #data: -# DJANGO_SETTINGS_MODULE: AHC_app.settings +# DJANGO_SETTINGS_MODULE: ahc.settings diff --git a/kubernetes/queue/celery/deployment.yaml b/kubernetes/queue/celery/deployment.yaml index ccfc7d9..e89a7cc 100644 --- a/kubernetes/queue/celery/deployment.yaml +++ b/kubernetes/queue/celery/deployment.yaml @@ -26,12 +26,12 @@ spec: - name: queue image: ahc_app-queue:latest imagePullPolicy: Never - command: [ "celery", "-A", "AHC_app.celery_notifications.config:celery_obj", "worker", "-l", "info"] + command: [ "celery", "-A", "celery_notifications.config:celery_obj", "worker", "-l", "info"] env: - name: PYTHONUNBUFFERED value: "1" - name: PYTHONPATH - value: "/app" + value: "/app/src" envFrom: - secretRef: name: web-secrets diff --git a/kubernetes/queue/celery/secret.yaml.template b/kubernetes/queue/celery/secret.yaml.template index 3757913..6e95f60 100644 --- a/kubernetes/queue/celery/secret.yaml.template +++ b/kubernetes/queue/celery/secret.yaml.template @@ -22,7 +22,7 @@ stringData: COUCH_CONNECTOR: "Server(\"http://127.0.0.1:5982\")" CELERY_BACKEND: "redis://redis:6379/0" - DJANGO_SETTINGS_MODULE: "AHC_app" + DJANGO_SETTINGS_MODULE: "ahc.settings" EMAIL_BACKEND: "django.core.mail.backends.smtp.EmailBackend" EMAIL_HOST: "sandbox.smtp.mailtrap.io" diff --git a/kubernetes/queue/kustomization.yaml b/kubernetes/queue/kustomization.yaml index 1503853..d578b4a 100644 --- a/kubernetes/queue/kustomization.yaml +++ b/kubernetes/queue/kustomization.yaml @@ -1,5 +1,6 @@ resources: - secret.yaml - celery/ + - celery-beat/ - flower/ - redis/ diff --git a/AHC_app/manage.py b/manage.py similarity index 78% rename from AHC_app/manage.py rename to manage.py index db3b9dc..fe42511 100644 --- a/AHC_app/manage.py +++ b/manage.py @@ -1,12 +1,15 @@ #!/usr/bin/env python """Django's command-line utility for administrative tasks.""" + import os import sys +from pathlib import Path def main(): """Run administrative tasks.""" - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "AHC_app.settings") + sys.path.insert(0, str(Path(__file__).resolve().parent / "src")) + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ahc.settings") try: from django.core.management import execute_from_command_line except ImportError as exc: diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..f2bdd19 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,89 @@ +[project] +name = "animals-healthcare-application" +version = "0.1.0" +description = "Animals Healthcare Application — pet health data management" +requires-python = ">=3.14" + +dependencies = [ + "django>=6.0,<6.1", + "djangorestframework>=3.14", + "psycopg[binary]>=3.2", + "celery>=5.4", + "redis>=5.0", + "flower", + "pycouchdb", + "discord", + "python-decouple", + "pillow>=11.0", + "cryptography>=43", + "cffi>=1.17", + "django-crispy-forms", + "crispy-bootstrap4", + "django-bootstrap-modal-forms", + "django-compressor", + "django-libsass", + "libsass", + "django-appconf", + "django-taggit", + "django-timezone-field>=6.1", + "tzdata", + "python3-openid", + "requests", + "requests-oauthlib", + "httplib2", + "python-dateutil", + "pyjwt", + "defusedxml", + "icecream", +] + +[dependency-groups] +dev = [ + "pre-commit", + "ruff", + "ty", + "codespell", + "bandit[toml]", + "pytest", + "pytest-django", + "pytest-cov", +] + +[tool.uv] +package = false + +[tool.ruff] +line-length = 124 + +[tool.ruff.lint] +select = ["E", "F", "UP", "B", "SIM", "I", "RUF", "DJ"] +ignore = [ + "DJ001", + "DJ008", + "RUF012", +] + +[tool.ruff.format] +quote-style = "double" +indent-style = "space" + +[tool.pytest.ini_options] +DJANGO_SETTINGS_MODULE = "ahc.settings" +pythonpath = ["src"] +python_files = ["test_*.py", "tests.py"] +addopts = "--strict-markers" +markers = [ + "unit: fast isolated tests with no DB access", + "integration: tests that use the DB or external services", + "slow: tests that take more than a few seconds", +] + +[tool.ty.environment] +python-version = "3.14" + +[tool.codespell] +skip = "uv.lock,./static,./static_collected" + +[tool.bandit] +exclude_dirs = [".venv"] +skips = ["B101", "B404", "B603", "B607"] diff --git a/AHC_app/AHC_app/__init__.py b/src/__init__.py similarity index 100% rename from AHC_app/AHC_app/__init__.py rename to src/__init__.py diff --git a/AHC_app/AHC_app/celery_notifications/__init__.py b/src/ahc/__init__.py similarity index 100% rename from AHC_app/AHC_app/celery_notifications/__init__.py rename to src/ahc/__init__.py diff --git a/AHC_app/AHC_app/celery_notifications/utils/__init__.py b/src/ahc/apps/__init__.py similarity index 100% rename from AHC_app/AHC_app/celery_notifications/utils/__init__.py rename to src/ahc/apps/__init__.py diff --git a/AHC_app/__init__.py b/src/ahc/apps/animals/__init__.py similarity index 100% rename from AHC_app/__init__.py rename to src/ahc/apps/animals/__init__.py diff --git a/AHC_app/animals/admin.py b/src/ahc/apps/animals/admin.py similarity index 100% rename from AHC_app/animals/admin.py rename to src/ahc/apps/animals/admin.py diff --git a/AHC_app/animals/apps.py b/src/ahc/apps/animals/apps.py similarity index 84% rename from AHC_app/animals/apps.py rename to src/ahc/apps/animals/apps.py index 47778cd..1023188 100644 --- a/AHC_app/animals/apps.py +++ b/src/ahc/apps/animals/apps.py @@ -3,7 +3,7 @@ class AnimalsConfig(AppConfig): default_auto_field = "django.db.models.BigAutoField" - name = "animals" + name = "ahc.apps.animals" def ready(self): pass diff --git a/AHC_app/animals/forms.py b/src/ahc/apps/animals/forms.py similarity index 96% rename from AHC_app/animals/forms.py rename to src/ahc/apps/animals/forms.py index fa3d045..ee9e217 100644 --- a/AHC_app/animals/forms.py +++ b/src/ahc/apps/animals/forms.py @@ -1,8 +1,9 @@ -from animals.models import Animal from django import forms from django.core.validators import MaxLengthValidator, MinLengthValidator from django.db.models import Q +from ahc.apps.animals.models import Animal + class AnimalRegisterForm(forms.ModelForm): class Meta: diff --git a/AHC_app/animals/migrations/0001_initial.py b/src/ahc/apps/animals/migrations/0001_initial.py similarity index 78% rename from AHC_app/animals/migrations/0001_initial.py rename to src/ahc/apps/animals/migrations/0001_initial.py index 898346b..64da9bb 100644 --- a/AHC_app/animals/migrations/0001_initial.py +++ b/src/ahc/apps/animals/migrations/0001_initial.py @@ -29,15 +29,11 @@ class Migration(migrations.Migration): ("full_name", models.CharField(max_length=50)), ( "short_description", - models.CharField( - blank=True, default=None, max_length=250, null=True - ), + models.CharField(blank=True, default=None, max_length=250, null=True), ), ( "long_description", - models.CharField( - blank=True, default=None, max_length=2500, null=True - ), + models.CharField(blank=True, default=None, max_length=2500, null=True), ), ("birthdate", models.DateField(default=None, null=True)), ( @@ -50,15 +46,11 @@ class Migration(migrations.Migration): ("creation_date", models.DateTimeField(auto_now_add=True)), ( "first_contact_vet", - models.CharField( - blank=True, default=None, max_length=250, null=True - ), + models.CharField(blank=True, default=None, max_length=250, null=True), ), ( "first_contact_medical_place", - models.CharField( - blank=True, default=None, max_length=250, null=True - ), + models.CharField(blank=True, default=None, max_length=250, null=True), ), ("last_control_visit", models.DateTimeField(default=None, null=True)), ( diff --git a/AHC_app/animals/__init__.py b/src/ahc/apps/animals/migrations/__init__.py similarity index 100% rename from AHC_app/animals/__init__.py rename to src/ahc/apps/animals/migrations/__init__.py diff --git a/AHC_app/animals/migrations/__init__.py b/src/ahc/apps/animals/mixins/__init__.py similarity index 100% rename from AHC_app/animals/migrations/__init__.py rename to src/ahc/apps/animals/mixins/__init__.py diff --git a/AHC_app/animals/mixins/animal_owner_permissions.py b/src/ahc/apps/animals/mixins/animal_owner_permissions.py similarity index 86% rename from AHC_app/animals/mixins/animal_owner_permissions.py rename to src/ahc/apps/animals/mixins/animal_owner_permissions.py index 378f8c0..e62efdb 100644 --- a/AHC_app/animals/mixins/animal_owner_permissions.py +++ b/src/ahc/apps/animals/mixins/animal_owner_permissions.py @@ -1,6 +1,7 @@ -from animals.models import Animal from django.contrib.auth.mixins import UserPassesTestMixin +from ahc.apps.animals.models import Animal + class UserPassesOwnershipTestMixin(UserPassesTestMixin): def test_func(self): diff --git a/AHC_app/animals/models.py b/src/ahc/apps/animals/models.py similarity index 95% rename from AHC_app/animals/models.py rename to src/ahc/apps/animals/models.py index d64a8d1..962f461 100644 --- a/AHC_app/animals/models.py +++ b/src/ahc/apps/animals/models.py @@ -1,7 +1,8 @@ import uuid from django.db import models -from users.models import Profile as UserProfile + +from ahc.apps.users.models import Profile as UserProfile class Animal(models.Model): diff --git a/AHC_app/animals/signals.py b/src/ahc/apps/animals/signals.py similarity index 95% rename from AHC_app/animals/signals.py rename to src/ahc/apps/animals/signals.py index 05ebd4f..daddc0f 100644 --- a/AHC_app/animals/signals.py +++ b/src/ahc/apps/animals/signals.py @@ -1,9 +1,10 @@ import os -from animals.models import Animal from django.db.models.signals import post_delete, post_save, pre_delete from django.dispatch import receiver -from users.models import Profile + +from ahc.apps.animals.models import Animal +from ahc.apps.users.models import Profile @receiver(post_save, sender=Animal) diff --git a/AHC_app/animals/templates/animals/all_animals_stable.html b/src/ahc/apps/animals/templates/animals/all_animals_stable.html similarity index 75% rename from AHC_app/animals/templates/animals/all_animals_stable.html rename to src/ahc/apps/animals/templates/animals/all_animals_stable.html index b0a72e1..b246f58 100644 --- a/AHC_app/animals/templates/animals/all_animals_stable.html +++ b/src/ahc/apps/animals/templates/animals/all_animals_stable.html @@ -15,11 +15,7 @@

Placeholder title

All pets:

{% for animal in animals %} - {{ animal.full_name }} + {% partial "partials/animal_card.html#animal_card" %} {% endfor %}
{% endif %} @@ -33,4 +29,4 @@

Operations:

{% endif %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/AHC_app/animals/templates/animals/animal_confirm_delete.html b/src/ahc/apps/animals/templates/animals/animal_confirm_delete.html similarity index 95% rename from AHC_app/animals/templates/animals/animal_confirm_delete.html rename to src/ahc/apps/animals/templates/animals/animal_confirm_delete.html index c1d4e3c..2145247 100644 --- a/AHC_app/animals/templates/animals/animal_confirm_delete.html +++ b/src/ahc/apps/animals/templates/animals/animal_confirm_delete.html @@ -10,4 +10,4 @@

Delete Animal


Cancel -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/AHC_app/animals/templates/animals/change_birthday.html b/src/ahc/apps/animals/templates/animals/change_birthday.html similarity index 95% rename from AHC_app/animals/templates/animals/change_birthday.html rename to src/ahc/apps/animals/templates/animals/change_birthday.html index 67c180d..5109645 100644 --- a/AHC_app/animals/templates/animals/change_birthday.html +++ b/src/ahc/apps/animals/templates/animals/change_birthday.html @@ -9,4 +9,4 @@

Return to profile

-{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/AHC_app/animals/templates/animals/change_first_contact.html b/src/ahc/apps/animals/templates/animals/change_first_contact.html similarity index 97% rename from AHC_app/animals/templates/animals/change_first_contact.html rename to src/ahc/apps/animals/templates/animals/change_first_contact.html index 562871b..4ef1549 100644 --- a/AHC_app/animals/templates/animals/change_first_contact.html +++ b/src/ahc/apps/animals/templates/animals/change_first_contact.html @@ -19,4 +19,4 @@

Current first contact medical place:

Return to profile

-{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/AHC_app/animals/templates/animals/change_owner.html b/src/ahc/apps/animals/templates/animals/change_owner.html similarity index 100% rename from AHC_app/animals/templates/animals/change_owner.html rename to src/ahc/apps/animals/templates/animals/change_owner.html diff --git a/AHC_app/animals/templates/animals/create.html b/src/ahc/apps/animals/templates/animals/create.html similarity index 100% rename from AHC_app/animals/templates/animals/create.html rename to src/ahc/apps/animals/templates/animals/create.html diff --git a/AHC_app/animals/templates/animals/image.html b/src/ahc/apps/animals/templates/animals/image.html similarity index 95% rename from AHC_app/animals/templates/animals/image.html rename to src/ahc/apps/animals/templates/animals/image.html index 6382fa1..ef53601 100644 --- a/AHC_app/animals/templates/animals/image.html +++ b/src/ahc/apps/animals/templates/animals/image.html @@ -9,4 +9,4 @@

Return to profile

-{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/AHC_app/animals/templates/animals/manage_keepers.html b/src/ahc/apps/animals/templates/animals/manage_keepers.html similarity index 100% rename from AHC_app/animals/templates/animals/manage_keepers.html rename to src/ahc/apps/animals/templates/animals/manage_keepers.html diff --git a/AHC_app/animals/templates/animals/profile.html b/src/ahc/apps/animals/templates/animals/profile.html similarity index 100% rename from AHC_app/animals/templates/animals/profile.html rename to src/ahc/apps/animals/templates/animals/profile.html diff --git a/AHC_app/animals/mixins/__init__.py b/src/ahc/apps/animals/templatetags/__init__.py similarity index 100% rename from AHC_app/animals/mixins/__init__.py rename to src/ahc/apps/animals/templatetags/__init__.py diff --git a/AHC_app/animals/templatetags/custom_timesince.py b/src/ahc/apps/animals/templatetags/custom_timesince.py similarity index 56% rename from AHC_app/animals/templatetags/custom_timesince.py rename to src/ahc/apps/animals/templatetags/custom_timesince.py index a9465d5..46267dc 100644 --- a/AHC_app/animals/templatetags/custom_timesince.py +++ b/src/ahc/apps/animals/templatetags/custom_timesince.py @@ -16,19 +16,8 @@ def years_and_months_since(value, arg): years -= 1 months += 12 - if years == 1: - years_str = "1 year" - else: - years_str = f"{years} years" - - if months == 1: - months_str = "1 month" - else: - months_str = f"{months} months" - - if years > 0: - response = f"{years_str}, {months_str}" - else: - response = f"{months_str}" + years_str = "1 year" if years == 1 else f"{years} years" + months_str = "1 month" if months == 1 else f"{months} months" + response = f"{years_str}, {months_str}" if years > 0 else f"{months_str}" return response diff --git a/src/ahc/apps/animals/tests.py b/src/ahc/apps/animals/tests.py new file mode 100644 index 0000000..933a9c0 --- /dev/null +++ b/src/ahc/apps/animals/tests.py @@ -0,0 +1,57 @@ +import pytest + +from ahc.apps.animals.models import Animal +from ahc.apps.animals.signals import update_allowed_users + + +@pytest.fixture +def animal(db, user_profile): + _, profile = user_profile + return Animal.objects.create(full_name="Whiskers", owner=profile) + + +@pytest.mark.integration +@pytest.mark.django_db +class TestAnimalModel: + def test_animal_is_created_with_uuid_pk(self, animal): + assert animal.id is not None + assert animal.full_name == "Whiskers" + + def test_owner_is_assigned(self, animal, user_profile): + _, profile = user_profile + assert animal.owner == profile + + def test_no_keepers_by_default(self, animal): + assert animal.allowed_users.count() == 0 + + def test_second_user_can_be_added_as_keeper(self, animal, second_user_profile): + _, other_profile = second_user_profile + animal.allowed_users.add(other_profile) + assert animal.allowed_users.filter(pk=other_profile.pk).exists() + + +@pytest.mark.integration +@pytest.mark.django_db +class TestUpdateAllowedUsersSignalHandler: + """update_allowed_users: owner must not appear in allowed_users.""" + + def test_owner_removed_when_present_in_allowed_users(self, animal, user_profile): + _, profile = user_profile + animal.allowed_users.add(profile) + assert animal.allowed_users.filter(pk=profile.pk).exists() + + update_allowed_users(sender=Animal, instance=animal) + + assert not animal.allowed_users.filter(pk=profile.pk).exists() + + def test_non_owner_keeper_not_affected(self, animal, second_user_profile): + _, other_profile = second_user_profile + animal.allowed_users.add(other_profile) + + update_allowed_users(sender=Animal, instance=animal) + + assert animal.allowed_users.filter(pk=other_profile.pk).exists() + + def test_no_op_when_allowed_users_is_empty(self, animal): + update_allowed_users(sender=Animal, instance=animal) + assert animal.allowed_users.count() == 0 diff --git a/AHC_app/animals/urls.py b/src/ahc/apps/animals/urls.py similarity index 78% rename from AHC_app/animals/urls.py rename to src/ahc/apps/animals/urls.py index f741254..f636055 100644 --- a/AHC_app/animals/urls.py +++ b/src/ahc/apps/animals/urls.py @@ -1,14 +1,13 @@ -from animals import views as animal_views -from animals.utils_owner import views as animal_owner_views from django.urls import path +from ahc.apps.animals import views as animal_views +from ahc.apps.animals.utils_owner import views as animal_owner_views + urlpatterns = [ path("create/", animal_views.CreateAnimalView.as_view(), name="animal_create"), path("/delete/", animal_owner_views.AnimalDeleteView.as_view(), name="animal_delete"), path("/owner/", animal_owner_views.ChangeOwnerView.as_view(), name="animal_ownership"), - path( - "/cnt/", animal_owner_views.ChangeFirstContactView.as_view(), name="animal_first_contact" - ), # TO change + path("/cnt/", animal_owner_views.ChangeFirstContactView.as_view(), name="animal_first_contact"), # TO change path("/btd/", animal_owner_views.ChangeBirthdayView.as_view(), name="animal_birthday"), path("/", animal_views.AnimalProfileDetailView.as_view(), name="animal_profile"), path("/upload-image/", animal_owner_views.ImageUploadView.as_view(), name="upload_image"), diff --git a/AHC_app/animals/templatetags/__init__.py b/src/ahc/apps/animals/utils_owner/__init__.py similarity index 100% rename from AHC_app/animals/templatetags/__init__.py rename to src/ahc/apps/animals/utils_owner/__init__.py diff --git a/AHC_app/animals/utils_owner/forms.py b/src/ahc/apps/animals/utils_owner/forms.py similarity index 93% rename from AHC_app/animals/utils_owner/forms.py rename to src/ahc/apps/animals/utils_owner/forms.py index 868e015..fb7cf7f 100644 --- a/AHC_app/animals/utils_owner/forms.py +++ b/src/ahc/apps/animals/utils_owner/forms.py @@ -1,9 +1,10 @@ from datetime import date -from animals.models import Animal from django import forms from PIL import Image -from users.models import Profile + +from ahc.apps.animals.models import Animal +from ahc.apps.users.models import Profile class ImageUploadForm(forms.ModelForm): @@ -23,9 +24,8 @@ def clean_profile_image(self): if extension not in self.ALLOWED_EXTENSIONS: raise forms.ValidationError("Invalid file extension.") - if image: - if image.size > self.MAX_IMAGE_SIZE_MB * 1024 * 1024: - raise forms.ValidationError("Image size is too large.") + if image and image.size > self.MAX_IMAGE_SIZE_MB * 1024 * 1024: + raise forms.ValidationError("Image size is too large.") if image: img = Image.open(image) diff --git a/AHC_app/animals/utils_owner/views.py b/src/ahc/apps/animals/utils_owner/views.py similarity index 96% rename from AHC_app/animals/utils_owner/views.py rename to src/ahc/apps/animals/utils_owner/views.py index 963d817..fe72dad 100644 --- a/AHC_app/animals/utils_owner/views.py +++ b/src/ahc/apps/animals/utils_owner/views.py @@ -1,12 +1,3 @@ -from animals.mixins.animal_owner_permissions import UserPassesOwnershipTestMixin -from animals.models import Animal -from animals.utils_owner.forms import ( - ChangeBirthdayForm, - ChangeFirstContactForm, - ChangeOwnerForm, - ImageUploadForm, - ManageKeepersForm, -) from django.contrib.auth.mixins import LoginRequiredMixin from django.shortcuts import get_object_or_404, redirect from django.urls import reverse, reverse_lazy @@ -14,6 +5,16 @@ from django.views.generic.edit import FormView from PIL import Image +from ahc.apps.animals.mixins.animal_owner_permissions import UserPassesOwnershipTestMixin +from ahc.apps.animals.models import Animal +from ahc.apps.animals.utils_owner.forms import ( + ChangeBirthdayForm, + ChangeFirstContactForm, + ChangeOwnerForm, + ImageUploadForm, + ManageKeepersForm, +) + class AnimalDeleteView(LoginRequiredMixin, UserPassesOwnershipTestMixin, DeleteView): model = Animal diff --git a/AHC_app/animals/views.py b/src/ahc/apps/animals/views.py similarity index 94% rename from AHC_app/animals/views.py rename to src/ahc/apps/animals/views.py index 84f1c0b..f3eed53 100644 --- a/AHC_app/animals/views.py +++ b/src/ahc/apps/animals/views.py @@ -1,5 +1,3 @@ -from animals.forms import AnimalRegisterForm, PinAnimalForm -from animals.models import Animal from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin from django.db.models import Q from django.http import JsonResponse @@ -8,7 +6,10 @@ from django.views.generic import TemplateView, View from django.views.generic.detail import DetailView from django.views.generic.edit import FormView -from medical_notes.models.type_basic_note import MedicalRecord + +from ahc.apps.animals.forms import AnimalRegisterForm, PinAnimalForm +from ahc.apps.animals.models import Animal +from ahc.apps.medical_notes.models.type_basic_note import MedicalRecord # from users.models import Profile as UserProfile diff --git a/AHC_app/animals/utils_owner/__init__.py b/src/ahc/apps/homepage/__init__.py similarity index 100% rename from AHC_app/animals/utils_owner/__init__.py rename to src/ahc/apps/homepage/__init__.py diff --git a/src/ahc/apps/homepage/admin.py b/src/ahc/apps/homepage/admin.py new file mode 100644 index 0000000..73a2081 --- /dev/null +++ b/src/ahc/apps/homepage/admin.py @@ -0,0 +1,5 @@ +from django.contrib import admin + +from ahc.apps.homepage.models import AnimalTitle + +admin.site.register(AnimalTitle) diff --git a/AHC_app/homepage/apps.py b/src/ahc/apps/homepage/apps.py similarity index 80% rename from AHC_app/homepage/apps.py rename to src/ahc/apps/homepage/apps.py index a4c9949..ef7e748 100644 --- a/AHC_app/homepage/apps.py +++ b/src/ahc/apps/homepage/apps.py @@ -3,4 +3,4 @@ class HomepageConfig(AppConfig): default_auto_field = "django.db.models.BigAutoField" - name = "homepage" + name = "ahc.apps.homepage" diff --git a/AHC_app/homepage/__init__.py b/src/ahc/apps/homepage/management/__init__.py similarity index 100% rename from AHC_app/homepage/__init__.py rename to src/ahc/apps/homepage/management/__init__.py diff --git a/AHC_app/homepage/management/commands/__init__.py b/src/ahc/apps/homepage/management/commands/__init__.py similarity index 100% rename from AHC_app/homepage/management/commands/__init__.py rename to src/ahc/apps/homepage/management/commands/__init__.py diff --git a/AHC_app/homepage/migrations/0001_initial.py b/src/ahc/apps/homepage/migrations/0001_initial.py similarity index 95% rename from AHC_app/homepage/migrations/0001_initial.py rename to src/ahc/apps/homepage/migrations/0001_initial.py index e5a9f45..47a51d2 100644 --- a/AHC_app/homepage/migrations/0001_initial.py +++ b/src/ahc/apps/homepage/migrations/0001_initial.py @@ -1,10 +1,11 @@ # Generated by Django 4.2.1 on 2023-10-12 07:43 import django.db.models.deletion -import homepage.utils from django.conf import settings from django.db import migrations, models +import ahc.apps.homepage.utils + class Migration(migrations.Migration): initial = True @@ -46,7 +47,7 @@ class Migration(migrations.Migration): ( "content", models.ImageField( - default=homepage.utils.ImageGenerator.default_profile_image, + default=ahc.apps.homepage.utils.ImageGenerator.default_profile_image, upload_to="static/media/background", ), ), diff --git a/AHC_app/homepage/migrations/0002_alter_profilebackground_content.py b/src/ahc/apps/homepage/migrations/0002_alter_profilebackground_content.py similarity index 78% rename from AHC_app/homepage/migrations/0002_alter_profilebackground_content.py rename to src/ahc/apps/homepage/migrations/0002_alter_profilebackground_content.py index d75b47b..572cb3e 100644 --- a/AHC_app/homepage/migrations/0002_alter_profilebackground_content.py +++ b/src/ahc/apps/homepage/migrations/0002_alter_profilebackground_content.py @@ -1,8 +1,9 @@ # Generated by Django 4.2.1 on 2023-10-06 16:41 -import homepage.utils from django.db import migrations, models +import ahc.apps.homepage.utils + class Migration(migrations.Migration): dependencies = [ @@ -14,7 +15,7 @@ class Migration(migrations.Migration): model_name="profilebackground", name="content", field=models.ImageField( - default=homepage.utils.ImageGenerator.default_profile_image, + default=ahc.apps.homepage.utils.ImageGenerator.default_profile_image, upload_to="static/media/background", ), ), diff --git a/AHC_app/homepage/migrations/0003_cronjob.py b/src/ahc/apps/homepage/migrations/0003_cronjob.py similarity index 100% rename from AHC_app/homepage/migrations/0003_cronjob.py rename to src/ahc/apps/homepage/migrations/0003_cronjob.py diff --git a/src/ahc/apps/homepage/migrations/0004_delete_cronjob.py b/src/ahc/apps/homepage/migrations/0004_delete_cronjob.py new file mode 100644 index 0000000..200dd96 --- /dev/null +++ b/src/ahc/apps/homepage/migrations/0004_delete_cronjob.py @@ -0,0 +1,11 @@ +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("homepage", "0003_cronjob"), + ] + + operations = [ + migrations.DeleteModel(name="CronJob"), + ] diff --git a/AHC_app/homepage/migrations/__init__.py b/src/ahc/apps/homepage/migrations/__init__.py similarity index 100% rename from AHC_app/homepage/migrations/__init__.py rename to src/ahc/apps/homepage/migrations/__init__.py diff --git a/AHC_app/homepage/models.py b/src/ahc/apps/homepage/models.py similarity index 70% rename from AHC_app/homepage/models.py rename to src/ahc/apps/homepage/models.py index fab7fc2..213acd7 100644 --- a/AHC_app/homepage/models.py +++ b/src/ahc/apps/homepage/models.py @@ -1,14 +1,15 @@ from django.contrib.auth.models import User from django.db import models from django.urls import reverse -from homepage.utils import ImageGenerator + +from ahc.apps.homepage.utils import ImageGenerator class Privilege(models.Model): title = models.CharField(max_length=30) privilege_to_delete_animal = models.BooleanField(default=False) - # TODO: reconsider usage to simplyfy priveliges test mixins + # TODO: reconsider usage to simplify privileges test mixins def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) raise NotImplementedError @@ -41,15 +42,3 @@ def __str__(self): def get_absolute_url(self): return reverse("article-detail", kwargs={"pk": self.pk}) - - -# TODO: implement to allow set cronjobs from admin panel, must run shell command -class CronJob(models.Model): - name = models.CharField(max_length=255) - command = models.CharField(max_length=255) - schedule = models.CharField(max_length=255) - last_execution = models.DateTimeField(null=True, blank=True) - next_execution = models.DateTimeField(null=True, blank=True) - - def __str__(self): - return self.name diff --git a/AHC_app/homepage/templates/homepage/base.html b/src/ahc/apps/homepage/templates/homepage/base.html similarity index 100% rename from AHC_app/homepage/templates/homepage/base.html rename to src/ahc/apps/homepage/templates/homepage/base.html diff --git a/AHC_app/homepage/templates/homepage/change_list_results.html b/src/ahc/apps/homepage/templates/homepage/change_list_results.html similarity index 100% rename from AHC_app/homepage/templates/homepage/change_list_results.html rename to src/ahc/apps/homepage/templates/homepage/change_list_results.html diff --git a/AHC_app/homepage/templates/homepage/homepage.html b/src/ahc/apps/homepage/templates/homepage/homepage.html similarity index 67% rename from AHC_app/homepage/templates/homepage/homepage.html rename to src/ahc/apps/homepage/templates/homepage/homepage.html index 83df364..18db231 100644 --- a/AHC_app/homepage/templates/homepage/homepage.html +++ b/src/ahc/apps/homepage/templates/homepage/homepage.html @@ -28,11 +28,7 @@

Pinned up:

{% for animal in recent_animals %} - {{ animal.full_name }} + {% partial "partials/animal_card.html#animal_card" %} {% endfor %}

@@ -47,11 +43,7 @@

Recent added:

{% for animal in recent_animals %} - {{ animal.full_name }} + {% partial "partials/animal_card.html#animal_card" %} {% endfor %}

diff --git a/AHC_app/homepage/tests/__init__.py b/src/ahc/apps/homepage/tests/__init__.py similarity index 100% rename from AHC_app/homepage/tests/__init__.py rename to src/ahc/apps/homepage/tests/__init__.py diff --git a/AHC_app/homepage/tests/models/__init__.py b/src/ahc/apps/homepage/tests/models/__init__.py similarity index 100% rename from AHC_app/homepage/tests/models/__init__.py rename to src/ahc/apps/homepage/tests/models/__init__.py diff --git a/AHC_app/homepage/tests/models/test_animal_title.py b/src/ahc/apps/homepage/tests/models/test_animal_title.py similarity index 100% rename from AHC_app/homepage/tests/models/test_animal_title.py rename to src/ahc/apps/homepage/tests/models/test_animal_title.py diff --git a/src/ahc/apps/homepage/tests/test_csp.py b/src/ahc/apps/homepage/tests/test_csp.py new file mode 100644 index 0000000..c52486e --- /dev/null +++ b/src/ahc/apps/homepage/tests/test_csp.py @@ -0,0 +1,21 @@ +import pytest +from django.test import Client, TestCase + + +@pytest.mark.integration +@pytest.mark.django_db +class TestCSPHeaders(TestCase): + def test_report_only_header_present(self): + response = Client().get("/") + self.assertIn("Content-Security-Policy-Report-Only", response.headers) + + def test_report_only_default_src_self(self): + response = Client().get("/") + header = response.headers.get("Content-Security-Policy-Report-Only", "") + self.assertIn("default-src 'self'", header) + + def test_report_only_no_unsafe_scripts(self): + response = Client().get("/") + header = response.headers.get("Content-Security-Policy-Report-Only", "") + self.assertIn("script-src 'self'", header) + self.assertNotIn("'unsafe-inline'", header.split("script-src")[1].split(";")[0]) diff --git a/AHC_app/homepage/tests/test_homepage.py b/src/ahc/apps/homepage/tests/test_homepage.py similarity index 93% rename from AHC_app/homepage/tests/test_homepage.py rename to src/ahc/apps/homepage/tests/test_homepage.py index fe3ad54..97b9797 100644 --- a/AHC_app/homepage/tests/test_homepage.py +++ b/src/ahc/apps/homepage/tests/test_homepage.py @@ -1,8 +1,10 @@ from html.parser import HTMLParser +import pytest from django.contrib.auth.models import User from django.test import Client, TestCase -from homepage.models import AnimalTitle + +from ahc.apps.homepage.models import AnimalTitle client = Client() @@ -17,6 +19,8 @@ def handle_starttag(self, tag, attrs): self.found_href = True +@pytest.mark.integration +@pytest.mark.django_db class TestHomepage(TestCase): def setUp(self) -> None: my_user = User.objects.create(username="test_user_placeholder") diff --git a/AHC_app/homepage/urls.py b/src/ahc/apps/homepage/urls.py similarity index 67% rename from AHC_app/homepage/urls.py rename to src/ahc/apps/homepage/urls.py index 6f65fb3..1ce25d8 100644 --- a/AHC_app/homepage/urls.py +++ b/src/ahc/apps/homepage/urls.py @@ -1,5 +1,6 @@ from django.urls import path -from homepage.views import HomepageView + +from ahc.apps.homepage.views import HomepageView urlpatterns = [ path("", HomepageView.as_view(), name="Homepage"), diff --git a/AHC_app/homepage/utils.py b/src/ahc/apps/homepage/utils.py similarity index 100% rename from AHC_app/homepage/utils.py rename to src/ahc/apps/homepage/utils.py diff --git a/AHC_app/homepage/views.py b/src/ahc/apps/homepage/views.py similarity index 90% rename from AHC_app/homepage/views.py rename to src/ahc/apps/homepage/views.py index 1a51f30..e100c62 100644 --- a/AHC_app/homepage/views.py +++ b/src/ahc/apps/homepage/views.py @@ -1,7 +1,8 @@ -from animals.models import Animal from django.db.models import Q from django.views.generic import TemplateView -from users.models import Profile as UserProfile + +from ahc.apps.animals.models import Animal +from ahc.apps.users.models import Profile as UserProfile class HomepageView(TemplateView): @@ -23,7 +24,6 @@ def get_context_data(self, **kwargs): context["pinned_animals"] = pinned_animals_query if user_query.allow_recennt_animals_list: - recent_created_animals_query = Animal.objects.filter( Q(owner=self.request.user.profile) | Q(allowed_users=self.request.user.profile) ).order_by("-creation_date")[:3] diff --git a/AHC_app/medical_notes/__init__.py b/src/ahc/apps/medical_notes/__init__.py similarity index 100% rename from AHC_app/medical_notes/__init__.py rename to src/ahc/apps/medical_notes/__init__.py diff --git a/src/ahc/apps/medical_notes/admin.py b/src/ahc/apps/medical_notes/admin.py new file mode 100644 index 0000000..846f6b4 --- /dev/null +++ b/src/ahc/apps/medical_notes/admin.py @@ -0,0 +1 @@ +# Register your models here. diff --git a/AHC_app/medical_notes/apps.py b/src/ahc/apps/medical_notes/apps.py similarity index 82% rename from AHC_app/medical_notes/apps.py rename to src/ahc/apps/medical_notes/apps.py index 2fc8826..5d5a03a 100644 --- a/AHC_app/medical_notes/apps.py +++ b/src/ahc/apps/medical_notes/apps.py @@ -3,7 +3,7 @@ class MedicalNotesConfig(AppConfig): default_auto_field = "django.db.models.BigAutoField" - name = "medical_notes" + name = "ahc.apps.medical_notes" def ready(self): pass diff --git a/AHC_app/medical_notes/forms.py b/src/ahc/apps/medical_notes/forms.py similarity index 100% rename from AHC_app/medical_notes/forms.py rename to src/ahc/apps/medical_notes/forms.py diff --git a/AHC_app/medical_notes/forms/__init__.py b/src/ahc/apps/medical_notes/forms/__init__.py similarity index 100% rename from AHC_app/medical_notes/forms/__init__.py rename to src/ahc/apps/medical_notes/forms/__init__.py diff --git a/AHC_app/medical_notes/forms/type_basic_note.py b/src/ahc/apps/medical_notes/forms/type_basic_note.py similarity index 94% rename from AHC_app/medical_notes/forms/type_basic_note.py rename to src/ahc/apps/medical_notes/forms/type_basic_note.py index 8263457..766d818 100644 --- a/AHC_app/medical_notes/forms/type_basic_note.py +++ b/src/ahc/apps/medical_notes/forms/type_basic_note.py @@ -1,7 +1,7 @@ from django import forms # from animals.models import Animal as AnimalProfile -from medical_notes.models.type_basic_note import MedicalRecord, MedicalRecordAttachment +from ahc.apps.medical_notes.models.type_basic_note import MedicalRecord, MedicalRecordAttachment # from django.core.validators import MaxLengthValidator, MinLengthValidator # from django.db.models import Q @@ -47,7 +47,7 @@ class Meta: def __init__(self, *args, **kwargs): animal_choices = kwargs.pop("animal_choices", None) type_of_event_param = kwargs.pop("type_of_event_param", None) - super(MedicalRecordForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) # self.Meta.fields.append('TYPES_OF_EVENTS') if animal_choices: @@ -64,7 +64,7 @@ def __init__(self, *args, **kwargs): class MedicalRecordEditForm(MedicalRecordForm): def __init__(self, *args, **kwargs): animal = kwargs.pop("animal", None) - super(MedicalRecordEditForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.animal = animal tag_names = list(self.instance.note_tags.values_list("name", flat=True)) self.initial["note_tags"] = ", ".join(tag_names) @@ -91,7 +91,7 @@ def __init__(self, *args, **kwargs): kwargs.pop("animal") animal_choices = kwargs.pop("animal_choices", None) is_author = kwargs.pop("is_author", None) - super(MedicalRecordEditRelatedAnimalsForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if animal_choices: self.fields["animal"].widget.choices = animal_choices diff --git a/AHC_app/medical_notes/forms/type_feeding_notes.py b/src/ahc/apps/medical_notes/forms/type_feeding_notes.py similarity index 94% rename from AHC_app/medical_notes/forms/type_feeding_notes.py rename to src/ahc/apps/medical_notes/forms/type_feeding_notes.py index 3e4fb4e..31a8660 100644 --- a/AHC_app/medical_notes/forms/type_feeding_notes.py +++ b/src/ahc/apps/medical_notes/forms/type_feeding_notes.py @@ -1,8 +1,9 @@ from django import forms from django.conf import settings -from medical_notes.models.type_feeding_notes import EmailNotification, FeedingNote from timezone_field import TimeZoneFormField +from ahc.apps.medical_notes.models.type_feeding_notes import EmailNotification, FeedingNote + class DietRecordForm(forms.ModelForm): class Meta: @@ -77,6 +78,6 @@ class Meta: days_of_week = forms.MultipleChoiceField(choices=days_of_week_choices, widget=forms.CheckboxSelectMultiple) def __init__(self, *args, **kwargs): - super(NotificationRecordForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.fields["timezone"].initial = str(settings.TIME_ZONE) diff --git a/AHC_app/medical_notes/forms/type_measurement_notes.py b/src/ahc/apps/medical_notes/forms/type_measurement_notes.py similarity index 79% rename from AHC_app/medical_notes/forms/type_measurement_notes.py rename to src/ahc/apps/medical_notes/forms/type_measurement_notes.py index ae4fe25..3923682 100644 --- a/AHC_app/medical_notes/forms/type_measurement_notes.py +++ b/src/ahc/apps/medical_notes/forms/type_measurement_notes.py @@ -1,5 +1,7 @@ from django import forms +from ahc.apps.medical_notes.models.type_measurement_notes import BiometricHeightRecords, BiometricWeightRecords + class BiometricRecordForm(forms.Form): RECORD_CHOICES = [ @@ -21,14 +23,10 @@ class BiometricRecordForm(forms.Form): custom_unit = forms.CharField(max_length=12, required=False) def __init__(self, *args, **kwargs): - super(BiometricRecordForm, self).__init__(*args, **kwargs) - - default_height_unit_to_present = BiometricHeightRecords._meta.get_field( - "height_unit_to_present" - ).get_default() - default_weight_unit_to_present = BiometricWeightRecords._meta.get_field( - "weight_unit_to_present" - ).get_default() + super().__init__(*args, **kwargs) + + default_height_unit_to_present = BiometricHeightRecords._meta.get_field("height_unit_to_present").get_default() + default_weight_unit_to_present = BiometricWeightRecords._meta.get_field("weight_unit_to_present").get_default() self.fields["height_unit_to_present"].initial = default_height_unit_to_present self.fields["weight_unit_to_present"].initial = default_weight_unit_to_present diff --git a/AHC_app/medical_notes/migrations/0001_initial.py b/src/ahc/apps/medical_notes/migrations/0001_initial.py similarity index 94% rename from AHC_app/medical_notes/migrations/0001_initial.py rename to src/ahc/apps/medical_notes/migrations/0001_initial.py index 7f28f34..8eed680 100644 --- a/AHC_app/medical_notes/migrations/0001_initial.py +++ b/src/ahc/apps/medical_notes/migrations/0001_initial.py @@ -146,9 +146,7 @@ class Migration(migrations.Migration): ), ( "animal", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, to="animals.animal" - ), + models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to="animals.animal"), ), ( "author", @@ -199,9 +197,7 @@ class Migration(migrations.Migration): ), ( "animal", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, to="animals.animal" - ), + models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to="animals.animal"), ), ], ), @@ -225,9 +221,7 @@ class Migration(migrations.Migration): ("description", models.CharField(max_length=250)), ( "animal", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, to="animals.animal" - ), + models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to="animals.animal"), ), ], ), @@ -246,9 +240,7 @@ class Migration(migrations.Migration): ("date_updated", models.DateTimeField(auto_now_add=True)), ( "animal", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, to="animals.animal" - ), + models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to="animals.animal"), ), ( "custom_biometric_record", diff --git a/AHC_app/medical_notes/migrations/0002_remove_currentmedicine_animal_delete_currentdiet_and_more.py b/src/ahc/apps/medical_notes/migrations/0002_remove_currentmedicine_animal_delete_currentdiet_and_more.py similarity index 100% rename from AHC_app/medical_notes/migrations/0002_remove_currentmedicine_animal_delete_currentdiet_and_more.py rename to src/ahc/apps/medical_notes/migrations/0002_remove_currentmedicine_animal_delete_currentdiet_and_more.py diff --git a/AHC_app/medical_notes/migrations/0003_feedingnote_smsnotification_emailnotification_and_more.py b/src/ahc/apps/medical_notes/migrations/0003_feedingnote_smsnotification_emailnotification_and_more.py similarity index 100% rename from AHC_app/medical_notes/migrations/0003_feedingnote_smsnotification_emailnotification_and_more.py rename to src/ahc/apps/medical_notes/migrations/0003_feedingnote_smsnotification_emailnotification_and_more.py diff --git a/AHC_app/medical_notes/migrations/0004_alter_discordnotification_timezone_and_more.py b/src/ahc/apps/medical_notes/migrations/0004_alter_discordnotification_timezone_and_more.py similarity index 100% rename from AHC_app/medical_notes/migrations/0004_alter_discordnotification_timezone_and_more.py rename to src/ahc/apps/medical_notes/migrations/0004_alter_discordnotification_timezone_and_more.py diff --git a/AHC_app/medical_notes/migrations/0005_medicalrecordattachment.py b/src/ahc/apps/medical_notes/migrations/0005_medicalrecordattachment.py similarity index 99% rename from AHC_app/medical_notes/migrations/0005_medicalrecordattachment.py rename to src/ahc/apps/medical_notes/migrations/0005_medicalrecordattachment.py index 921f03e..a93c2ec 100644 --- a/AHC_app/medical_notes/migrations/0005_medicalrecordattachment.py +++ b/src/ahc/apps/medical_notes/migrations/0005_medicalrecordattachment.py @@ -1,9 +1,10 @@ # Generated by Django 4.2.1 on 2023-12-28 16:40 -from django.db import migrations, models -import django.db.models.deletion import uuid +import django.db.models.deletion +from django.db import migrations, models + class Migration(migrations.Migration): dependencies = [ diff --git a/AHC_app/medical_notes/migrations/0006_remove_medicalrecordattachment_description.py b/src/ahc/apps/medical_notes/migrations/0006_remove_medicalrecordattachment_description.py similarity index 100% rename from AHC_app/medical_notes/migrations/0006_remove_medicalrecordattachment_description.py rename to src/ahc/apps/medical_notes/migrations/0006_remove_medicalrecordattachment_description.py diff --git a/AHC_app/medical_notes/migrations/0007_medicalrecordattachment_url.py b/src/ahc/apps/medical_notes/migrations/0007_medicalrecordattachment_url.py similarity index 100% rename from AHC_app/medical_notes/migrations/0007_medicalrecordattachment_url.py rename to src/ahc/apps/medical_notes/migrations/0007_medicalrecordattachment_url.py diff --git a/AHC_app/medical_notes/migrations/0008_alter_medicalrecordattachment_file.py b/src/ahc/apps/medical_notes/migrations/0008_alter_medicalrecordattachment_file.py similarity index 100% rename from AHC_app/medical_notes/migrations/0008_alter_medicalrecordattachment_file.py rename to src/ahc/apps/medical_notes/migrations/0008_alter_medicalrecordattachment_file.py diff --git a/AHC_app/medical_notes/migrations/0009_discordnotification_last_modification_and_more.py b/src/ahc/apps/medical_notes/migrations/0009_discordnotification_last_modification_and_more.py similarity index 83% rename from AHC_app/medical_notes/migrations/0009_discordnotification_last_modification_and_more.py rename to src/ahc/apps/medical_notes/migrations/0009_discordnotification_last_modification_and_more.py index 4e9e757..237bd01 100644 --- a/AHC_app/medical_notes/migrations/0009_discordnotification_last_modification_and_more.py +++ b/src/ahc/apps/medical_notes/migrations/0009_discordnotification_last_modification_and_more.py @@ -6,7 +6,6 @@ class Migration(migrations.Migration): - dependencies = [ ("medical_notes", "0008_alter_medicalrecordattachment_file"), ] @@ -15,16 +14,16 @@ class Migration(migrations.Migration): migrations.AddField( model_name="discordnotification", name="last_modification", - field=models.DateTimeField(default=datetime.datetime(2024, 2, 2, 13, 46, 49, 356514)), + field=models.DateTimeField(default=datetime.datetime(2024, 2, 2, 13, 46, 49, 356514, tzinfo=datetime.UTC)), ), migrations.AddField( model_name="emailnotification", name="last_modification", - field=models.DateTimeField(default=datetime.datetime(2024, 2, 2, 13, 46, 49, 356514)), + field=models.DateTimeField(default=datetime.datetime(2024, 2, 2, 13, 46, 49, 356514, tzinfo=datetime.UTC)), ), migrations.AddField( model_name="smsnotification", name="last_modification", - field=models.DateTimeField(default=datetime.datetime(2024, 2, 2, 13, 46, 49, 356514)), + field=models.DateTimeField(default=datetime.datetime(2024, 2, 2, 13, 46, 49, 356514, tzinfo=datetime.UTC)), ), ] diff --git a/AHC_app/medical_notes/migrations/0010_alter_discordnotification_last_modification_and_more.py b/src/ahc/apps/medical_notes/migrations/0010_alter_discordnotification_last_modification_and_more.py similarity index 99% rename from AHC_app/medical_notes/migrations/0010_alter_discordnotification_last_modification_and_more.py rename to src/ahc/apps/medical_notes/migrations/0010_alter_discordnotification_last_modification_and_more.py index c0dc312..70e6d6d 100644 --- a/AHC_app/medical_notes/migrations/0010_alter_discordnotification_last_modification_and_more.py +++ b/src/ahc/apps/medical_notes/migrations/0010_alter_discordnotification_last_modification_and_more.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ("medical_notes", "0009_discordnotification_last_modification_and_more"), ] diff --git a/AHC_app/medical_notes/migrations/0011_medicalrecordattachment_description.py b/src/ahc/apps/medical_notes/migrations/0011_medicalrecordattachment_description.py similarity index 99% rename from AHC_app/medical_notes/migrations/0011_medicalrecordattachment_description.py rename to src/ahc/apps/medical_notes/migrations/0011_medicalrecordattachment_description.py index 7690074..2e74989 100644 --- a/AHC_app/medical_notes/migrations/0011_medicalrecordattachment_description.py +++ b/src/ahc/apps/medical_notes/migrations/0011_medicalrecordattachment_description.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ("medical_notes", "0010_alter_discordnotification_last_modification_and_more"), ] diff --git a/AHC_app/medical_notes/migrations/0012_medicalrecordattachment_file_name_and_more.py b/src/ahc/apps/medical_notes/migrations/0012_medicalrecordattachment_file_name_and_more.py similarity index 99% rename from AHC_app/medical_notes/migrations/0012_medicalrecordattachment_file_name_and_more.py rename to src/ahc/apps/medical_notes/migrations/0012_medicalrecordattachment_file_name_and_more.py index 0639d1d..075e3aa 100644 --- a/AHC_app/medical_notes/migrations/0012_medicalrecordattachment_file_name_and_more.py +++ b/src/ahc/apps/medical_notes/migrations/0012_medicalrecordattachment_file_name_and_more.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ("medical_notes", "0011_medicalrecordattachment_description"), ] diff --git a/AHC_app/medical_notes/migrations/0013_remove_medicalrecordattachment_url_and_more.py b/src/ahc/apps/medical_notes/migrations/0013_remove_medicalrecordattachment_url_and_more.py similarity index 99% rename from AHC_app/medical_notes/migrations/0013_remove_medicalrecordattachment_url_and_more.py rename to src/ahc/apps/medical_notes/migrations/0013_remove_medicalrecordattachment_url_and_more.py index 57ce211..b87311c 100644 --- a/AHC_app/medical_notes/migrations/0013_remove_medicalrecordattachment_url_and_more.py +++ b/src/ahc/apps/medical_notes/migrations/0013_remove_medicalrecordattachment_url_and_more.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ("medical_notes", "0012_medicalrecordattachment_file_name_and_more"), ] diff --git a/AHC_app/medical_notes/migrations/0014_alter_discordnotification_last_modification_and_more.py b/src/ahc/apps/medical_notes/migrations/0014_alter_discordnotification_last_modification_and_more.py similarity index 99% rename from AHC_app/medical_notes/migrations/0014_alter_discordnotification_last_modification_and_more.py rename to src/ahc/apps/medical_notes/migrations/0014_alter_discordnotification_last_modification_and_more.py index 4e0b8bb..9d99dea 100644 --- a/AHC_app/medical_notes/migrations/0014_alter_discordnotification_last_modification_and_more.py +++ b/src/ahc/apps/medical_notes/migrations/0014_alter_discordnotification_last_modification_and_more.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ("medical_notes", "0013_remove_medicalrecordattachment_url_and_more"), ] diff --git a/AHC_app/medical_notes/migrations/__init__.py b/src/ahc/apps/medical_notes/migrations/__init__.py similarity index 100% rename from AHC_app/medical_notes/migrations/__init__.py rename to src/ahc/apps/medical_notes/migrations/__init__.py diff --git a/AHC_app/medical_notes/models.py b/src/ahc/apps/medical_notes/models.py similarity index 100% rename from AHC_app/medical_notes/models.py rename to src/ahc/apps/medical_notes/models.py diff --git a/AHC_app/medical_notes/models/__init__.py b/src/ahc/apps/medical_notes/models/__init__.py similarity index 100% rename from AHC_app/medical_notes/models/__init__.py rename to src/ahc/apps/medical_notes/models/__init__.py diff --git a/AHC_app/medical_notes/models/type_basic_note.py b/src/ahc/apps/medical_notes/models/type_basic_note.py similarity index 95% rename from AHC_app/medical_notes/models/type_basic_note.py rename to src/ahc/apps/medical_notes/models/type_basic_note.py index b5ce3d4..757be9e 100644 --- a/AHC_app/medical_notes/models/type_basic_note.py +++ b/src/ahc/apps/medical_notes/models/type_basic_note.py @@ -1,10 +1,11 @@ import uuid -from animals.models import Animal from django.db import models from taggit.managers import TaggableManager from taggit.models import GenericUUIDTaggedItemBase, TaggedItemBase -from users.models import Profile as UserProfile + +from ahc.apps.animals.models import Animal +from ahc.apps.users.models import Profile as UserProfile class UUIDTaggedItem(GenericUUIDTaggedItemBase, TaggedItemBase): diff --git a/AHC_app/medical_notes/models/type_feeding_notes.py b/src/ahc/apps/medical_notes/models/type_feeding_notes.py similarity index 97% rename from AHC_app/medical_notes/models/type_feeding_notes.py rename to src/ahc/apps/medical_notes/models/type_feeding_notes.py index e48c449..67a31c0 100644 --- a/AHC_app/medical_notes/models/type_feeding_notes.py +++ b/src/ahc/apps/medical_notes/models/type_feeding_notes.py @@ -3,9 +3,10 @@ from django.contrib.postgres.fields import ArrayField from django.db import models -from medical_notes.models.type_basic_note import MedicalRecord from timezone_field import TimeZoneField +from ahc.apps.medical_notes.models.type_basic_note import MedicalRecord + class FeedingNote(models.Model): related_note = models.ForeignKey(MedicalRecord, on_delete=models.CASCADE, null=False, blank=False) diff --git a/AHC_app/medical_notes/models/type_measurement_notes.py b/src/ahc/apps/medical_notes/models/type_measurement_notes.py similarity index 63% rename from AHC_app/medical_notes/models/type_measurement_notes.py rename to src/ahc/apps/medical_notes/models/type_measurement_notes.py index 1c36dda..d2a0925 100644 --- a/AHC_app/medical_notes/models/type_measurement_notes.py +++ b/src/ahc/apps/medical_notes/models/type_measurement_notes.py @@ -1,6 +1,7 @@ -from animals.models import Animal from django.db import models -from medical_notes.models.type_basic_note import MedicalRecord + +from ahc.apps.animals.models import Animal +from ahc.apps.medical_notes.models.type_basic_note import MedicalRecord class BiometricHeightRecords(models.Model): @@ -23,17 +24,9 @@ class BiometricCustomRecords(models.Model): class BiometricRecord(models.Model): animal = models.ForeignKey(Animal, on_delete=models.CASCADE) - related_note = models.ForeignKey( - MedicalRecord, on_delete=models.SET_NULL, blank=True, null=True - ) + related_note = models.ForeignKey(MedicalRecord, on_delete=models.SET_NULL, blank=True, null=True) date_updated = models.DateTimeField(auto_now_add=True, editable=True) - weight_biometric_record = models.OneToOneField( - BiometricWeightRecords, on_delete=models.CASCADE, blank=True, null=True - ) - height_biometric_record = models.OneToOneField( - BiometricHeightRecords, on_delete=models.CASCADE, blank=True, null=True - ) - custom_biometric_record = models.OneToOneField( - BiometricCustomRecords, on_delete=models.CASCADE, blank=True, null=True - ) + weight_biometric_record = models.OneToOneField(BiometricWeightRecords, on_delete=models.CASCADE, blank=True, null=True) + height_biometric_record = models.OneToOneField(BiometricHeightRecords, on_delete=models.CASCADE, blank=True, null=True) + custom_biometric_record = models.OneToOneField(BiometricCustomRecords, on_delete=models.CASCADE, blank=True, null=True) diff --git a/AHC_app/medical_notes/signals.py b/src/ahc/apps/medical_notes/signals.py similarity index 100% rename from AHC_app/medical_notes/signals.py rename to src/ahc/apps/medical_notes/signals.py diff --git a/AHC_app/medical_notes/signals/__init__.py b/src/ahc/apps/medical_notes/signals/__init__.py similarity index 100% rename from AHC_app/medical_notes/signals/__init__.py rename to src/ahc/apps/medical_notes/signals/__init__.py diff --git a/AHC_app/medical_notes/signals/type_feeding_notes.py b/src/ahc/apps/medical_notes/signals/type_feeding_notes.py similarity index 77% rename from AHC_app/medical_notes/signals/type_feeding_notes.py rename to src/ahc/apps/medical_notes/signals/type_feeding_notes.py index ce07d43..28dc8d5 100644 --- a/AHC_app/medical_notes/signals/type_feeding_notes.py +++ b/src/ahc/apps/medical_notes/signals/type_feeding_notes.py @@ -1,8 +1,9 @@ from django.db import transaction from django.db.models.signals import post_save from django.dispatch import receiver -from medical_notes.models.type_feeding_notes import FeedingNote -from users.models import Profile as UserProfile + +from ahc.apps.medical_notes.models.type_feeding_notes import FeedingNote +from ahc.apps.users.models import Profile as UserProfile @receiver(post_save, sender=FeedingNote) diff --git a/AHC_app/medical_notes/signals/type_measurement_notes.py b/src/ahc/apps/medical_notes/signals/type_measurement_notes.py similarity index 64% rename from AHC_app/medical_notes/signals/type_measurement_notes.py rename to src/ahc/apps/medical_notes/signals/type_measurement_notes.py index 6e7cb9e..d3cddd6 100644 --- a/AHC_app/medical_notes/signals/type_measurement_notes.py +++ b/src/ahc/apps/medical_notes/signals/type_measurement_notes.py @@ -2,27 +2,24 @@ from django.db.models import Q from django.db.models.signals import post_save, pre_save from django.dispatch import receiver -from medical_notes.models.type_basic_note import MedicalRecord -from medical_notes.models.type_measurement_notes import BiometricRecord -from users.models import Profile as UserProfile + +from ahc.apps.medical_notes.models.type_basic_note import MedicalRecord +from ahc.apps.medical_notes.models.type_measurement_notes import BiometricRecord +from ahc.apps.users.models import Profile as UserProfile @receiver(pre_save, sender=BiometricRecord) def validate_one_to_one_fields(sender, instance, **kwargs): - if ( - len( - { - instance - for instance in ( - instance.weight_biometric_record, - instance.height_biometric_record, - instance.custom_biometric_record, - ) - if instance is not None - } + assigned = sum( + 1 + for field in ( + instance.weight_biometric_record, + instance.height_biometric_record, + instance.custom_biometric_record, ) - > 1 - ): + if field is not None + ) + if assigned > 1: raise ValidationError("BiometricRecord can only have one of OneToOneFields assigned.") diff --git a/AHC_app/medical_notes/templates/medical_notes/create.html b/src/ahc/apps/medical_notes/templates/medical_notes/create.html similarity index 100% rename from AHC_app/medical_notes/templates/medical_notes/create.html rename to src/ahc/apps/medical_notes/templates/medical_notes/create.html diff --git a/AHC_app/medical_notes/templates/medical_notes/create_notify.html b/src/ahc/apps/medical_notes/templates/medical_notes/create_notify.html similarity index 100% rename from AHC_app/medical_notes/templates/medical_notes/create_notify.html rename to src/ahc/apps/medical_notes/templates/medical_notes/create_notify.html diff --git a/AHC_app/medical_notes/templates/medical_notes/delete_confirm.html b/src/ahc/apps/medical_notes/templates/medical_notes/delete_confirm.html similarity index 100% rename from AHC_app/medical_notes/templates/medical_notes/delete_confirm.html rename to src/ahc/apps/medical_notes/templates/medical_notes/delete_confirm.html diff --git a/AHC_app/medical_notes/templates/medical_notes/edit.html b/src/ahc/apps/medical_notes/templates/medical_notes/edit.html similarity index 100% rename from AHC_app/medical_notes/templates/medical_notes/edit.html rename to src/ahc/apps/medical_notes/templates/medical_notes/edit.html diff --git a/AHC_app/medical_notes/templates/medical_notes/feeding_notes_list.html b/src/ahc/apps/medical_notes/templates/medical_notes/feeding_notes_list.html similarity index 100% rename from AHC_app/medical_notes/templates/medical_notes/feeding_notes_list.html rename to src/ahc/apps/medical_notes/templates/medical_notes/feeding_notes_list.html diff --git a/AHC_app/medical_notes/templates/medical_notes/full_timeline_of_notes.html b/src/ahc/apps/medical_notes/templates/medical_notes/full_timeline_of_notes.html similarity index 100% rename from AHC_app/medical_notes/templates/medical_notes/full_timeline_of_notes.html rename to src/ahc/apps/medical_notes/templates/medical_notes/full_timeline_of_notes.html diff --git a/AHC_app/medical_notes/templates/medical_notes/notification_list.html b/src/ahc/apps/medical_notes/templates/medical_notes/notification_list.html similarity index 100% rename from AHC_app/medical_notes/templates/medical_notes/notification_list.html rename to src/ahc/apps/medical_notes/templates/medical_notes/notification_list.html diff --git a/AHC_app/medical_notes/templatetags/__init__.py b/src/ahc/apps/medical_notes/templatetags/__init__.py similarity index 100% rename from AHC_app/medical_notes/templatetags/__init__.py rename to src/ahc/apps/medical_notes/templatetags/__init__.py diff --git a/AHC_app/medical_notes/templatetags/custom_file_name.py b/src/ahc/apps/medical_notes/templatetags/custom_file_name.py similarity index 64% rename from AHC_app/medical_notes/templatetags/custom_file_name.py rename to src/ahc/apps/medical_notes/templatetags/custom_file_name.py index 82d6968..79421c0 100644 --- a/AHC_app/medical_notes/templatetags/custom_file_name.py +++ b/src/ahc/apps/medical_notes/templatetags/custom_file_name.py @@ -1,5 +1,6 @@ from django import template -from medical_notes.models.type_feeding_notes import FeedingNotification + +from ahc.apps.medical_notes.models.type_feeding_notes import FeedingNotification register = template.Library() @@ -10,6 +11,6 @@ def to_class_name(value): raise template.TemplateSyntaxError("Value cannot be None") if FeedingNotification not in value.__class__.__bases__: - raise template.TemplateSyntaxError(f"Not allowed to use on the model") + raise template.TemplateSyntaxError("Not allowed to use on the model") return value.__class__.__name__ diff --git a/AHC_app/medical_notes/templatetags/custom_to_class_name.py b/src/ahc/apps/medical_notes/templatetags/custom_to_class_name.py similarity index 100% rename from AHC_app/medical_notes/templatetags/custom_to_class_name.py rename to src/ahc/apps/medical_notes/templatetags/custom_to_class_name.py diff --git a/src/ahc/apps/medical_notes/tests.py b/src/ahc/apps/medical_notes/tests.py new file mode 100644 index 0000000..c18ca7e --- /dev/null +++ b/src/ahc/apps/medical_notes/tests.py @@ -0,0 +1,54 @@ +from unittest.mock import MagicMock + +import pytest +from django.core.exceptions import ValidationError + +from ahc.apps.medical_notes.models.type_measurement_notes import ( + BiometricHeightRecords, + BiometricWeightRecords, +) +from ahc.apps.medical_notes.signals.type_measurement_notes import validate_one_to_one_fields + + +def _make_instance(weight=None, height=None, custom=None): + instance = MagicMock() + instance.weight_biometric_record = weight + instance.height_biometric_record = height + instance.custom_biometric_record = custom + return instance + + +@pytest.mark.unit +class TestBiometricRecordValidation: + """validate_one_to_one_fields: at most one measurement type per BiometricRecord.""" + + def test_two_types_raises_validation_error(self): + instance = _make_instance( + weight=BiometricWeightRecords(weight=5), + height=BiometricHeightRecords(height=30), + ) + with pytest.raises(ValidationError): + validate_one_to_one_fields(sender=None, instance=instance) + + def test_all_three_types_raises_validation_error(self): + from ahc.apps.medical_notes.models.type_measurement_notes import BiometricCustomRecords + + instance = _make_instance( + weight=BiometricWeightRecords(weight=5), + height=BiometricHeightRecords(height=30), + custom=BiometricCustomRecords(record_name="x", record_value="1", record_unit="cm"), + ) + with pytest.raises(ValidationError): + validate_one_to_one_fields(sender=None, instance=instance) + + def test_weight_only_is_valid(self): + instance = _make_instance(weight=BiometricWeightRecords(weight=5)) + validate_one_to_one_fields(sender=None, instance=instance) + + def test_height_only_is_valid(self): + instance = _make_instance(height=BiometricHeightRecords(height=30)) + validate_one_to_one_fields(sender=None, instance=instance) + + def test_all_none_is_valid(self): + instance = _make_instance() + validate_one_to_one_fields(sender=None, instance=instance) diff --git a/AHC_app/medical_notes/urls.py b/src/ahc/apps/medical_notes/urls.py similarity index 85% rename from AHC_app/medical_notes/urls.py rename to src/ahc/apps/medical_notes/urls.py index dea5590..cf54c43 100644 --- a/AHC_app/medical_notes/urls.py +++ b/src/ahc/apps/medical_notes/urls.py @@ -1,13 +1,14 @@ from django.urls import path -from medical_notes.views import type_basic_note as notes_views -from medical_notes.views import type_feeding_notes as feeding_views -from medical_notes.views import type_measurement_notes as measurement_views + +from ahc.apps.medical_notes.views import type_basic_note as notes_views +from ahc.apps.medical_notes.views import type_feeding_notes as feeding_views +from ahc.apps.medical_notes.views import type_measurement_notes as measurement_views urlpatterns = [ path("/create/", notes_views.CreateNoteFormView.as_view(), name="note_create"), path("/edit/", notes_views.EditNoteView.as_view(), name="note_edit"), path("/delete/", notes_views.DeleteNoteView.as_view(), name="note_delete"), - path("/realted/", notes_views.EditRelatedAnimalsView.as_view(), name="note_animals_edit"), + path("/related/", notes_views.EditRelatedAnimalsView.as_view(), name="note_animals_edit"), path("/notes/", notes_views.FullTimelineOfNotes.as_view(), name="full_timeline_of_notes"), path("/feeding_create/", feeding_views.DietRecordCreateView.as_view(), name="feeding_create"), path("/feeding_edit/", feeding_views.EditDietRecordView.as_view(), name="feeding_edit"), diff --git a/AHC_app/medical_notes/views.py b/src/ahc/apps/medical_notes/views.py similarity index 100% rename from AHC_app/medical_notes/views.py rename to src/ahc/apps/medical_notes/views.py diff --git a/AHC_app/medical_notes/views/__init__.py b/src/ahc/apps/medical_notes/views/__init__.py similarity index 100% rename from AHC_app/medical_notes/views/__init__.py rename to src/ahc/apps/medical_notes/views/__init__.py diff --git a/AHC_app/medical_notes/views/mixins/user_animal_permisions.py b/src/ahc/apps/medical_notes/views/mixins/user_animal_permisions.py similarity index 100% rename from AHC_app/medical_notes/views/mixins/user_animal_permisions.py rename to src/ahc/apps/medical_notes/views/mixins/user_animal_permisions.py diff --git a/AHC_app/medical_notes/views/type_basic_note.py b/src/ahc/apps/medical_notes/views/type_basic_note.py similarity index 96% rename from AHC_app/medical_notes/views/type_basic_note.py rename to src/ahc/apps/medical_notes/views/type_basic_note.py index 7748361..13110d8 100644 --- a/AHC_app/medical_notes/views/type_basic_note.py +++ b/src/ahc/apps/medical_notes/views/type_basic_note.py @@ -1,4 +1,3 @@ -from animals.models import Animal as AnimalProfile from django.conf import settings from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin @@ -12,13 +11,15 @@ from django.views.generic import View from django.views.generic.edit import DeleteView, FormView, UpdateView from django.views.generic.list import ListView -from medical_notes.forms.type_basic_note import ( + +from ahc.apps.animals.models import Animal as AnimalProfile +from ahc.apps.medical_notes.forms.type_basic_note import ( MedicalRecordEditForm, MedicalRecordEditRelatedAnimalsForm, MedicalRecordForm, UploadAppendixForm, ) -from medical_notes.models.type_basic_note import MedicalRecord, MedicalRecordAttachment +from ahc.apps.medical_notes.models.type_basic_note import MedicalRecord, MedicalRecordAttachment # UploadAppendixFormSet = formset_factory(UploadAppendixForm, extra=0) @@ -32,9 +33,7 @@ def get_form_kwargs(self): kwargs = super().get_form_kwargs() query = ( - AnimalProfile.objects.filter( - Q(owner=self.request.user.profile) | Q(allowed_users=self.request.user.profile) - ) + AnimalProfile.objects.filter(Q(owner=self.request.user.profile) | Q(allowed_users=self.request.user.profile)) .exclude(id=self.kwargs.get("pk")) .order_by("-creation_date") ) @@ -133,7 +132,7 @@ def get_context_data(self, **kwargs): form.fields["medical_record_id"].initial = str(note.id) upload_forms.append(form) - notes_with_forms = zip(context["notes"], upload_forms) + notes_with_forms = zip(context["notes"], upload_forms, strict=False) context["notes"] = notes_with_forms @@ -182,7 +181,7 @@ def post(self, request, *args, **kwargs): else: print(form.errors) - for field, errors in form.errors.items(): + for _field, errors in form.errors.items(): messages.error(request, f"Failed to upload: {', '.join(errors)}") return redirect(request.path) @@ -371,7 +370,7 @@ def test_func(self): def get(self, request, *args, **kwargs): couch_connector = settings.COUCH_DB reference_id = self.kwargs.get("id") - filename = self.kwargs.get("name") + _filename = self.kwargs.get("name") attachment = couch_connector.get(reference_id) if not attachment: diff --git a/AHC_app/medical_notes/views/type_feeding_notes.py b/src/ahc/apps/medical_notes/views/type_feeding_notes.py similarity index 95% rename from AHC_app/medical_notes/views/type_feeding_notes.py rename to src/ahc/apps/medical_notes/views/type_feeding_notes.py index 7fe7c76..13a4fc1 100644 --- a/AHC_app/medical_notes/views/type_feeding_notes.py +++ b/src/ahc/apps/medical_notes/views/type_feeding_notes.py @@ -1,4 +1,3 @@ -from animals.models import Animal as AnimalProfile from django.conf import settings from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin from django.http import HttpResponseRedirect @@ -6,12 +5,14 @@ from django.urls import reverse_lazy from django.views.generic.edit import FormView, UpdateView from django.views.generic.list import ListView -from medical_notes.forms.type_feeding_notes import ( + +from ahc.apps.animals.models import Animal as AnimalProfile +from ahc.apps.medical_notes.forms.type_feeding_notes import ( DietRecordForm, NotificationRecordForm, ) -from medical_notes.models.type_basic_note import MedicalRecord -from medical_notes.models.type_feeding_notes import EmailNotification, FeedingNote +from ahc.apps.medical_notes.models.type_basic_note import MedicalRecord +from ahc.apps.medical_notes.models.type_feeding_notes import EmailNotification, FeedingNote class DietRecordCreateView(LoginRequiredMixin, UserPassesTestMixin, FormView): @@ -27,7 +28,7 @@ def form_valid(self, form): note_id = self.kwargs.get("pk") related_note = get_object_or_404(MedicalRecord, id=note_id) - animal = related_note.animal + _animal = related_note.animal feeding_note = form.save(commit=False) feeding_note.related_note = related_note diff --git a/AHC_app/medical_notes/views/type_measurement_notes.py b/src/ahc/apps/medical_notes/views/type_measurement_notes.py similarity index 83% rename from AHC_app/medical_notes/views/type_measurement_notes.py rename to src/ahc/apps/medical_notes/views/type_measurement_notes.py index e4c0a3b..0e48e33 100644 --- a/AHC_app/medical_notes/views/type_measurement_notes.py +++ b/src/ahc/apps/medical_notes/views/type_measurement_notes.py @@ -1,9 +1,10 @@ -from animals.models import Animal as AnimalProfile from django.shortcuts import get_object_or_404, redirect, reverse from django.views.generic.edit import FormView -from medical_notes.forms.type_measurement_notes import BiometricRecordForm -from medical_notes.models.type_basic_note import MedicalRecord -from medical_notes.models.type_measurement_notes import ( + +from ahc.apps.animals.models import Animal as AnimalProfile +from ahc.apps.medical_notes.forms.type_measurement_notes import BiometricRecordForm +from ahc.apps.medical_notes.models.type_basic_note import MedicalRecord +from ahc.apps.medical_notes.models.type_measurement_notes import ( BiometricCustomRecords, BiometricHeightRecords, BiometricRecord, @@ -34,7 +35,7 @@ def form_valid(self, form): weight = form.cleaned_data["weight"] unit = form.cleaned_data["weight_unit_to_present"] weight_record = BiometricWeightRecords.objects.create(weight=weight, weight_unit_to_present=unit) - biometric_record = BiometricRecord.objects.create( + _biometric_record = BiometricRecord.objects.create( animal=animal, related_note=related_note, weight_biometric_record=weight_record, @@ -43,7 +44,7 @@ def form_valid(self, form): height = form.cleaned_data["height"] unit = form.cleaned_data["height_unit_to_present"] height_record = BiometricHeightRecords.objects.create(height=height, height_unit_to_present=unit) - biometric_record = BiometricRecord.objects.create( + _biometric_record = BiometricRecord.objects.create( animal=animal, related_note=related_note, height_biometric_record=height_record, @@ -57,7 +58,7 @@ def form_valid(self, form): record_value=custom_value, record_unit=custom_unit, ) - biometric_record = BiometricRecord.objects.create( + _biometric_record = BiometricRecord.objects.create( animal=animal, related_note=related_note, custom_biometric_record=custom_record, diff --git a/AHC_app/users/__init__.py b/src/ahc/apps/users/__init__.py similarity index 100% rename from AHC_app/users/__init__.py rename to src/ahc/apps/users/__init__.py diff --git a/AHC_app/users/admin.py b/src/ahc/apps/users/admin.py similarity index 59% rename from AHC_app/users/admin.py rename to src/ahc/apps/users/admin.py index ed54a24..6074baa 100644 --- a/AHC_app/users/admin.py +++ b/src/ahc/apps/users/admin.py @@ -1,4 +1,5 @@ from django.contrib import admin -from users.models import Profile + +from ahc.apps.users.models import Profile admin.site.register(Profile) diff --git a/AHC_app/users/apps.py b/src/ahc/apps/users/apps.py similarity index 84% rename from AHC_app/users/apps.py rename to src/ahc/apps/users/apps.py index d7ff0b2..ab86c76 100644 --- a/AHC_app/users/apps.py +++ b/src/ahc/apps/users/apps.py @@ -3,7 +3,7 @@ class UsersConfig(AppConfig): default_auto_field = "django.db.models.BigAutoField" - name = "users" + name = "ahc.apps.users" def ready(self): pass diff --git a/AHC_app/users/forms.py b/src/ahc/apps/users/forms.py similarity index 92% rename from AHC_app/users/forms.py rename to src/ahc/apps/users/forms.py index 37c2b8d..acc0b2f 100644 --- a/AHC_app/users/forms.py +++ b/src/ahc/apps/users/forms.py @@ -1,6 +1,7 @@ from django import forms from django.contrib.auth.forms import User, UserCreationForm -from users.models import Profile + +from ahc.apps.users.models import Profile class UserRegisterForm(UserCreationForm): diff --git a/AHC_app/users/migrations/0001_initial.py b/src/ahc/apps/users/migrations/0001_initial.py similarity index 100% rename from AHC_app/users/migrations/0001_initial.py rename to src/ahc/apps/users/migrations/0001_initial.py diff --git a/AHC_app/users/migrations/0002_profile_allow_recennt_animals_list.py b/src/ahc/apps/users/migrations/0002_profile_allow_recennt_animals_list.py similarity index 99% rename from AHC_app/users/migrations/0002_profile_allow_recennt_animals_list.py rename to src/ahc/apps/users/migrations/0002_profile_allow_recennt_animals_list.py index 7fee793..f7296ae 100644 --- a/AHC_app/users/migrations/0002_profile_allow_recennt_animals_list.py +++ b/src/ahc/apps/users/migrations/0002_profile_allow_recennt_animals_list.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ("users", "0001_initial"), ] diff --git a/AHC_app/users/migrations/0003_profile_pinned_animals.py b/src/ahc/apps/users/migrations/0003_profile_pinned_animals.py similarity index 99% rename from AHC_app/users/migrations/0003_profile_pinned_animals.py rename to src/ahc/apps/users/migrations/0003_profile_pinned_animals.py index c039789..4087290 100644 --- a/AHC_app/users/migrations/0003_profile_pinned_animals.py +++ b/src/ahc/apps/users/migrations/0003_profile_pinned_animals.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ("animals", "0001_initial"), ("users", "0002_profile_allow_recennt_animals_list"), diff --git a/AHC_app/users/migrations/__init__.py b/src/ahc/apps/users/migrations/__init__.py similarity index 100% rename from AHC_app/users/migrations/__init__.py rename to src/ahc/apps/users/migrations/__init__.py diff --git a/AHC_app/users/models.py b/src/ahc/apps/users/models.py similarity index 94% rename from AHC_app/users/models.py rename to src/ahc/apps/users/models.py index 9a67048..badcf02 100644 --- a/AHC_app/users/models.py +++ b/src/ahc/apps/users/models.py @@ -1,8 +1,9 @@ from django.contrib.auth.models import User from django.db import models -from homepage.models import Privilege, ProfileBackground from PIL import Image +from ahc.apps.homepage.models import Privilege, ProfileBackground + class Profile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) diff --git a/AHC_app/users/signals.py b/src/ahc/apps/users/signals.py similarity index 82% rename from AHC_app/users/signals.py rename to src/ahc/apps/users/signals.py index 6821573..6a7f786 100644 --- a/AHC_app/users/signals.py +++ b/src/ahc/apps/users/signals.py @@ -1,8 +1,9 @@ from django.contrib.auth.models import User from django.db.models.signals import post_save, pre_save from django.dispatch import receiver -from homepage.models import Privilege, ProfileBackground -from users.models import Profile + +from ahc.apps.homepage.models import Privilege, ProfileBackground +from ahc.apps.users.models import Profile @receiver(pre_save, sender=Profile) @@ -22,7 +23,7 @@ def create_background(sender, instance, **kwargs): @receiver(post_save, sender=User) def create_profile(sender, instance, created, **kwargs): if created: - background, _ = ProfileBackground.objects.get_or_create(title="Default Background") + _background, _ = ProfileBackground.objects.get_or_create(title="Default Background") Profile.objects.create(user=instance) diff --git a/AHC_app/users/templates/users/login.html b/src/ahc/apps/users/templates/users/login.html similarity index 98% rename from AHC_app/users/templates/users/login.html rename to src/ahc/apps/users/templates/users/login.html index b08716c..2322254 100644 --- a/AHC_app/users/templates/users/login.html +++ b/src/ahc/apps/users/templates/users/login.html @@ -23,4 +23,4 @@ -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/AHC_app/users/templates/users/login_success.html b/src/ahc/apps/users/templates/users/login_success.html similarity index 98% rename from AHC_app/users/templates/users/login_success.html rename to src/ahc/apps/users/templates/users/login_success.html index cf6e929..106bfab 100644 --- a/AHC_app/users/templates/users/login_success.html +++ b/src/ahc/apps/users/templates/users/login_success.html @@ -21,4 +21,4 @@ -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/AHC_app/users/templates/users/logout.html b/src/ahc/apps/users/templates/users/logout.html similarity index 100% rename from AHC_app/users/templates/users/logout.html rename to src/ahc/apps/users/templates/users/logout.html diff --git a/AHC_app/users/templates/users/password_reset.html b/src/ahc/apps/users/templates/users/password_reset.html similarity index 81% rename from AHC_app/users/templates/users/password_reset.html rename to src/ahc/apps/users/templates/users/password_reset.html index 1c2f919..02384ea 100644 --- a/AHC_app/users/templates/users/password_reset.html +++ b/src/ahc/apps/users/templates/users/password_reset.html @@ -5,10 +5,10 @@ {% csrf_token %}

Reset Password

{% for field in form %} - {{ field.label_tag }} + {{ field.label_tag }} {{ field }} {% if field.errors %} - {{ field.errors|striptags }} + {{ field.errors|striptags }} {% endif %} {% endfor %}
@@ -17,4 +17,4 @@

Reset Password

-{%endblock content%} \ No newline at end of file +{%endblock content%} diff --git a/AHC_app/users/templates/users/password_reset_complete.html b/src/ahc/apps/users/templates/users/password_reset_complete.html similarity index 88% rename from AHC_app/users/templates/users/password_reset_complete.html rename to src/ahc/apps/users/templates/users/password_reset_complete.html index 23a11e2..c7160eb 100644 --- a/AHC_app/users/templates/users/password_reset_complete.html +++ b/src/ahc/apps/users/templates/users/password_reset_complete.html @@ -4,5 +4,5 @@

Your password has been changed successfully. Please Login

- -{%endblock content%} \ No newline at end of file + +{%endblock content%} diff --git a/AHC_app/users/templates/users/password_reset_confirm.html b/src/ahc/apps/users/templates/users/password_reset_confirm.html similarity index 80% rename from AHC_app/users/templates/users/password_reset_confirm.html rename to src/ahc/apps/users/templates/users/password_reset_confirm.html index 4ddd783..5e3d36c 100644 --- a/AHC_app/users/templates/users/password_reset_confirm.html +++ b/src/ahc/apps/users/templates/users/password_reset_confirm.html @@ -5,16 +5,16 @@
{% csrf_token %}

Password Reset Confirm

- + {% for field in form %} - {{ field.label_tag }} + {{ field.label_tag }} {{ field }} {% if field.errors %} - {{ field.errors|striptags }} + {{ field.errors|striptags }} {% endif %} {% endfor %} - - + +
diff --git a/AHC_app/users/templates/users/password_reset_done.html b/src/ahc/apps/users/templates/users/password_reset_done.html similarity index 90% rename from AHC_app/users/templates/users/password_reset_done.html rename to src/ahc/apps/users/templates/users/password_reset_done.html index adf83a3..f92eef6 100644 --- a/AHC_app/users/templates/users/password_reset_done.html +++ b/src/ahc/apps/users/templates/users/password_reset_done.html @@ -6,4 +6,4 @@

Reset Password

Please check your inbox and follow the instruction to reset your password.

-{%endblock content%} \ No newline at end of file +{%endblock content%} diff --git a/AHC_app/users/templates/users/password_reset_email.html b/src/ahc/apps/users/templates/users/password_reset_email.html similarity index 93% rename from AHC_app/users/templates/users/password_reset_email.html rename to src/ahc/apps/users/templates/users/password_reset_email.html index 098d1e9..7c768d7 100644 --- a/AHC_app/users/templates/users/password_reset_email.html +++ b/src/ahc/apps/users/templates/users/password_reset_email.html @@ -7,4 +7,4 @@ {{ protocol }}://{{ domain }}{% url "password_reset_confirm" uidb64=uid token=token %}

Thanks

-

Todo App Team

\ No newline at end of file +

Todo App Team

diff --git a/AHC_app/users/templates/users/profile.html b/src/ahc/apps/users/templates/users/profile.html similarity index 100% rename from AHC_app/users/templates/users/profile.html rename to src/ahc/apps/users/templates/users/profile.html diff --git a/AHC_app/users/templates/users/register.html b/src/ahc/apps/users/templates/users/register.html similarity index 100% rename from AHC_app/users/templates/users/register.html rename to src/ahc/apps/users/templates/users/register.html diff --git a/src/ahc/apps/users/tests.py b/src/ahc/apps/users/tests.py new file mode 100644 index 0000000..7984f3e --- /dev/null +++ b/src/ahc/apps/users/tests.py @@ -0,0 +1,27 @@ +import pytest + +from ahc.apps.users.models import Profile + + +@pytest.mark.integration +@pytest.mark.django_db +class TestProfileModel: + def test_str_returns_username(self, user_profile): + _, profile = user_profile + assert str(profile) == "testuser" + + def test_profile_linked_to_user(self, user_profile): + user, profile = user_profile + assert profile.user == user + + def test_allow_recent_animals_list_defaults_to_true(self, user_profile): + _, profile = user_profile + assert profile.allow_recennt_animals_list is True + + def test_pinned_animals_empty_by_default(self, user_profile): + _, profile = user_profile + assert profile.pinned_animals.count() == 0 + + def test_profile_is_unique_per_user(self, user_profile): + user, _ = user_profile + assert Profile.objects.filter(user=user).count() == 1 diff --git a/AHC_app/users/urls.py b/src/ahc/apps/users/urls.py similarity index 89% rename from AHC_app/users/urls.py rename to src/ahc/apps/users/urls.py index b0a23c4..33b0792 100644 --- a/AHC_app/users/urls.py +++ b/src/ahc/apps/users/urls.py @@ -6,15 +6,14 @@ PasswordResetView, ) from django.urls import path -from users import views as user_views + +from ahc.apps.users import views as user_views urlpatterns = [ path("", auth_views.LoginView.as_view(template_name="users/login.html"), name="login"), path("login/", auth_views.LoginView.as_view(template_name="users/login.html"), name="login"), path("register/", user_views.UserRegisterView.as_view(), name="register"), - path( - "login_success/", auth_views.LoginView.as_view(template_name="users/login_success.html"), name="login_success" - ), + path("login_success/", auth_views.LoginView.as_view(template_name="users/login_success.html"), name="login_success"), path("logout/", auth_views.LogoutView.as_view(template_name="users/logout.html"), name="logout"), path("profile/", user_views.UserProfileView.as_view(), name="profile"), path( diff --git a/AHC_app/users/views.py b/src/ahc/apps/users/views.py similarity index 90% rename from AHC_app/users/views.py rename to src/ahc/apps/users/views.py index dc39aeb..bb7e5c1 100644 --- a/AHC_app/users/views.py +++ b/src/ahc/apps/users/views.py @@ -2,8 +2,9 @@ from django.contrib.auth.mixins import LoginRequiredMixin from django.urls import reverse_lazy from django.views.generic import CreateView, UpdateView -from users.forms import ProfileUpdateForm, UserRegisterForm, UserUpdateForm -from users.models import Profile + +from ahc.apps.users.forms import ProfileUpdateForm, UserRegisterForm, UserUpdateForm +from ahc.apps.users.models import Profile class UserRegisterView(CreateView): diff --git a/AHC_app/AHC_app/asgi.py b/src/ahc/asgi.py similarity index 82% rename from AHC_app/AHC_app/asgi.py rename to src/ahc/asgi.py index 5ce600a..edf19c7 100644 --- a/AHC_app/AHC_app/asgi.py +++ b/src/ahc/asgi.py @@ -11,6 +11,6 @@ from django.core.asgi import get_asgi_application -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "AHC_app.settings") +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ahc.settings") application = get_asgi_application() diff --git a/AHC_app/AHC_app/settings.py b/src/ahc/settings.py similarity index 68% rename from AHC_app/AHC_app/settings.py rename to src/ahc/settings.py index f933f48..c5664ea 100644 --- a/AHC_app/AHC_app/settings.py +++ b/src/ahc/settings.py @@ -9,29 +9,54 @@ For the full list of settings and their values, see https://docs.djangoproject.com/en/4.2/ref/settings/ """ -import os -import sys +import sys from pathlib import Path import pycouchdb +from decouple import Csv, config + +_OFFLINE_COMMANDS = { + "check", + "collectstatic", + "compress", + "crontab", + "makemigrations", + "migrate", + "shell", + "showmigrations", + "sqlmigrate", + "test", +} + + +def _is_test_run() -> bool: + return "test" in sys.argv or (bool(sys.argv) and "pytest" in sys.argv[0]) + + +def _skip_external_services() -> bool: + """Return True when live network backends (CouchDB) must not be initialised. + + Covers: pytest invocations, manage.py test, and any manage.py command that + does not require a running CouchDB connection at import time. + """ + return _is_test_run() or any(cmd in sys.argv for cmd in _OFFLINE_COMMANDS) -from decouple import config # Build paths inside the project like this: BASE_DIR / 'subdir'. -BASE_DIR = Path(__file__).resolve().parent.parent +BASE_DIR = Path(__file__).resolve().parents[2] # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ -# SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = "django-insecure-x#q0@altnjw2yrhh)edi)co2)n3p8q&0qmz7m8oxu-*jhd8d9-" - -# SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True - -ALLOWED_HOSTS = [] +if _is_test_run(): + SECRET_KEY = config("SECRET_KEY", default="django-insecure-test-only-not-for-production") + DEBUG = True +else: + SECRET_KEY = config("SECRET_KEY") + DEBUG = config("DEBUG", default=False, cast=bool) +ALLOWED_HOSTS = config("ALLOWED_HOSTS", default="localhost,127.0.0.1", cast=Csv()) # Application definition @@ -43,21 +68,21 @@ "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", + "django.contrib.postgres", "crispy_forms", "crispy_bootstrap4", "bootstrap_modal_forms", "compressor", "taggit", - "django_crontab", - "django_cron", - "homepage.apps.HomepageConfig", - "users.apps.UsersConfig", - "animals.apps.AnimalsConfig", - "medical_notes.apps.MedicalNotesConfig", + "ahc.apps.homepage.apps.HomepageConfig", + "ahc.apps.users.apps.UsersConfig", + "ahc.apps.animals.apps.AnimalsConfig", + "ahc.apps.medical_notes.apps.MedicalNotesConfig", ] MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", + "django.middleware.csp.ContentSecurityPolicyMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.common.CommonMiddleware", "django.middleware.csrf.CsrfViewMiddleware", @@ -66,7 +91,7 @@ "django.middleware.clickjacking.XFrameOptionsMiddleware", ] -ROOT_URLCONF = "AHC_app.urls" +ROOT_URLCONF = "ahc.urls" TEMPLATES = [ { @@ -90,13 +115,13 @@ CRISPY_TEMPLATE_PACK = "bootstrap4" -WSGI_APPLICATION = "AHC_app.wsgi.application" +WSGI_APPLICATION = "ahc.wsgi.application" # Database # https://docs.djangoproject.com/en/4.2/ref/settings/#databases -if "test" in sys.argv: +if _is_test_run(): DATABASES = { "default": { "ENGINE": "django.db.backends.sqlite3", @@ -117,8 +142,7 @@ # COUCH_CONNECTOR = (config("COUCH_CONNECTOR"),) -if "test" not in sys.argv: - +if not _skip_external_services(): COUCHDB_USER = config("COUCHDB_USER") COUCHDB_PASSWORD = config("COUCHDB_PASSWORD") COUCHDB_PORT = config("COUCHDB_PORT") @@ -169,7 +193,7 @@ STATIC_URL = "/static/" STATIC_ROOT = "static_collected" STATICFILES_DIRS = [ - os.path.join(BASE_DIR, "static/"), + BASE_DIR / "static", ] STATICFILES_FINDERS = [ @@ -182,7 +206,20 @@ COMPRESS_PRECOMPILERS = (("text/x-scss", "django_libsass.SassCompiler"),) COMPRESS_OFFLINE = True LIBSASS_OUTPUT_STYLE = "compressed" -STATICFILES_STORAGE = "django.contrib.staticfiles.storage.ManifestStaticFilesStorage" + +_staticfiles_backend = ( + "django.contrib.staticfiles.storage.StaticFilesStorage" + if _is_test_run() + else "django.contrib.staticfiles.storage.ManifestStaticFilesStorage" +) +STORAGES = { + "default": { + "BACKEND": "django.core.files.storage.FileSystemStorage", + }, + "staticfiles": { + "BACKEND": _staticfiles_backend, + }, +} """ DOCUMENTATION TO CUSTOM SCSS: https://picocss.com/docs/customization.html @@ -194,7 +231,7 @@ """ MEDIA_URL = "/media/" -MEDIA_ROOT = os.path.join(BASE_DIR, "static/media") +MEDIA_ROOT = BASE_DIR / "static" / "media" # Default primary key field type # https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field @@ -202,18 +239,6 @@ DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" -CRONJOBS = [ - # ("*/4 * * * *", "AHC_app.celery_notifications.cron.send_emails"), - # ("*/2 * * * *", "AHC_app.celery_notifications.cron.send_email_example"), - # # ('2 * * * *', 'AHC_app.celery_notifications.cron:send_emails'), - # ("4 * * * *", "AHC_app.celery_notifications.cron.send_sms"), - ("6 * * * *", "AHC_app.celery_notifications.cron.send_discord_notes"), -] - -CRON_CLASSES = [ - # 'AHC_app.celery_notifications.cron.SynchNotificationsCron', -] - CELERY_BROKER_URL = config("CELERY_BROKER_URL") CELERY_BACKEND = config("CELERY_BACKEND") @@ -228,3 +253,23 @@ DISCORD_TOKEN = config("DISCORD_TOKEN") TEST_RUNNER = "django.test.runner.DiscoverRunner" + +from django.utils.csp import CSP # noqa: E402 + +SECURE_CSP = { + "default-src": [CSP.SELF], + "script-src": [CSP.SELF], + "style-src": [CSP.SELF, CSP.UNSAFE_INLINE, "https://fonts.googleapis.com"], + "img-src": [CSP.SELF, "data:"], + "font-src": [CSP.SELF, "https://fonts.gstatic.com"], + "connect-src": [CSP.SELF], + "object-src": [CSP.NONE], + "base-uri": [CSP.SELF], +} +SECURE_CSP_REPORT_ONLY = SECURE_CSP + +TASKS = { + "default": { + "BACKEND": "django.tasks.backends.immediate.ImmediateBackend", + }, +} diff --git a/AHC_app/AHC_app/urls.py b/src/ahc/urls.py similarity index 78% rename from AHC_app/AHC_app/urls.py rename to src/ahc/urls.py index 4ef5aef..cb0ff0d 100644 --- a/AHC_app/AHC_app/urls.py +++ b/src/ahc/urls.py @@ -14,6 +14,7 @@ 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ + from django.conf import settings from django.conf.urls.static import static from django.contrib import admin @@ -22,12 +23,13 @@ urlpatterns = [ path("admin/", admin.site.urls), - path("", include("homepage.urls")), - path("user/", include("users.urls")), - path("pet/", include("animals.urls")), - path("note/", include("medical_notes.urls")), + path("", include("ahc.apps.homepage.urls")), + path("user/", include("ahc.apps.users.urls")), + path("pet/", include("ahc.apps.animals.urls")), + path("note/", include("ahc.apps.medical_notes.urls")), path( "favicon.ico", RedirectView.as_view(url=static("media/icons/chinchilla.png")), ), -] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + *static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT), +] diff --git a/AHC_app/AHC_app/wsgi.py b/src/ahc/wsgi.py similarity index 82% rename from AHC_app/AHC_app/wsgi.py rename to src/ahc/wsgi.py index 7375290..96b6880 100644 --- a/AHC_app/AHC_app/wsgi.py +++ b/src/ahc/wsgi.py @@ -11,6 +11,6 @@ from django.core.wsgi import get_wsgi_application -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "AHC_app.settings") +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ahc.settings") application = get_wsgi_application() diff --git a/AHC_app/static/AHC_app/base.css b/src/celery_notifications/__init__.py similarity index 100% rename from AHC_app/static/AHC_app/base.css rename to src/celery_notifications/__init__.py diff --git a/AHC_app/AHC_app/celery_notifications/config.py b/src/celery_notifications/config.py similarity index 61% rename from AHC_app/AHC_app/celery_notifications/config.py rename to src/celery_notifications/config.py index bcfa1c6..6f4a3b1 100644 --- a/AHC_app/AHC_app/celery_notifications/config.py +++ b/src/celery_notifications/config.py @@ -1,21 +1,37 @@ import os from celery import Celery, shared_task +from celery.schedules import crontab from celery.utils.log import get_task_logger from django.conf import settings -# from AHC_app.celery_notifications.utils.discord_utils import send_via_discord -from AHC_app.celery_notifications.utils.sending_utils import send_via_email +# from celery_notifications.utils.discord_utils import send_via_discord +from celery_notifications.utils.sending_utils import send_via_email logger = get_task_logger(__name__) -os.environ.setdefault("DJANGO_SETTING_MODULE", "django_with_celery.settings") -celery_obj = Celery("django_with_celery") +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ahc.settings") +celery_obj = Celery("ahc") celery_obj.config_from_object("django.conf:settings", namespace="CELERY") celery_obj.conf.broker_connection_retry_on_startup = True -celery_obj.autodiscover_tasks(["AHC_app"]) +celery_obj.autodiscover_tasks() + + +@celery_obj.task(name="ahc.beat.dispatch_discord_notes") +def dispatch_discord_notes(): + from celery_notifications.cron import send_discord_notes + + send_discord_notes() + + +celery_obj.conf.beat_schedule = { + "send-discord-notes-hourly": { + "task": "ahc.beat.dispatch_discord_notes", + "schedule": crontab(minute=6), + }, +} @celery_obj.task() diff --git a/AHC_app/AHC_app/celery_notifications/cron.py b/src/celery_notifications/cron.py similarity index 77% rename from AHC_app/AHC_app/celery_notifications/cron.py rename to src/celery_notifications/cron.py index a46ed4c..de1a3c2 100644 --- a/AHC_app/AHC_app/celery_notifications/cron.py +++ b/src/celery_notifications/cron.py @@ -3,26 +3,26 @@ import logging.config import logging.handlers import pathlib - from datetime import date, datetime, time, timedelta from functools import wraps from django.db.models import Q, QuerySet +from django.tasks import task from django.utils import timezone -from medical_notes.models.type_feeding_notes import EmailNotification -from AHC_app.celery_notifications.config import ( +from ahc.apps.medical_notes.models.type_feeding_notes import EmailNotification +from celery_notifications.config import ( send_discord_notifications, send_email_notifications, ) -from AHC_app.celery_notifications.utils.example_task import send_mail_fnc +from celery_notifications.utils.example_task import send_mail_fnc logger = logging.getLogger("crons_logger") def setup_logging(): - config_file = pathlib.Path("AHC_app/celery_notifications/logger_config.json") - with open(config_file, "r") as file: + config_file = pathlib.Path(__file__).parent / "logger_config.json" + with open(config_file) as file: config = json.load(file) logging.config.dictConfig(config) @@ -85,13 +85,7 @@ def send_emails() -> None: return None for notification in notifications_to_send: - user_set_zone: str = notification.timezone - # user_weekday_number: int = datetime.now( - # tz=pytz.timezone(user_set_zone) - # ).weekday() - # - # if user_weekday_number in notification.related_note.days_of_week: - # break + _user_set_zone: str = notification.timezone email: str = notification.email animal: str = notification.related_note.related_note.animal @@ -103,7 +97,7 @@ def send_emails() -> None: # "note_edit", kwargs={"pk": notification.related_note.id} # ) note_url: str = "" - center: str = f"{message} \n\n " f"For further information:\n{note_url}" + center: str = f"{message} \n\n For further information:\n{note_url}" sender: str = notification.related_note.related_note.author footer: str = f"Best regards \n{sender}" @@ -153,24 +147,13 @@ def send_discord_notes(): send_discord_notifications.apply_async(kwargs={"user_id": user_id, "user_message": user_message}, countdown=delay) -# class SynchNotificationsCron(CronJobBase): -# RUN_EVERY_MINS = 60 -# -# schedule = Schedule(run_every_mins=RUN_EVERY_MINS) -# code = "AHC_app.SynchNotificationsCronJob" -# -# # run_at_times = ["55"] -# -# @staticmethod -# def cron_send_emails(): -# from icecream import ic -# ic() -# -# send_emails() -# -# @staticmethod -# def cron_send_discord(): -# from icecream import ic -# ic() -# -# send_discord_notes() +@task +def log_notification_count() -> int: + """Django Background Tasks example. Use for simple in-process tasks. + + For distributed / retryable work, use Celery (@shared_task). + Enqueue with: log_notification_count.enqueue() + """ + count = EmailNotification.objects.filter(is_active=True).count() + logger.info("Active email notifications: %d", count) + return count diff --git a/AHC_app/AHC_app/celery_notifications/logger_config.json b/src/celery_notifications/logger_config.json similarity index 100% rename from AHC_app/AHC_app/celery_notifications/logger_config.json rename to src/celery_notifications/logger_config.json diff --git a/src/celery_notifications/utils/__init__.py b/src/celery_notifications/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/AHC_app/AHC_app/celery_notifications/utils/discord_utils.py b/src/celery_notifications/utils/discord_utils.py similarity index 94% rename from AHC_app/AHC_app/celery_notifications/utils/discord_utils.py rename to src/celery_notifications/utils/discord_utils.py index 87da4e7..c7585f0 100644 --- a/AHC_app/AHC_app/celery_notifications/utils/discord_utils.py +++ b/src/celery_notifications/utils/discord_utils.py @@ -2,10 +2,9 @@ from discord import Client, Intents from discord.ext import commands -from django.conf import settings # TOKEN = settings.DISCORD_TOKEN -TOKEN = "none" +TOKEN = "none" # nosec B105 def send_via_discord(user_id: int, user_message: str) -> None: diff --git a/AHC_app/AHC_app/celery_notifications/utils/example_task.py b/src/celery_notifications/utils/example_task.py similarity index 100% rename from AHC_app/AHC_app/celery_notifications/utils/example_task.py rename to src/celery_notifications/utils/example_task.py diff --git a/AHC_app/AHC_app/celery_notifications/utils/sending_utils.py b/src/celery_notifications/utils/sending_utils.py similarity index 87% rename from AHC_app/AHC_app/celery_notifications/utils/sending_utils.py rename to src/celery_notifications/utils/sending_utils.py index 3d8caea..fe3de81 100644 --- a/AHC_app/AHC_app/celery_notifications/utils/sending_utils.py +++ b/src/celery_notifications/utils/sending_utils.py @@ -9,8 +9,8 @@ def standardize_message_size(message: str, max_length: int = 2500) -> str: def send_via_email(**kwargs): - recipient_list = kwargs.get("email") - subject = kwargs.get("subject") + _recipient_list = kwargs.get("email") + _subject = kwargs.get("subject") message = kwargs.get("message") message = standardize_message_size(message, max_length=2500) sender_email = settings.EMAIL_HOST_USER @@ -33,7 +33,8 @@ def send_via_email(**kwargs): server.login("0c425676241dc7", "3ca81a9102980f") server.sendmail(sender, receiver, message) - # send_mail(subject=subject, message=message, from_email=sender_email, recipient_list=recipient_list, fail_silently=False) + # send_mail(subject=subject, message=message, from_email=sender_email, + # recipient_list=recipient_list, fail_silently=False) def send_via_sms(**kwargs): diff --git a/static/AHC_app/base.css b/static/AHC_app/base.css new file mode 100644 index 0000000..e69de29 diff --git a/AHC_app/static/css/expanding_sections.css b/static/css/expanding_sections.css similarity index 100% rename from AHC_app/static/css/expanding_sections.css rename to static/css/expanding_sections.css diff --git a/AHC_app/static/css/hide_large_description.css b/static/css/hide_large_description.css similarity index 100% rename from AHC_app/static/css/hide_large_description.css rename to static/css/hide_large_description.css diff --git a/AHC_app/static/css/pico-1.5.9/.github/CONTRIBUTING.md b/static/css/pico-1.5.9/.github/CONTRIBUTING.md similarity index 100% rename from AHC_app/static/css/pico-1.5.9/.github/CONTRIBUTING.md rename to static/css/pico-1.5.9/.github/CONTRIBUTING.md diff --git a/AHC_app/static/css/pico-1.5.9/.github/ISSUE_TEMPLATE/bug_report.md b/static/css/pico-1.5.9/.github/ISSUE_TEMPLATE/bug_report.md similarity index 100% rename from AHC_app/static/css/pico-1.5.9/.github/ISSUE_TEMPLATE/bug_report.md rename to static/css/pico-1.5.9/.github/ISSUE_TEMPLATE/bug_report.md diff --git a/AHC_app/static/css/pico-1.5.9/.github/ISSUE_TEMPLATE/config.yml b/static/css/pico-1.5.9/.github/ISSUE_TEMPLATE/config.yml similarity index 100% rename from AHC_app/static/css/pico-1.5.9/.github/ISSUE_TEMPLATE/config.yml rename to static/css/pico-1.5.9/.github/ISSUE_TEMPLATE/config.yml diff --git a/AHC_app/static/css/pico-1.5.9/.github/examples.jpg b/static/css/pico-1.5.9/.github/examples.jpg similarity index 100% rename from AHC_app/static/css/pico-1.5.9/.github/examples.jpg rename to static/css/pico-1.5.9/.github/examples.jpg diff --git a/AHC_app/static/css/pico-1.5.9/.github/logo.svg b/static/css/pico-1.5.9/.github/logo.svg similarity index 100% rename from AHC_app/static/css/pico-1.5.9/.github/logo.svg rename to static/css/pico-1.5.9/.github/logo.svg diff --git a/AHC_app/static/css/pico-1.5.9/.gitignore b/static/css/pico-1.5.9/.gitignore similarity index 100% rename from AHC_app/static/css/pico-1.5.9/.gitignore rename to static/css/pico-1.5.9/.gitignore diff --git a/AHC_app/static/css/pico-1.5.9/LICENSE.md b/static/css/pico-1.5.9/LICENSE.md similarity index 100% rename from AHC_app/static/css/pico-1.5.9/LICENSE.md rename to static/css/pico-1.5.9/LICENSE.md diff --git a/AHC_app/static/css/pico-1.5.9/README.md b/static/css/pico-1.5.9/README.md similarity index 100% rename from AHC_app/static/css/pico-1.5.9/README.md rename to static/css/pico-1.5.9/README.md diff --git a/AHC_app/static/css/pico-1.5.9/composer.json b/static/css/pico-1.5.9/composer.json similarity index 100% rename from AHC_app/static/css/pico-1.5.9/composer.json rename to static/css/pico-1.5.9/composer.json diff --git a/AHC_app/static/css/pico-1.5.9/css/pico.classless.css b/static/css/pico-1.5.9/css/pico.classless.css similarity index 100% rename from AHC_app/static/css/pico-1.5.9/css/pico.classless.css rename to static/css/pico-1.5.9/css/pico.classless.css diff --git a/AHC_app/static/css/pico-1.5.9/css/pico.classless.css.map b/static/css/pico-1.5.9/css/pico.classless.css.map similarity index 100% rename from AHC_app/static/css/pico-1.5.9/css/pico.classless.css.map rename to static/css/pico-1.5.9/css/pico.classless.css.map diff --git a/AHC_app/static/css/pico-1.5.9/css/pico.classless.min.css b/static/css/pico-1.5.9/css/pico.classless.min.css similarity index 100% rename from AHC_app/static/css/pico-1.5.9/css/pico.classless.min.css rename to static/css/pico-1.5.9/css/pico.classless.min.css diff --git a/AHC_app/static/css/pico-1.5.9/css/pico.classless.min.css.map b/static/css/pico-1.5.9/css/pico.classless.min.css.map similarity index 100% rename from AHC_app/static/css/pico-1.5.9/css/pico.classless.min.css.map rename to static/css/pico-1.5.9/css/pico.classless.min.css.map diff --git a/AHC_app/static/css/pico-1.5.9/css/pico.css b/static/css/pico-1.5.9/css/pico.css similarity index 100% rename from AHC_app/static/css/pico-1.5.9/css/pico.css rename to static/css/pico-1.5.9/css/pico.css diff --git a/AHC_app/static/css/pico-1.5.9/css/pico.css.map b/static/css/pico-1.5.9/css/pico.css.map similarity index 100% rename from AHC_app/static/css/pico-1.5.9/css/pico.css.map rename to static/css/pico-1.5.9/css/pico.css.map diff --git a/AHC_app/static/css/pico-1.5.9/css/pico.fluid.classless.css b/static/css/pico-1.5.9/css/pico.fluid.classless.css similarity index 100% rename from AHC_app/static/css/pico-1.5.9/css/pico.fluid.classless.css rename to static/css/pico-1.5.9/css/pico.fluid.classless.css diff --git a/AHC_app/static/css/pico-1.5.9/css/pico.fluid.classless.css.map b/static/css/pico-1.5.9/css/pico.fluid.classless.css.map similarity index 100% rename from AHC_app/static/css/pico-1.5.9/css/pico.fluid.classless.css.map rename to static/css/pico-1.5.9/css/pico.fluid.classless.css.map diff --git a/AHC_app/static/css/pico-1.5.9/css/pico.fluid.classless.min.css b/static/css/pico-1.5.9/css/pico.fluid.classless.min.css similarity index 100% rename from AHC_app/static/css/pico-1.5.9/css/pico.fluid.classless.min.css rename to static/css/pico-1.5.9/css/pico.fluid.classless.min.css diff --git a/AHC_app/static/css/pico-1.5.9/css/pico.fluid.classless.min.css.map b/static/css/pico-1.5.9/css/pico.fluid.classless.min.css.map similarity index 100% rename from AHC_app/static/css/pico-1.5.9/css/pico.fluid.classless.min.css.map rename to static/css/pico-1.5.9/css/pico.fluid.classless.min.css.map diff --git a/AHC_app/static/css/pico-1.5.9/css/pico.min.css b/static/css/pico-1.5.9/css/pico.min.css similarity index 100% rename from AHC_app/static/css/pico-1.5.9/css/pico.min.css rename to static/css/pico-1.5.9/css/pico.min.css diff --git a/AHC_app/static/css/pico-1.5.9/css/pico.min.css.map b/static/css/pico-1.5.9/css/pico.min.css.map similarity index 100% rename from AHC_app/static/css/pico-1.5.9/css/pico.min.css.map rename to static/css/pico-1.5.9/css/pico.min.css.map diff --git a/AHC_app/static/css/pico-1.5.9/css/pico.slim.css b/static/css/pico-1.5.9/css/pico.slim.css similarity index 100% rename from AHC_app/static/css/pico-1.5.9/css/pico.slim.css rename to static/css/pico-1.5.9/css/pico.slim.css diff --git a/AHC_app/static/css/pico-1.5.9/css/pico.slim.css.map b/static/css/pico-1.5.9/css/pico.slim.css.map similarity index 100% rename from AHC_app/static/css/pico-1.5.9/css/pico.slim.css.map rename to static/css/pico-1.5.9/css/pico.slim.css.map diff --git a/AHC_app/static/css/pico-1.5.9/css/pico.slim.min.css b/static/css/pico-1.5.9/css/pico.slim.min.css similarity index 100% rename from AHC_app/static/css/pico-1.5.9/css/pico.slim.min.css rename to static/css/pico-1.5.9/css/pico.slim.min.css diff --git a/AHC_app/static/css/pico-1.5.9/css/pico.slim.min.css.map b/static/css/pico-1.5.9/css/pico.slim.min.css.map similarity index 100% rename from AHC_app/static/css/pico-1.5.9/css/pico.slim.min.css.map rename to static/css/pico-1.5.9/css/pico.slim.min.css.map diff --git a/AHC_app/static/css/pico-1.5.9/css/postcss.config.js b/static/css/pico-1.5.9/css/postcss.config.js similarity index 100% rename from AHC_app/static/css/pico-1.5.9/css/postcss.config.js rename to static/css/pico-1.5.9/css/postcss.config.js diff --git a/AHC_app/static/css/pico-1.5.9/css/themes/default.css b/static/css/pico-1.5.9/css/themes/default.css similarity index 100% rename from AHC_app/static/css/pico-1.5.9/css/themes/default.css rename to static/css/pico-1.5.9/css/themes/default.css diff --git a/AHC_app/static/css/pico-1.5.9/css/themes/default.css.map b/static/css/pico-1.5.9/css/themes/default.css.map similarity index 100% rename from AHC_app/static/css/pico-1.5.9/css/themes/default.css.map rename to static/css/pico-1.5.9/css/themes/default.css.map diff --git a/AHC_app/static/css/pico-1.5.9/css/themes/default.min.css b/static/css/pico-1.5.9/css/themes/default.min.css similarity index 100% rename from AHC_app/static/css/pico-1.5.9/css/themes/default.min.css rename to static/css/pico-1.5.9/css/themes/default.min.css diff --git a/AHC_app/static/css/pico-1.5.9/css/themes/default.min.css.map b/static/css/pico-1.5.9/css/themes/default.min.css.map similarity index 100% rename from AHC_app/static/css/pico-1.5.9/css/themes/default.min.css.map rename to static/css/pico-1.5.9/css/themes/default.min.css.map diff --git a/AHC_app/static/css/pico-1.5.9/docs/accordions.html b/static/css/pico-1.5.9/docs/accordions.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/accordions.html rename to static/css/pico-1.5.9/docs/accordions.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/buttons.html b/static/css/pico-1.5.9/docs/buttons.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/buttons.html rename to static/css/pico-1.5.9/docs/buttons.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/cards.html b/static/css/pico-1.5.9/docs/cards.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/cards.html rename to static/css/pico-1.5.9/docs/cards.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/classless.html b/static/css/pico-1.5.9/docs/classless.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/classless.html rename to static/css/pico-1.5.9/docs/classless.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/containers.html b/static/css/pico-1.5.9/docs/containers.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/containers.html rename to static/css/pico-1.5.9/docs/containers.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/css/pico.docs.css b/static/css/pico-1.5.9/docs/css/pico.docs.css similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/css/pico.docs.css rename to static/css/pico-1.5.9/docs/css/pico.docs.css diff --git a/AHC_app/static/css/pico-1.5.9/docs/css/pico.docs.css.map b/static/css/pico-1.5.9/docs/css/pico.docs.css.map similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/css/pico.docs.css.map rename to static/css/pico-1.5.9/docs/css/pico.docs.css.map diff --git a/AHC_app/static/css/pico-1.5.9/docs/css/pico.docs.min.css b/static/css/pico-1.5.9/docs/css/pico.docs.min.css similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/css/pico.docs.min.css rename to static/css/pico-1.5.9/docs/css/pico.docs.min.css diff --git a/AHC_app/static/css/pico-1.5.9/docs/css/pico.docs.min.css.map b/static/css/pico-1.5.9/docs/css/pico.docs.min.css.map similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/css/pico.docs.min.css.map rename to static/css/pico-1.5.9/docs/css/pico.docs.min.css.map diff --git a/AHC_app/static/css/pico-1.5.9/docs/customization.html b/static/css/pico-1.5.9/docs/customization.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/customization.html rename to static/css/pico-1.5.9/docs/customization.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/dropdowns.html b/static/css/pico-1.5.9/docs/dropdowns.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/dropdowns.html rename to static/css/pico-1.5.9/docs/dropdowns.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/forms.html b/static/css/pico-1.5.9/docs/forms.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/forms.html rename to static/css/pico-1.5.9/docs/forms.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/grid.html b/static/css/pico-1.5.9/docs/grid.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/grid.html rename to static/css/pico-1.5.9/docs/grid.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/index.html b/static/css/pico-1.5.9/docs/index.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/index.html rename to static/css/pico-1.5.9/docs/index.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/js/commons.js b/static/css/pico-1.5.9/docs/js/commons.js similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/js/commons.js rename to static/css/pico-1.5.9/docs/js/commons.js diff --git a/AHC_app/static/css/pico-1.5.9/docs/js/commons.min.js b/static/css/pico-1.5.9/docs/js/commons.min.js similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/js/commons.min.js rename to static/css/pico-1.5.9/docs/js/commons.min.js diff --git a/AHC_app/static/css/pico-1.5.9/docs/js/customization.js b/static/css/pico-1.5.9/docs/js/customization.js similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/js/customization.js rename to static/css/pico-1.5.9/docs/js/customization.js diff --git a/AHC_app/static/css/pico-1.5.9/docs/js/customization.min.js b/static/css/pico-1.5.9/docs/js/customization.min.js similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/js/customization.min.js rename to static/css/pico-1.5.9/docs/js/customization.min.js diff --git a/AHC_app/static/css/pico-1.5.9/docs/js/grid.js b/static/css/pico-1.5.9/docs/js/grid.js similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/js/grid.js rename to static/css/pico-1.5.9/docs/js/grid.js diff --git a/AHC_app/static/css/pico-1.5.9/docs/js/grid.min.js b/static/css/pico-1.5.9/docs/js/grid.min.js similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/js/grid.min.js rename to static/css/pico-1.5.9/docs/js/grid.min.js diff --git a/AHC_app/static/css/pico-1.5.9/docs/js/modal.js b/static/css/pico-1.5.9/docs/js/modal.js similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/js/modal.js rename to static/css/pico-1.5.9/docs/js/modal.js diff --git a/AHC_app/static/css/pico-1.5.9/docs/js/modal.min.js b/static/css/pico-1.5.9/docs/js/modal.min.js similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/js/modal.min.js rename to static/css/pico-1.5.9/docs/js/modal.min.js diff --git a/AHC_app/static/css/pico-1.5.9/docs/js/src/color-picker.js b/static/css/pico-1.5.9/docs/js/src/color-picker.js similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/js/src/color-picker.js rename to static/css/pico-1.5.9/docs/js/src/color-picker.js diff --git a/AHC_app/static/css/pico-1.5.9/docs/js/src/material-design-colors.js b/static/css/pico-1.5.9/docs/js/src/material-design-colors.js similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/js/src/material-design-colors.js rename to static/css/pico-1.5.9/docs/js/src/material-design-colors.js diff --git a/AHC_app/static/css/pico-1.5.9/docs/js/src/theme-switcher.js b/static/css/pico-1.5.9/docs/js/src/theme-switcher.js similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/js/src/theme-switcher.js rename to static/css/pico-1.5.9/docs/js/src/theme-switcher.js diff --git a/AHC_app/static/css/pico-1.5.9/docs/js/src/toggle-navigation.js b/static/css/pico-1.5.9/docs/js/src/toggle-navigation.js similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/js/src/toggle-navigation.js rename to static/css/pico-1.5.9/docs/js/src/toggle-navigation.js diff --git a/AHC_app/static/css/pico-1.5.9/docs/loading.html b/static/css/pico-1.5.9/docs/loading.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/loading.html rename to static/css/pico-1.5.9/docs/loading.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/modal.html b/static/css/pico-1.5.9/docs/modal.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/modal.html rename to static/css/pico-1.5.9/docs/modal.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/navs.html b/static/css/pico-1.5.9/docs/navs.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/navs.html rename to static/css/pico-1.5.9/docs/navs.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/progress.html b/static/css/pico-1.5.9/docs/progress.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/progress.html rename to static/css/pico-1.5.9/docs/progress.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/rtl.html b/static/css/pico-1.5.9/docs/rtl.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/rtl.html rename to static/css/pico-1.5.9/docs/rtl.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/scroller.html b/static/css/pico-1.5.9/docs/scroller.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/scroller.html rename to static/css/pico-1.5.9/docs/scroller.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/scss/components/_modal.scss b/static/css/pico-1.5.9/docs/scss/components/_modal.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/scss/components/_modal.scss rename to static/css/pico-1.5.9/docs/scss/components/_modal.scss diff --git a/AHC_app/static/css/pico-1.5.9/docs/scss/components/_nav.scss b/static/css/pico-1.5.9/docs/scss/components/_nav.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/scss/components/_nav.scss rename to static/css/pico-1.5.9/docs/scss/components/_nav.scss diff --git a/AHC_app/static/css/pico-1.5.9/docs/scss/components/_theme-switcher.scss b/static/css/pico-1.5.9/docs/scss/components/_theme-switcher.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/scss/components/_theme-switcher.scss rename to static/css/pico-1.5.9/docs/scss/components/_theme-switcher.scss diff --git a/AHC_app/static/css/pico-1.5.9/docs/scss/content/_code.scss b/static/css/pico-1.5.9/docs/scss/content/_code.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/scss/content/_code.scss rename to static/css/pico-1.5.9/docs/scss/content/_code.scss diff --git a/AHC_app/static/css/pico-1.5.9/docs/scss/content/_typography.scss b/static/css/pico-1.5.9/docs/scss/content/_typography.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/scss/content/_typography.scss rename to static/css/pico-1.5.9/docs/scss/content/_typography.scss diff --git a/AHC_app/static/css/pico-1.5.9/docs/scss/layout/_aside.scss b/static/css/pico-1.5.9/docs/scss/layout/_aside.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/scss/layout/_aside.scss rename to static/css/pico-1.5.9/docs/scss/layout/_aside.scss diff --git a/AHC_app/static/css/pico-1.5.9/docs/scss/layout/_document.scss b/static/css/pico-1.5.9/docs/scss/layout/_document.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/scss/layout/_document.scss rename to static/css/pico-1.5.9/docs/scss/layout/_document.scss diff --git a/AHC_app/static/css/pico-1.5.9/docs/scss/layout/_documentation.scss b/static/css/pico-1.5.9/docs/scss/layout/_documentation.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/scss/layout/_documentation.scss rename to static/css/pico-1.5.9/docs/scss/layout/_documentation.scss diff --git a/AHC_app/static/css/pico-1.5.9/docs/scss/layout/_main.scss b/static/css/pico-1.5.9/docs/scss/layout/_main.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/scss/layout/_main.scss rename to static/css/pico-1.5.9/docs/scss/layout/_main.scss diff --git a/AHC_app/static/css/pico-1.5.9/docs/scss/pico.docs.scss b/static/css/pico-1.5.9/docs/scss/pico.docs.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/scss/pico.docs.scss rename to static/css/pico-1.5.9/docs/scss/pico.docs.scss diff --git a/AHC_app/static/css/pico-1.5.9/docs/scss/themes/_docs.scss b/static/css/pico-1.5.9/docs/scss/themes/_docs.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/scss/themes/_docs.scss rename to static/css/pico-1.5.9/docs/scss/themes/_docs.scss diff --git a/AHC_app/static/css/pico-1.5.9/docs/scss/themes/docs/_dark.scss b/static/css/pico-1.5.9/docs/scss/themes/docs/_dark.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/scss/themes/docs/_dark.scss rename to static/css/pico-1.5.9/docs/scss/themes/docs/_dark.scss diff --git a/AHC_app/static/css/pico-1.5.9/docs/scss/themes/docs/_icons.scss b/static/css/pico-1.5.9/docs/scss/themes/docs/_icons.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/scss/themes/docs/_icons.scss rename to static/css/pico-1.5.9/docs/scss/themes/docs/_icons.scss diff --git a/AHC_app/static/css/pico-1.5.9/docs/scss/themes/docs/_light.scss b/static/css/pico-1.5.9/docs/scss/themes/docs/_light.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/scss/themes/docs/_light.scss rename to static/css/pico-1.5.9/docs/scss/themes/docs/_light.scss diff --git a/AHC_app/static/css/pico-1.5.9/docs/src/_footer.html b/static/css/pico-1.5.9/docs/src/_footer.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/src/_footer.html rename to static/css/pico-1.5.9/docs/src/_footer.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/src/_head.html b/static/css/pico-1.5.9/docs/src/_head.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/src/_head.html rename to static/css/pico-1.5.9/docs/src/_head.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/src/_nav.html b/static/css/pico-1.5.9/docs/src/_nav.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/src/_nav.html rename to static/css/pico-1.5.9/docs/src/_nav.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/src/_sidebar.html b/static/css/pico-1.5.9/docs/src/_sidebar.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/src/_sidebar.html rename to static/css/pico-1.5.9/docs/src/_sidebar.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/src/accordions.html b/static/css/pico-1.5.9/docs/src/accordions.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/src/accordions.html rename to static/css/pico-1.5.9/docs/src/accordions.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/src/buttons.html b/static/css/pico-1.5.9/docs/src/buttons.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/src/buttons.html rename to static/css/pico-1.5.9/docs/src/buttons.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/src/cards.html b/static/css/pico-1.5.9/docs/src/cards.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/src/cards.html rename to static/css/pico-1.5.9/docs/src/cards.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/src/classless.html b/static/css/pico-1.5.9/docs/src/classless.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/src/classless.html rename to static/css/pico-1.5.9/docs/src/classless.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/src/containers.html b/static/css/pico-1.5.9/docs/src/containers.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/src/containers.html rename to static/css/pico-1.5.9/docs/src/containers.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/src/customization.html b/static/css/pico-1.5.9/docs/src/customization.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/src/customization.html rename to static/css/pico-1.5.9/docs/src/customization.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/src/dropdowns.html b/static/css/pico-1.5.9/docs/src/dropdowns.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/src/dropdowns.html rename to static/css/pico-1.5.9/docs/src/dropdowns.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/src/forms.html b/static/css/pico-1.5.9/docs/src/forms.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/src/forms.html rename to static/css/pico-1.5.9/docs/src/forms.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/src/grid.html b/static/css/pico-1.5.9/docs/src/grid.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/src/grid.html rename to static/css/pico-1.5.9/docs/src/grid.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/src/index.html b/static/css/pico-1.5.9/docs/src/index.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/src/index.html rename to static/css/pico-1.5.9/docs/src/index.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/src/loading.html b/static/css/pico-1.5.9/docs/src/loading.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/src/loading.html rename to static/css/pico-1.5.9/docs/src/loading.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/src/modal.html b/static/css/pico-1.5.9/docs/src/modal.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/src/modal.html rename to static/css/pico-1.5.9/docs/src/modal.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/src/navs.html b/static/css/pico-1.5.9/docs/src/navs.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/src/navs.html rename to static/css/pico-1.5.9/docs/src/navs.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/src/progress.html b/static/css/pico-1.5.9/docs/src/progress.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/src/progress.html rename to static/css/pico-1.5.9/docs/src/progress.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/src/rtl.html b/static/css/pico-1.5.9/docs/src/rtl.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/src/rtl.html rename to static/css/pico-1.5.9/docs/src/rtl.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/src/scroller.html b/static/css/pico-1.5.9/docs/src/scroller.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/src/scroller.html rename to static/css/pico-1.5.9/docs/src/scroller.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/src/tables.html b/static/css/pico-1.5.9/docs/src/tables.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/src/tables.html rename to static/css/pico-1.5.9/docs/src/tables.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/src/themes.html b/static/css/pico-1.5.9/docs/src/themes.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/src/themes.html rename to static/css/pico-1.5.9/docs/src/themes.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/src/tooltips.html b/static/css/pico-1.5.9/docs/src/tooltips.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/src/tooltips.html rename to static/css/pico-1.5.9/docs/src/tooltips.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/src/typography.html b/static/css/pico-1.5.9/docs/src/typography.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/src/typography.html rename to static/css/pico-1.5.9/docs/src/typography.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/src/we-love-classes.html b/static/css/pico-1.5.9/docs/src/we-love-classes.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/src/we-love-classes.html rename to static/css/pico-1.5.9/docs/src/we-love-classes.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/tables.html b/static/css/pico-1.5.9/docs/tables.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/tables.html rename to static/css/pico-1.5.9/docs/tables.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/themes.html b/static/css/pico-1.5.9/docs/themes.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/themes.html rename to static/css/pico-1.5.9/docs/themes.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/tooltips.html b/static/css/pico-1.5.9/docs/tooltips.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/tooltips.html rename to static/css/pico-1.5.9/docs/tooltips.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/typography.html b/static/css/pico-1.5.9/docs/typography.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/typography.html rename to static/css/pico-1.5.9/docs/typography.html diff --git a/AHC_app/static/css/pico-1.5.9/docs/we-love-classes.html b/static/css/pico-1.5.9/docs/we-love-classes.html similarity index 100% rename from AHC_app/static/css/pico-1.5.9/docs/we-love-classes.html rename to static/css/pico-1.5.9/docs/we-love-classes.html diff --git a/AHC_app/static/css/pico-1.5.9/package-lock.json b/static/css/pico-1.5.9/package-lock.json similarity index 100% rename from AHC_app/static/css/pico-1.5.9/package-lock.json rename to static/css/pico-1.5.9/package-lock.json diff --git a/AHC_app/static/css/pico-1.5.9/package.json b/static/css/pico-1.5.9/package.json similarity index 100% rename from AHC_app/static/css/pico-1.5.9/package.json rename to static/css/pico-1.5.9/package.json diff --git a/AHC_app/static/css/pico-1.5.9/scss/_functions.scss b/static/css/pico-1.5.9/scss/_functions.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/_functions.scss rename to static/css/pico-1.5.9/scss/_functions.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/_variables.scss b/static/css/pico-1.5.9/scss/_variables.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/_variables.scss rename to static/css/pico-1.5.9/scss/_variables.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/components/_accordion.scss b/static/css/pico-1.5.9/scss/components/_accordion.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/components/_accordion.scss rename to static/css/pico-1.5.9/scss/components/_accordion.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/components/_card.scss b/static/css/pico-1.5.9/scss/components/_card.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/components/_card.scss rename to static/css/pico-1.5.9/scss/components/_card.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/components/_dropdown.scss b/static/css/pico-1.5.9/scss/components/_dropdown.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/components/_dropdown.scss rename to static/css/pico-1.5.9/scss/components/_dropdown.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/components/_modal.scss b/static/css/pico-1.5.9/scss/components/_modal.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/components/_modal.scss rename to static/css/pico-1.5.9/scss/components/_modal.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/components/_nav.scss b/static/css/pico-1.5.9/scss/components/_nav.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/components/_nav.scss rename to static/css/pico-1.5.9/scss/components/_nav.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/components/_progress.scss b/static/css/pico-1.5.9/scss/components/_progress.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/components/_progress.scss rename to static/css/pico-1.5.9/scss/components/_progress.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/content/_button.scss b/static/css/pico-1.5.9/scss/content/_button.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/content/_button.scss rename to static/css/pico-1.5.9/scss/content/_button.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/content/_code.scss b/static/css/pico-1.5.9/scss/content/_code.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/content/_code.scss rename to static/css/pico-1.5.9/scss/content/_code.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/content/_embedded.scss b/static/css/pico-1.5.9/scss/content/_embedded.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/content/_embedded.scss rename to static/css/pico-1.5.9/scss/content/_embedded.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/content/_form-alt-input-types.scss b/static/css/pico-1.5.9/scss/content/_form-alt-input-types.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/content/_form-alt-input-types.scss rename to static/css/pico-1.5.9/scss/content/_form-alt-input-types.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/content/_form-checkbox-radio.scss b/static/css/pico-1.5.9/scss/content/_form-checkbox-radio.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/content/_form-checkbox-radio.scss rename to static/css/pico-1.5.9/scss/content/_form-checkbox-radio.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/content/_form.scss b/static/css/pico-1.5.9/scss/content/_form.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/content/_form.scss rename to static/css/pico-1.5.9/scss/content/_form.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/content/_miscs.scss b/static/css/pico-1.5.9/scss/content/_miscs.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/content/_miscs.scss rename to static/css/pico-1.5.9/scss/content/_miscs.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/content/_table.scss b/static/css/pico-1.5.9/scss/content/_table.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/content/_table.scss rename to static/css/pico-1.5.9/scss/content/_table.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/content/_typography.scss b/static/css/pico-1.5.9/scss/content/_typography.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/content/_typography.scss rename to static/css/pico-1.5.9/scss/content/_typography.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/layout/_container.scss b/static/css/pico-1.5.9/scss/layout/_container.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/layout/_container.scss rename to static/css/pico-1.5.9/scss/layout/_container.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/layout/_document.scss b/static/css/pico-1.5.9/scss/layout/_document.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/layout/_document.scss rename to static/css/pico-1.5.9/scss/layout/_document.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/layout/_grid.scss b/static/css/pico-1.5.9/scss/layout/_grid.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/layout/_grid.scss rename to static/css/pico-1.5.9/scss/layout/_grid.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/layout/_scroller.scss b/static/css/pico-1.5.9/scss/layout/_scroller.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/layout/_scroller.scss rename to static/css/pico-1.5.9/scss/layout/_scroller.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/layout/_section.scss b/static/css/pico-1.5.9/scss/layout/_section.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/layout/_section.scss rename to static/css/pico-1.5.9/scss/layout/_section.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/layout/_sectioning.scss b/static/css/pico-1.5.9/scss/layout/_sectioning.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/layout/_sectioning.scss rename to static/css/pico-1.5.9/scss/layout/_sectioning.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/pico.classless.scss b/static/css/pico-1.5.9/scss/pico.classless.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/pico.classless.scss rename to static/css/pico-1.5.9/scss/pico.classless.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/pico.fluid.classless.scss b/static/css/pico-1.5.9/scss/pico.fluid.classless.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/pico.fluid.classless.scss rename to static/css/pico-1.5.9/scss/pico.fluid.classless.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/pico.scss b/static/css/pico-1.5.9/scss/pico.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/pico.scss rename to static/css/pico-1.5.9/scss/pico.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/pico.slim.scss b/static/css/pico-1.5.9/scss/pico.slim.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/pico.slim.scss rename to static/css/pico-1.5.9/scss/pico.slim.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/postcss.config.js b/static/css/pico-1.5.9/scss/postcss.config.js similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/postcss.config.js rename to static/css/pico-1.5.9/scss/postcss.config.js diff --git a/AHC_app/static/css/pico-1.5.9/scss/themes/default.scss b/static/css/pico-1.5.9/scss/themes/default.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/themes/default.scss rename to static/css/pico-1.5.9/scss/themes/default.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/themes/default/_colors.scss b/static/css/pico-1.5.9/scss/themes/default/_colors.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/themes/default/_colors.scss rename to static/css/pico-1.5.9/scss/themes/default/_colors.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/themes/default/_dark.scss b/static/css/pico-1.5.9/scss/themes/default/_dark.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/themes/default/_dark.scss rename to static/css/pico-1.5.9/scss/themes/default/_dark.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/themes/default/_light.scss b/static/css/pico-1.5.9/scss/themes/default/_light.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/themes/default/_light.scss rename to static/css/pico-1.5.9/scss/themes/default/_light.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/themes/default/_styles.scss b/static/css/pico-1.5.9/scss/themes/default/_styles.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/themes/default/_styles.scss rename to static/css/pico-1.5.9/scss/themes/default/_styles.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/utilities/_accessibility.scss b/static/css/pico-1.5.9/scss/utilities/_accessibility.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/utilities/_accessibility.scss rename to static/css/pico-1.5.9/scss/utilities/_accessibility.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/utilities/_loading.scss b/static/css/pico-1.5.9/scss/utilities/_loading.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/utilities/_loading.scss rename to static/css/pico-1.5.9/scss/utilities/_loading.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/utilities/_reduce-motion.scss b/static/css/pico-1.5.9/scss/utilities/_reduce-motion.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/utilities/_reduce-motion.scss rename to static/css/pico-1.5.9/scss/utilities/_reduce-motion.scss diff --git a/AHC_app/static/css/pico-1.5.9/scss/utilities/_tooltip.scss b/static/css/pico-1.5.9/scss/utilities/_tooltip.scss similarity index 100% rename from AHC_app/static/css/pico-1.5.9/scss/utilities/_tooltip.scss rename to static/css/pico-1.5.9/scss/utilities/_tooltip.scss diff --git a/AHC_app/static/css/stable_grid.css b/static/css/stable_grid.css similarity index 100% rename from AHC_app/static/css/stable_grid.css rename to static/css/stable_grid.css diff --git a/AHC_app/static/css/timeline.css b/static/css/timeline.css similarity index 100% rename from AHC_app/static/css/timeline.css rename to static/css/timeline.css diff --git a/AHC_app/static/custom_pico.scss b/static/custom_pico.scss similarity index 100% rename from AHC_app/static/custom_pico.scss rename to static/custom_pico.scss diff --git a/AHC_app/static/js/expanding_sections.js b/static/js/expanding_sections.js similarity index 100% rename from AHC_app/static/js/expanding_sections.js rename to static/js/expanding_sections.js diff --git a/AHC_app/static/js/hiding_note_fields_in_form.js b/static/js/hiding_note_fields_in_form.js similarity index 100% rename from AHC_app/static/js/hiding_note_fields_in_form.js rename to static/js/hiding_note_fields_in_form.js diff --git a/AHC_app/static/js/hiding_note_fields_in_measurement_form.js b/static/js/hiding_note_fields_in_measurement_form.js similarity index 100% rename from AHC_app/static/js/hiding_note_fields_in_measurement_form.js rename to static/js/hiding_note_fields_in_measurement_form.js diff --git a/AHC_app/static/js/pin_animal.js b/static/js/pin_animal.js similarity index 100% rename from AHC_app/static/js/pin_animal.js rename to static/js/pin_animal.js diff --git a/AHC_app/static/js/timeline.js b/static/js/timeline.js similarity index 100% rename from AHC_app/static/js/timeline.js rename to static/js/timeline.js diff --git a/AHC_app/static/media/background/background-1169534_1920.png b/static/media/background/background-1169534_1920.png similarity index 100% rename from AHC_app/static/media/background/background-1169534_1920.png rename to static/media/background/background-1169534_1920.png diff --git a/AHC_app/static/media/background/black.jpg b/static/media/background/black.jpg similarity index 100% rename from AHC_app/static/media/background/black.jpg rename to static/media/background/black.jpg diff --git a/AHC_app/static/media/background/default_title.jpg b/static/media/background/default_title.jpg similarity index 100% rename from AHC_app/static/media/background/default_title.jpg rename to static/media/background/default_title.jpg diff --git a/AHC_app/static/media/background/lizard2.jpg b/static/media/background/lizard2.jpg similarity index 100% rename from AHC_app/static/media/background/lizard2.jpg rename to static/media/background/lizard2.jpg diff --git a/AHC_app/static/media/icons/chinchilla.png b/static/media/icons/chinchilla.png similarity index 100% rename from AHC_app/static/media/icons/chinchilla.png rename to static/media/icons/chinchilla.png diff --git a/AHC_app/static/media/profile_pics/pet-care-icon.png b/static/media/profile_pics/pet-care-icon.png similarity index 100% rename from AHC_app/static/media/profile_pics/pet-care-icon.png rename to static/media/profile_pics/pet-care-icon.png diff --git a/AHC_app/static/media/profile_pics/pet-care.png b/static/media/profile_pics/pet-care.png similarity index 100% rename from AHC_app/static/media/profile_pics/pet-care.png rename to static/media/profile_pics/pet-care.png diff --git a/AHC_app/static/media/profile_pics/signup.png b/static/media/profile_pics/signup.png similarity index 100% rename from AHC_app/static/media/profile_pics/signup.png rename to static/media/profile_pics/signup.png diff --git a/AHC_app/static/media/profile_pics/signup2.png b/static/media/profile_pics/signup2.png similarity index 100% rename from AHC_app/static/media/profile_pics/signup2.png rename to static/media/profile_pics/signup2.png diff --git a/AHC_app/static/media/readme_examples/Animal profile.png b/static/media/readme_examples/Animal profile.png similarity index 100% rename from AHC_app/static/media/readme_examples/Animal profile.png rename to static/media/readme_examples/Animal profile.png diff --git a/AHC_app/static/media/readme_examples/Diet note details.png b/static/media/readme_examples/Diet note details.png similarity index 100% rename from AHC_app/static/media/readme_examples/Diet note details.png rename to static/media/readme_examples/Diet note details.png diff --git a/AHC_app/static/media/readme_examples/Full timeline of notes.png b/static/media/readme_examples/Full timeline of notes.png similarity index 100% rename from AHC_app/static/media/readme_examples/Full timeline of notes.png rename to static/media/readme_examples/Full timeline of notes.png diff --git a/AHC_app/static/media/readme_examples/User registration.png b/static/media/readme_examples/User registration.png similarity index 100% rename from AHC_app/static/media/readme_examples/User registration.png rename to static/media/readme_examples/User registration.png diff --git a/static_collected/CACHE/css/custom_pico.fc2f6099451a.css b/static_collected/CACHE/css/custom_pico.fc2f6099451a.css new file mode 100644 index 0000000..62dafb0 --- /dev/null +++ b/static_collected/CACHE/css/custom_pico.fc2f6099451a.css @@ -0,0 +1,32 @@ +/*! + * Pico CSS v1.5.9 (https://picocss.com) + * Copyright 2019-2023 - Licensed under MIT + */:root{--font-family: system-ui, -apple-system, "Segoe UI", "Roboto", "Ubuntu", + "Cantarell", "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", + "Segoe UI Symbol", "Noto Color Emoji";--line-height: 1.5;--font-weight: 400;--font-size: 16px;--border-radius: 0.25rem;--border-width: 1px;--outline-width: 3px;--spacing: 1rem;--typography-spacing-vertical: 1.5rem;--block-spacing-vertical: calc(var(--spacing) * 2);--block-spacing-horizontal: var(--spacing);--grid-spacing-vertical: 0;--grid-spacing-horizontal: var(--spacing);--form-element-spacing-vertical: 0.75rem;--form-element-spacing-horizontal: 1rem;--nav-element-spacing-vertical: 1rem;--nav-element-spacing-horizontal: 0.5rem;--nav-link-spacing-vertical: 0.5rem;--nav-link-spacing-horizontal: 0.5rem;--form-label-font-weight: var(--font-weight);--transition: 0.2s ease-in-out;--modal-overlay-backdrop-filter: blur(0.25rem)}@media (min-width: 576px){:root{--font-size: 17px}}@media (min-width: 768px){:root{--font-size: 18px}}@media (min-width: 992px){:root{--font-size: 19px}}@media (min-width: 1200px){:root{--font-size: 20px}}@media (min-width: 576px){body>header,body>main,body>footer,section{--block-spacing-vertical: calc(var(--spacing) * 2.5)}}@media (min-width: 768px){body>header,body>main,body>footer,section{--block-spacing-vertical: calc(var(--spacing) * 3)}}@media (min-width: 992px){body>header,body>main,body>footer,section{--block-spacing-vertical: calc(var(--spacing) * 3.5)}}@media (min-width: 1200px){body>header,body>main,body>footer,section{--block-spacing-vertical: calc(var(--spacing) * 4)}}@media (min-width: 576px){article{--block-spacing-horizontal: calc(var(--spacing) * 1.25)}}@media (min-width: 768px){article{--block-spacing-horizontal: calc(var(--spacing) * 1.5)}}@media (min-width: 992px){article{--block-spacing-horizontal: calc(var(--spacing) * 1.75)}}@media (min-width: 1200px){article{--block-spacing-horizontal: calc(var(--spacing) * 2)}}dialog>article{--block-spacing-vertical: calc(var(--spacing) * 2);--block-spacing-horizontal: var(--spacing)}@media (min-width: 576px){dialog>article{--block-spacing-vertical: calc(var(--spacing) * 2.5);--block-spacing-horizontal: calc(var(--spacing) * 1.25)}}@media (min-width: 768px){dialog>article{--block-spacing-vertical: calc(var(--spacing) * 3);--block-spacing-horizontal: calc(var(--spacing) * 1.5)}}a{--text-decoration: none}a.secondary,a.contrast{--text-decoration: underline}small{--font-size: 0.875em}h1,h2,h3,h4,h5,h6{--font-weight: 700}h1{--font-size: 2rem;--typography-spacing-vertical: 3rem}h2{--font-size: 1.75rem;--typography-spacing-vertical: 2.625rem}h3{--font-size: 1.5rem;--typography-spacing-vertical: 2.25rem}h4{--font-size: 1.25rem;--typography-spacing-vertical: 1.874rem}h5{--font-size: 1.125rem;--typography-spacing-vertical: 1.6875rem}[type="checkbox"],[type="radio"]{--border-width: 2px}[type="checkbox"][role="switch"]{--border-width: 3px}thead th,thead td,tfoot th,tfoot td{--border-width: 3px}:not(thead,tfoot)>*>td{--font-size: 0.875em}pre,code,kbd,samp{--font-family: "Menlo", "Consolas", "Roboto Mono", "Ubuntu Monospace", + "Noto Mono", "Oxygen Mono", "Liberation Mono", monospace, + "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"}kbd{--font-weight: bolder}[data-theme="light"],:root:not([data-theme="dark"]){--background-color: #fff;--color: #415462;--h1-color: #1b2832;--h2-color: #23333e;--h3-color: #2c3d49;--h4-color: #374956;--h5-color: #415462;--h6-color: #998133;--muted-color: #73828c;--muted-border-color: #edf0f3;--primary: #fdd835;--primary-hover: #fbc02d;--primary-focus: rgba(253,216,53,0.125);--primary-inverse: #fff;--secondary: #F0AD05;--secondary-hover: #415462;--secondary-focus: rgba(240,173,5,0.125);--secondary-inverse: #fff;--contrast: #1b2832;--contrast-hover: #000;--contrast-focus: rgba(240,173,5,0.125);--contrast-inverse: #fff;--mark-background-color: #fff2ca;--mark-color: #543a25;--ins-color: #388e3c;--del-color: #c62828;--blockquote-border-color: var(--muted-border-color);--blockquote-footer-color: var(--muted-color);--button-box-shadow: 0 0 0 rgba(0, 0, 0, 0);--button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0);--form-element-background-color: transparent;--form-element-border-color: #a2afb9;--form-element-color: var(--color);--form-element-placeholder-color: var(--muted-color);--form-element-active-background-color: transparent;--form-element-active-border-color: var(--primary);--form-element-focus-color: var(--primary-focus);--form-element-disabled-background-color: #fbc02d;--form-element-disabled-border-color: #a2afb9;--form-element-disabled-opacity: 0.5;--form-element-invalid-border-color: #c62828;--form-element-invalid-active-border-color: #d32f2f;--form-element-invalid-focus-color: rgba(211,47,47,0.125);--form-element-valid-border-color: #388e3c;--form-element-valid-active-border-color: #43a047;--form-element-valid-focus-color: rgba(67,160,71,0.125);--switch-background-color: #bbc6ce;--switch-color: var(--primary-inverse);--switch-checked-background-color: var(--primary);--range-border-color: #fbc02d;--range-active-border-color: #bbc6ce;--range-thumb-border-color: var(--background-color);--range-thumb-color: var(--secondary);--range-thumb-hover-color: var(--secondary-hover);--range-thumb-active-color: var(--primary);--table-border-color: var(--muted-border-color);--table-row-stripped-background-color: #f6f8f9;--code-background-color: #edf0f3;--code-color: var(--muted-color);--code-kbd-background-color: var(--contrast);--code-kbd-color: var(--contrast-inverse);--code-tag-color: #b34d80;--code-property-color: #3d888f;--code-value-color: #986;--code-comment-color: #a2afb9;--accordion-border-color: var(--muted-border-color);--accordion-close-summary-color: var(--color);--accordion-open-summary-color: var(--muted-color);--card-background-color: var(--background-color);--card-border-color: var(--muted-border-color);--card-box-shadow: + .0145rem .029rem .174rem rgba(27,40,50,0.01698), + .0335rem .067rem .402rem rgba(27,40,50,0.024), + .0625rem .125rem .75rem rgba(27,40,50,0.03), + .1125rem .225rem 1.35rem rgba(27,40,50,0.036), + .2085rem .417rem 2.502rem rgba(27,40,50,0.04302), + .5rem 1rem 6rem rgba(27,40,50,0.06), + 0 0 0 0.0625rem rgba(27,40,50,0.015);--card-sectionning-background-color: #fafbfc;--dropdown-background-color: #fafbfc;--dropdown-border-color: #f4d890;--dropdown-box-shadow: var(--card-box-shadow);--dropdown-color: var(--color);--dropdown-hover-background-color: #edf0f3;--modal-overlay-background-color: rgba(251,192,45,0.7);--progress-background-color: #fbc02d;--progress-color: var(--primary);--loading-spinner-opacity: 0.5;--tooltip-background-color: var(--contrast);--tooltip-color: var(--contrast-inverse);--icon-checkbox: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(65.28, 84.32, 97.92)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron-button: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron-button-inverse: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-close: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(114.75, 129.625, 140.25)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E");--icon-date: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(65.28, 84.32, 97.92)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");--icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(198, 40, 40)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E");--icon-minus: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'%3E%3C/line%3E%3C/svg%3E");--icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(65.28, 84.32, 97.92)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E");--icon-time: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(65.28, 84.32, 97.92)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E");--icon-valid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(56, 142, 60)' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");color-scheme:light}@media only screen and (prefers-color-scheme: dark){:root:not([data-theme]){--background-color: #11191f;--color: #bbc6ce;--h1-color: #edf0f3;--h2-color: #f4d890;--h3-color: #fbc02d;--h4-color: #dbc37d;--h5-color: #bbc6ce;--h6-color: #aebbc3;--muted-color: #73828c;--muted-border-color: #1f2d38;--primary: #fdd835;--primary-hover: #ffeb3b;--primary-focus: rgba(253,216,53,0.25);--primary-inverse: #fff;--secondary: #F0AD05;--secondary-hover: #73828c;--secondary-focus: rgba(115,130,140,0.25);--secondary-inverse: #fff;--contrast: #edf0f3;--contrast-hover: #fff;--contrast-focus: rgba(115,130,140,0.25);--contrast-inverse: #000;--mark-background-color: #d0c284;--mark-color: #11191f;--ins-color: #388e3c;--del-color: #c62828;--blockquote-border-color: var(--muted-border-color);--blockquote-footer-color: var(--muted-color);--button-box-shadow: 0 0 0 rgba(0, 0, 0, 0);--button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0);--form-element-background-color: #11191f;--form-element-border-color: #374956;--form-element-color: var(--color);--form-element-placeholder-color: var(--muted-color);--form-element-active-background-color: var(--form-element-background-color);--form-element-active-border-color: var(--primary);--form-element-focus-color: var(--primary-focus);--form-element-disabled-background-color: #2c3d49;--form-element-disabled-border-color: #415462;--form-element-disabled-opacity: 0.5;--form-element-invalid-border-color: #b71c1c;--form-element-invalid-active-border-color: #c62828;--form-element-invalid-focus-color: rgba(198,40,40,0.25);--form-element-valid-border-color: #2e7d32;--form-element-valid-active-border-color: #388e3c;--form-element-valid-focus-color: rgba(56,142,60,0.25);--switch-background-color: #374956;--switch-color: var(--primary-inverse);--switch-checked-background-color: var(--primary);--range-border-color: #23333e;--range-active-border-color: #2c3d49;--range-thumb-border-color: var(--background-color);--range-thumb-color: var(--secondary);--range-thumb-hover-color: var(--secondary-hover);--range-thumb-active-color: var(--primary);--table-border-color: var(--muted-border-color);--table-row-stripped-background-color: rgba(115,130,140,0.05);--code-background-color: #17232c;--code-color: var(--muted-color);--code-kbd-background-color: var(--contrast);--code-kbd-color: var(--contrast-inverse);--code-tag-color: #a65980;--code-property-color: #599fa6;--code-value-color: #8c8473;--code-comment-color: #998133;--accordion-border-color: var(--muted-border-color);--accordion-active-summary-color: var(--primary);--accordion-close-summary-color: var(--color);--accordion-open-summary-color: var(--muted-color);--card-background-color: #141e25;--card-border-color: var(--card-background-color);--card-box-shadow: + .0145rem .029rem .174rem rgba(0,0,0,0.01698), + .0335rem .067rem .402rem rgba(0,0,0,0.024), + .0625rem .125rem .75rem rgba(0,0,0,0.03), + .1125rem .225rem 1.35rem rgba(0,0,0,0.036), + .2085rem .417rem 2.502rem rgba(0,0,0,0.04302), + .5rem 1rem 6rem rgba(0,0,0,0.06), + 0 0 0 0.0625rem rgba(0,0,0,0.015);--card-sectionning-background-color: #17232c;--dropdown-background-color: #1b2832;--dropdown-border-color: #23333e;--dropdown-box-shadow: var(--card-box-shadow);--dropdown-color: var(--color);--dropdown-hover-background-color: rgba(35,51,62,0.75);--modal-overlay-background-color: rgba(35,51,62,0.8);--progress-background-color: #23333e;--progress-color: var(--primary);--loading-spinner-opacity: 0.5;--tooltip-background-color: var(--contrast);--tooltip-color: var(--contrast-inverse);--icon-checkbox: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(161.976, 175.304, 184.824)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron-button: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron-button-inverse: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(0, 0, 0)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-close: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(114.75, 129.625, 140.25)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E");--icon-date: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(161.976, 175.304, 184.824)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");--icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(183, 28, 28)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E");--icon-minus: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'%3E%3C/line%3E%3C/svg%3E");--icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(161.976, 175.304, 184.824)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E");--icon-time: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(161.976, 175.304, 184.824)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E");--icon-valid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(46, 125, 50)' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");color-scheme:dark}}[data-theme="dark"]{--background-color: #11191f;--color: #bbc6ce;--h1-color: #edf0f3;--h2-color: #f4d890;--h3-color: #fbc02d;--h4-color: #dbc37d;--h5-color: #bbc6ce;--h6-color: #aebbc3;--muted-color: #73828c;--muted-border-color: #1f2d38;--primary: #fdd835;--primary-hover: #ffeb3b;--primary-focus: rgba(253,216,53,0.25);--primary-inverse: #fff;--secondary: #F0AD05;--secondary-hover: #73828c;--secondary-focus: rgba(115,130,140,0.25);--secondary-inverse: #fff;--contrast: #edf0f3;--contrast-hover: #fff;--contrast-focus: rgba(115,130,140,0.25);--contrast-inverse: #000;--mark-background-color: #d0c284;--mark-color: #11191f;--ins-color: #388e3c;--del-color: #c62828;--blockquote-border-color: var(--muted-border-color);--blockquote-footer-color: var(--muted-color);--button-box-shadow: 0 0 0 rgba(0, 0, 0, 0);--button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0);--form-element-background-color: #11191f;--form-element-border-color: #374956;--form-element-color: var(--color);--form-element-placeholder-color: var(--muted-color);--form-element-active-background-color: var(--form-element-background-color);--form-element-active-border-color: var(--primary);--form-element-focus-color: var(--primary-focus);--form-element-disabled-background-color: #2c3d49;--form-element-disabled-border-color: #415462;--form-element-disabled-opacity: 0.5;--form-element-invalid-border-color: #b71c1c;--form-element-invalid-active-border-color: #c62828;--form-element-invalid-focus-color: rgba(198,40,40,0.25);--form-element-valid-border-color: #2e7d32;--form-element-valid-active-border-color: #388e3c;--form-element-valid-focus-color: rgba(56,142,60,0.25);--switch-background-color: #374956;--switch-color: var(--primary-inverse);--switch-checked-background-color: var(--primary);--range-border-color: #23333e;--range-active-border-color: #2c3d49;--range-thumb-border-color: var(--background-color);--range-thumb-color: var(--secondary);--range-thumb-hover-color: var(--secondary-hover);--range-thumb-active-color: var(--primary);--table-border-color: var(--muted-border-color);--table-row-stripped-background-color: rgba(115,130,140,0.05);--code-background-color: #17232c;--code-color: var(--muted-color);--code-kbd-background-color: var(--contrast);--code-kbd-color: var(--contrast-inverse);--code-tag-color: #a65980;--code-property-color: #599fa6;--code-value-color: #8c8473;--code-comment-color: #998133;--accordion-border-color: var(--muted-border-color);--accordion-active-summary-color: var(--primary);--accordion-close-summary-color: var(--color);--accordion-open-summary-color: var(--muted-color);--card-background-color: #141e25;--card-border-color: var(--card-background-color);--card-box-shadow: + .0145rem .029rem .174rem rgba(0,0,0,0.01698), + .0335rem .067rem .402rem rgba(0,0,0,0.024), + .0625rem .125rem .75rem rgba(0,0,0,0.03), + .1125rem .225rem 1.35rem rgba(0,0,0,0.036), + .2085rem .417rem 2.502rem rgba(0,0,0,0.04302), + .5rem 1rem 6rem rgba(0,0,0,0.06), + 0 0 0 0.0625rem rgba(0,0,0,0.015);--card-sectionning-background-color: #17232c;--dropdown-background-color: #1b2832;--dropdown-border-color: #23333e;--dropdown-box-shadow: var(--card-box-shadow);--dropdown-color: var(--color);--dropdown-hover-background-color: rgba(35,51,62,0.75);--modal-overlay-background-color: rgba(35,51,62,0.8);--progress-background-color: #23333e;--progress-color: var(--primary);--loading-spinner-opacity: 0.5;--tooltip-background-color: var(--contrast);--tooltip-color: var(--contrast-inverse);--icon-checkbox: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(161.976, 175.304, 184.824)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron-button: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-chevron-button-inverse: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(0, 0, 0)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");--icon-close: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(114.75, 129.625, 140.25)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E");--icon-date: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(161.976, 175.304, 184.824)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");--icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(183, 28, 28)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E");--icon-minus: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'%3E%3C/line%3E%3C/svg%3E");--icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(161.976, 175.304, 184.824)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E");--icon-time: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(161.976, 175.304, 184.824)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E");--icon-valid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(46, 125, 50)' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");color-scheme:dark}progress,[type="checkbox"],[type="radio"],[type="range"]{accent-color:var(--primary)}*,*::before,*::after{box-sizing:border-box;background-repeat:no-repeat}::before,::after{text-decoration:inherit;vertical-align:inherit}:where(:root){-webkit-tap-highlight-color:transparent;-webkit-text-size-adjust:100%;text-size-adjust:100%;background-color:var(--background-color);color:var(--color);font-weight:var(--font-weight);font-size:var(--font-size);line-height:var(--line-height);font-family:var(--font-family);text-rendering:optimizeLegibility;overflow-wrap:break-word;cursor:default;tab-size:4}main{display:block}body{width:100%;margin:0}body>header,body>main,body>footer{width:100%;margin-right:auto;margin-left:auto;padding:var(--block-spacing-vertical) 0}.container,.container-fluid{width:100%;margin-right:auto;margin-left:auto;padding-right:var(--spacing);padding-left:var(--spacing)}@media (min-width: 576px){.container{max-width:510px;padding-right:0;padding-left:0}}@media (min-width: 768px){.container{max-width:700px}}@media (min-width: 992px){.container{max-width:920px}}@media (min-width: 1200px){.container{max-width:1130px}}section{margin-bottom:var(--block-spacing-vertical)}.grid{grid-column-gap:var(--grid-spacing-horizontal);grid-row-gap:var(--grid-spacing-vertical);display:grid;grid-template-columns:1fr;margin:0}@media (min-width: 992px){.grid{grid-template-columns:repeat(auto-fit, minmax(0%, 1fr))}}.grid>*{min-width:0}figure{display:block;margin:0;padding:0;overflow-x:auto}figure figcaption{padding:calc(var(--spacing) * 0.5) 0;color:var(--muted-color)}b,strong{font-weight:bolder}sub,sup{position:relative;font-size:0.75em;line-height:0;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}address,blockquote,dl,figure,form,ol,p,pre,table,ul{margin-top:0;margin-bottom:var(--typography-spacing-vertical);color:var(--color);font-style:normal;font-weight:var(--font-weight);font-size:var(--font-size)}a,[role="link"]{--color: var(--primary);--background-color: transparent;outline:none;background-color:var(--background-color);color:var(--color);text-decoration:var(--text-decoration);transition:background-color var(--transition),color var(--transition),text-decoration var(--transition),box-shadow var(--transition)}a:is([aria-current], :hover, :active, :focus),[role="link"]:is([aria-current], :hover, :active, :focus){--color: var(--primary-hover);--text-decoration: underline}a:focus,[role="link"]:focus{--background-color: var(--primary-focus)}a.secondary,[role="link"].secondary{--color: var(--secondary)}a.secondary:is([aria-current], :hover, :active, :focus),[role="link"].secondary:is([aria-current], :hover, :active, :focus){--color: var(--secondary-hover)}a.secondary:focus,[role="link"].secondary:focus{--background-color: var(--secondary-focus)}a.contrast,[role="link"].contrast{--color: var(--contrast)}a.contrast:is([aria-current], :hover, :active, :focus),[role="link"].contrast:is([aria-current], :hover, :active, :focus){--color: var(--contrast-hover)}a.contrast:focus,[role="link"].contrast:focus{--background-color: var(--contrast-focus)}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:var(--typography-spacing-vertical);color:var(--color);font-weight:var(--font-weight);font-size:var(--font-size);font-family:var(--font-family)}h1{--color: var(--h1-color)}h2{--color: var(--h2-color)}h3{--color: var(--h3-color)}h4{--color: var(--h4-color)}h5{--color: var(--h5-color)}h6{--color: var(--h6-color)}:where(address, blockquote, dl, figure, form, ol, p, pre, table, ul)~:is(h1, h2, h3, h4, h5, h6){margin-top:var(--typography-spacing-vertical)}hgroup,.headings{margin-bottom:var(--typography-spacing-vertical)}hgroup>*,.headings>*{margin-bottom:0}hgroup>*:last-child,.headings>*:last-child{--color: var(--muted-color);--font-weight: unset;font-size:1rem;font-family:unset}p{margin-bottom:var(--typography-spacing-vertical)}small{font-size:var(--font-size)}:where(dl, ol, ul){padding-right:0;padding-left:var(--spacing);padding-inline-start:var(--spacing);padding-inline-end:0}:where(dl, ol, ul) li{margin-bottom:calc(var(--typography-spacing-vertical) * 0.25)}:where(dl, ol, ul) :is(dl, ol, ul){margin:0;margin-top:calc(var(--typography-spacing-vertical) * 0.25)}ul li{list-style:square}mark{padding:0.125rem 0.25rem;background-color:var(--mark-background-color);color:var(--mark-color);vertical-align:baseline}blockquote{display:block;margin:var(--typography-spacing-vertical) 0;padding:var(--spacing);border-right:none;border-left:0.25rem solid var(--blockquote-border-color);border-inline-start:0.25rem solid var(--blockquote-border-color);border-inline-end:none}blockquote footer{margin-top:calc(var(--typography-spacing-vertical) * 0.5);color:var(--blockquote-footer-color)}abbr[title]{border-bottom:1px dotted;text-decoration:none;cursor:help}ins{color:var(--ins-color);text-decoration:none}del{color:var(--del-color)}::selection{background-color:var(--primary-focus)}:where(audio, canvas, iframe, img, svg, video){vertical-align:middle}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}:where(iframe){border-style:none}img{max-width:100%;height:auto;border-style:none}:where(svg:not([fill])){fill:currentColor}svg:not(:root){overflow:hidden}button{margin:0;overflow:visible;font-family:inherit;text-transform:none}button,[type="button"],[type="reset"],[type="submit"]{-webkit-appearance:button}button{display:block;width:100%;margin-bottom:var(--spacing)}[role="button"]{display:inline-block;text-decoration:none}button,input[type="submit"],input[type="button"],input[type="reset"],[role="button"]{--background-color: var(--primary);--border-color: var(--primary);--color: var(--primary-inverse);--box-shadow: var(--button-box-shadow, 0 0 0 rgba(0, 0, 0, 0));padding:var(--form-element-spacing-vertical) var(--form-element-spacing-horizontal);border:var(--border-width) solid var(--border-color);border-radius:var(--border-radius);outline:none;background-color:var(--background-color);box-shadow:var(--box-shadow);color:var(--color);font-weight:var(--font-weight);font-size:1rem;line-height:var(--line-height);text-align:center;cursor:pointer;transition:background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)}button:is([aria-current], :hover, :active, :focus),input[type="submit"]:is([aria-current], :hover, :active, :focus),input[type="button"]:is([aria-current], :hover, :active, :focus),input[type="reset"]:is([aria-current], :hover, :active, :focus),[role="button"]:is([aria-current], :hover, :active, :focus){--background-color: var(--primary-hover);--border-color: var(--primary-hover);--box-shadow: var(--button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0));--color: var(--primary-inverse)}button:focus,input[type="submit"]:focus,input[type="button"]:focus,input[type="reset"]:focus,[role="button"]:focus{--box-shadow: var(--button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), + 0 0 0 var(--outline-width) var(--primary-focus)}:is(button, input[type="submit"], input[type="button"], [role="button"]).secondary,input[type="reset"]{--background-color: var(--secondary);--border-color: var(--secondary);--color: var(--secondary-inverse);cursor:pointer}:is(button, input[type="submit"], input[type="button"], [role="button"]).secondary:is([aria-current], :hover, :active, :focus),input[type="reset"]:is([aria-current], :hover, :active, :focus){--background-color: var(--secondary-hover);--border-color: var(--secondary-hover);--color: var(--secondary-inverse)}:is(button, input[type="submit"], input[type="button"], [role="button"]).secondary:focus,input[type="reset"]:focus{--box-shadow: var(--button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), + 0 0 0 var(--outline-width) var(--secondary-focus)}:is(button, input[type="submit"], input[type="button"], [role="button"]).contrast{--background-color: var(--contrast);--border-color: var(--contrast);--color: var(--contrast-inverse)}:is(button, input[type="submit"], input[type="button"], [role="button"]).contrast:is([aria-current], :hover, :active, :focus){--background-color: var(--contrast-hover);--border-color: var(--contrast-hover);--color: var(--contrast-inverse)}:is(button, input[type="submit"], input[type="button"], [role="button"]).contrast:focus{--box-shadow: var(--button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), + 0 0 0 var(--outline-width) var(--contrast-focus)}:is(button, input[type="submit"], input[type="button"], [role="button"]).outline,input[type="reset"].outline{--background-color: transparent;--color: var(--primary)}:is(button, input[type="submit"], input[type="button"], [role="button"]).outline:is([aria-current], :hover, :active, :focus),input[type="reset"].outline:is([aria-current], :hover, :active, :focus){--background-color: transparent;--color: var(--primary-hover)}:is(button, input[type="submit"], input[type="button"], [role="button"]).outline.secondary,input[type="reset"].outline{--color: var(--secondary)}:is(button, input[type="submit"], input[type="button"], [role="button"]).outline.secondary:is([aria-current], :hover, :active, :focus),input[type="reset"].outline:is([aria-current], :hover, :active, :focus){--color: var(--secondary-hover)}:is(button, input[type="submit"], input[type="button"], [role="button"]).outline.contrast{--color: var(--contrast)}:is(button, input[type="submit"], input[type="button"], [role="button"]).outline.contrast:is([aria-current], :hover, :active, :focus){--color: var(--contrast-hover)}:where(button, [type="submit"], [type="button"], [type="reset"], [role="button"])[disabled],:where(fieldset[disabled]) :is(button, [type="submit"], [type="button"], [type="reset"], [role="button"]),a[role="button"]:not([href]){opacity:0.5;pointer-events:none}input,optgroup,select,textarea{margin:0;font-size:1rem;line-height:var(--line-height);font-family:inherit;letter-spacing:inherit}input{overflow:visible}select{text-transform:none}legend{max-width:100%;padding:0;color:inherit;white-space:normal}textarea{overflow:auto}[type="checkbox"],[type="radio"]{padding:0}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}::-moz-focus-inner{padding:0;border-style:none}:-moz-focusring{outline:none}:-moz-ui-invalid{box-shadow:none}::-ms-expand{display:none}[type="file"],[type="range"]{padding:0;border-width:0}input:not([type="checkbox"],[type="radio"],[type="range"]){height:calc( (1rem * var(--line-height)) + (var(--form-element-spacing-vertical) * 2) + (var(--border-width) * 2))}fieldset{margin:0;margin-bottom:var(--spacing);padding:0;border:0}label,fieldset legend{display:block;margin-bottom:calc(var(--spacing) * 0.25);font-weight:var(--form-label-font-weight, var(--font-weight))}input:not([type="checkbox"],[type="radio"]),select,textarea{width:100%}input:not([type="checkbox"],[type="radio"],[type="range"],[type="file"]),select,textarea{appearance:none;padding:var(--form-element-spacing-vertical) var(--form-element-spacing-horizontal)}input,select,textarea{--background-color: var(--form-element-background-color);--border-color: var(--form-element-border-color);--color: var(--form-element-color);--box-shadow: none;border:var(--border-width) solid var(--border-color);border-radius:var(--border-radius);outline:none;background-color:var(--background-color);box-shadow:var(--box-shadow);color:var(--color);font-weight:var(--font-weight);transition:background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)}input:not([type="submit"],[type="button"],[type="reset"],[type="checkbox"],[type="radio"],[readonly]):is(:active, :focus),:where(select, textarea):is(:active, :focus){--background-color: var(--form-element-active-background-color)}input:not([type="submit"],[type="button"],[type="reset"],[role="switch"],[readonly]):is(:active, :focus),:where(select, textarea):is(:active, :focus){--border-color: var(--form-element-active-border-color)}input:not([type="submit"],[type="button"],[type="reset"],[type="range"],[type="file"],[readonly]):focus,select:focus,textarea:focus{--box-shadow: 0 0 0 var(--outline-width) var(--form-element-focus-color)}input:not([type="submit"],[type="button"],[type="reset"])[disabled],select[disabled],textarea[disabled],:where(fieldset[disabled]) :is(input:not([type="submit"], [type="button"], [type="reset"]), select, textarea){--background-color: var(--form-element-disabled-background-color);--border-color: var(--form-element-disabled-border-color);opacity:var(--form-element-disabled-opacity);pointer-events:none}:where(input, select, textarea):not([type="checkbox"],[type="radio"],[type="date"],[type="datetime-local"],[type="month"],[type="time"],[type="week"])[aria-invalid]{padding-right:calc( var(--form-element-spacing-horizontal) + 1.5rem) !important;padding-left:var(--form-element-spacing-horizontal);padding-inline-start:var(--form-element-spacing-horizontal) !important;padding-inline-end:calc( var(--form-element-spacing-horizontal) + 1.5rem) !important;background-position:center right 0.75rem;background-size:1rem auto;background-repeat:no-repeat}:where(input, select, textarea):not([type="checkbox"],[type="radio"],[type="date"],[type="datetime-local"],[type="month"],[type="time"],[type="week"])[aria-invalid="false"]{background-image:var(--icon-valid)}:where(input, select, textarea):not([type="checkbox"],[type="radio"],[type="date"],[type="datetime-local"],[type="month"],[type="time"],[type="week"])[aria-invalid="true"]{background-image:var(--icon-invalid)}:where(input, select, textarea)[aria-invalid="false"]{--border-color: var(--form-element-valid-border-color)}:where(input, select, textarea)[aria-invalid="false"]:is(:active, :focus){--border-color: var(--form-element-valid-active-border-color) !important;--box-shadow: 0 0 0 var(--outline-width) var(--form-element-valid-focus-color) !important}:where(input, select, textarea)[aria-invalid="true"]{--border-color: var(--form-element-invalid-border-color)}:where(input, select, textarea)[aria-invalid="true"]:is(:active, :focus){--border-color: var(--form-element-invalid-active-border-color) !important;--box-shadow: 0 0 0 var(--outline-width) var(--form-element-invalid-focus-color) !important}[dir="rtl"] :where(input, select, textarea):not([type="checkbox"],[type="radio"]):is([aria-invalid], [aria-invalid="true"], [aria-invalid="false"] ){background-position:center left 0.75rem}input::placeholder,input::-webkit-input-placeholder,textarea::placeholder,textarea::-webkit-input-placeholder,select:invalid{color:var(--form-element-placeholder-color);opacity:1}input:not([type="checkbox"],[type="radio"]),select,textarea{margin-bottom:var(--spacing)}select::-ms-expand{border:0;background-color:transparent}select:not([multiple],[size]){padding-right:calc(var(--form-element-spacing-horizontal) + 1.5rem);padding-left:var(--form-element-spacing-horizontal);padding-inline-start:var(--form-element-spacing-horizontal);padding-inline-end:calc(var(--form-element-spacing-horizontal) + 1.5rem);background-image:var(--icon-chevron);background-position:center right 0.75rem;background-size:1rem auto;background-repeat:no-repeat}[dir="rtl"] select:not([multiple],[size]){background-position:center left 0.75rem}:where(input, select, textarea, .grid)+small{display:block;width:100%;margin-top:calc(var(--spacing) * -0.75);margin-bottom:var(--spacing);color:var(--muted-color)}label>:where(input, select, textarea){margin-top:calc(var(--spacing) * 0.25)}[type="checkbox"],[type="radio"]{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:1.25em;height:1.25em;margin-top:-0.125em;margin-right:0.375em;margin-left:0;margin-inline-start:0;margin-inline-end:0.375em;border-width:var(--border-width);font-size:inherit;vertical-align:middle;cursor:pointer}[type="checkbox"]::-ms-check,[type="radio"]::-ms-check{display:none}[type="checkbox"]:checked,[type="checkbox"]:checked:active,[type="checkbox"]:checked:focus,[type="radio"]:checked,[type="radio"]:checked:active,[type="radio"]:checked:focus{--background-color: var(--primary);--border-color: var(--primary);background-image:var(--icon-checkbox);background-position:center;background-size:0.75em auto;background-repeat:no-repeat}[type="checkbox"]~label,[type="radio"]~label{display:inline-block;margin-right:0.375em;margin-bottom:0;cursor:pointer}[type="checkbox"]:indeterminate{--background-color: var(--primary);--border-color: var(--primary);background-image:var(--icon-minus);background-position:center;background-size:0.75em auto;background-repeat:no-repeat}[type="radio"]{border-radius:50%}[type="radio"]:checked,[type="radio"]:checked:active,[type="radio"]:checked:focus{--background-color: var(--primary-inverse);border-width:0.35em;background-image:none}[type="checkbox"][role="switch"]{--background-color: var(--switch-background-color);--border-color: var(--switch-background-color);--color: var(--switch-color);width:2.25em;height:1.25em;border:var(--border-width) solid var(--border-color);border-radius:1.25em;background-color:var(--background-color);line-height:1.25em}[type="checkbox"][role="switch"]:focus{--background-color: var(--switch-background-color);--border-color: var(--switch-background-color)}[type="checkbox"][role="switch"]:checked{--background-color: var(--switch-checked-background-color);--border-color: var(--switch-checked-background-color)}[type="checkbox"][role="switch"]:before{display:block;width:calc(1.25em - (var(--border-width) * 2));height:100%;border-radius:50%;background-color:var(--color);content:"";transition:margin 0.1s ease-in-out}[type="checkbox"][role="switch"]:checked{background-image:none}[type="checkbox"][role="switch"]:checked::before{margin-left:calc(1.125em - var(--border-width));margin-inline-start:calc(1.125em - var(--border-width))}[type="checkbox"][aria-invalid="false"],[type="checkbox"]:checked[aria-invalid="false"],[type="radio"][aria-invalid="false"],[type="radio"]:checked[aria-invalid="false"],[type="checkbox"][role="switch"][aria-invalid="false"],[type="checkbox"][role="switch"]:checked[aria-invalid="false"]{--border-color: var(--form-element-valid-border-color)}[type="checkbox"][aria-invalid="true"],[type="checkbox"]:checked[aria-invalid="true"],[type="radio"][aria-invalid="true"],[type="radio"]:checked[aria-invalid="true"],[type="checkbox"][role="switch"][aria-invalid="true"],[type="checkbox"][role="switch"]:checked[aria-invalid="true"]{--border-color: var(--form-element-invalid-border-color)}[type="color"]::-webkit-color-swatch-wrapper{padding:0}[type="color"]::-moz-focus-inner{padding:0}[type="color"]::-webkit-color-swatch{border:0;border-radius:calc(var(--border-radius) * 0.5)}[type="color"]::-moz-color-swatch{border:0;border-radius:calc(var(--border-radius) * 0.5)}input:not([type="checkbox"],[type="radio"],[type="range"],[type="file"]):is([type="date"], [type="datetime-local"], [type="month"], [type="time"], [type="week"]){--icon-position: 0.75rem;--icon-width: 1rem;padding-right:calc(var(--icon-width) + var(--icon-position));background-image:var(--icon-date);background-position:center right var(--icon-position);background-size:var(--icon-width) auto;background-repeat:no-repeat}input:not([type="checkbox"],[type="radio"],[type="range"],[type="file"])[type="time"]{background-image:var(--icon-time)}[type="date"]::-webkit-calendar-picker-indicator,[type="datetime-local"]::-webkit-calendar-picker-indicator,[type="month"]::-webkit-calendar-picker-indicator,[type="time"]::-webkit-calendar-picker-indicator,[type="week"]::-webkit-calendar-picker-indicator{width:var(--icon-width);margin-right:calc(var(--icon-width) * -1);margin-left:var(--icon-position);opacity:0}[dir="rtl"] :is([type="date"], [type="datetime-local"], [type="month"], [type="time"], [type="week"]){text-align:right}[type="file"]{--color: var(--muted-color);padding:calc(var(--form-element-spacing-vertical) * 0.5) 0;border:0;border-radius:0;background:none}[type="file"]::file-selector-button{--background-color: var(--secondary);--border-color: var(--secondary);--color: var(--secondary-inverse);margin-right:calc(var(--spacing) / 2);margin-left:0;margin-inline-start:0;margin-inline-end:calc(var(--spacing) / 2);padding:calc(var(--form-element-spacing-vertical) * 0.5) calc(var(--form-element-spacing-horizontal) * 0.5);border:var(--border-width) solid var(--border-color);border-radius:var(--border-radius);outline:none;background-color:var(--background-color);box-shadow:var(--box-shadow);color:var(--color);font-weight:var(--font-weight);font-size:1rem;line-height:var(--line-height);text-align:center;cursor:pointer;transition:background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)}[type="file"]::file-selector-button:is(:hover, :active, :focus){--background-color: var(--secondary-hover);--border-color: var(--secondary-hover)}[type="file"]::-webkit-file-upload-button{--background-color: var(--secondary);--border-color: var(--secondary);--color: var(--secondary-inverse);margin-right:calc(var(--spacing) / 2);margin-left:0;margin-inline-start:0;margin-inline-end:calc(var(--spacing) / 2);padding:calc(var(--form-element-spacing-vertical) * 0.5) calc(var(--form-element-spacing-horizontal) * 0.5);border:var(--border-width) solid var(--border-color);border-radius:var(--border-radius);outline:none;background-color:var(--background-color);box-shadow:var(--box-shadow);color:var(--color);font-weight:var(--font-weight);font-size:1rem;line-height:var(--line-height);text-align:center;cursor:pointer;transition:background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)}[type="file"]::-webkit-file-upload-button:is(:hover, :active, :focus){--background-color: var(--secondary-hover);--border-color: var(--secondary-hover)}[type="file"]::-ms-browse{--background-color: var(--secondary);--border-color: var(--secondary);--color: var(--secondary-inverse);margin-right:calc(var(--spacing) / 2);margin-left:0;margin-inline-start:0;margin-inline-end:calc(var(--spacing) / 2);padding:calc(var(--form-element-spacing-vertical) * 0.5) calc(var(--form-element-spacing-horizontal) * 0.5);border:var(--border-width) solid var(--border-color);border-radius:var(--border-radius);outline:none;background-color:var(--background-color);box-shadow:var(--box-shadow);color:var(--color);font-weight:var(--font-weight);font-size:1rem;line-height:var(--line-height);text-align:center;cursor:pointer;transition:background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)}[type="file"]::-ms-browse:is(:hover, :active, :focus){--background-color: var(--secondary-hover);--border-color: var(--secondary-hover)}[type="range"]{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:100%;height:1.25rem;background:none}[type="range"]::-webkit-slider-runnable-track{width:100%;height:.25rem;border-radius:var(--border-radius);background-color:var(--range-border-color);transition:background-color var(--transition),box-shadow var(--transition)}[type="range"]::-moz-range-track{width:100%;height:.25rem;border-radius:var(--border-radius);background-color:var(--range-border-color);transition:background-color var(--transition),box-shadow var(--transition)}[type="range"]::-ms-track{width:100%;height:.25rem;border-radius:var(--border-radius);background-color:var(--range-border-color);transition:background-color var(--transition),box-shadow var(--transition)}[type="range"]::-webkit-slider-thumb{-webkit-appearance:none;width:1.25rem;height:1.25rem;margin-top:-.5rem;border:2px solid var(--range-thumb-border-color);border-radius:50%;background-color:var(--range-thumb-color);cursor:pointer;transition:background-color var(--transition),transform var(--transition)}[type="range"]::-moz-range-thumb{-webkit-appearance:none;width:1.25rem;height:1.25rem;margin-top:-.5rem;border:2px solid var(--range-thumb-border-color);border-radius:50%;background-color:var(--range-thumb-color);cursor:pointer;transition:background-color var(--transition),transform var(--transition)}[type="range"]::-ms-thumb{-webkit-appearance:none;width:1.25rem;height:1.25rem;margin-top:-.5rem;border:2px solid var(--range-thumb-border-color);border-radius:50%;background-color:var(--range-thumb-color);cursor:pointer;transition:background-color var(--transition),transform var(--transition)}[type="range"]:hover,[type="range"]:focus{--range-border-color: var(--range-active-border-color);--range-thumb-color: var(--range-thumb-hover-color)}[type="range"]:active{--range-thumb-color: var(--range-thumb-active-color)}[type="range"]:active::-webkit-slider-thumb{transform:scale(1.25)}[type="range"]:active::-moz-range-thumb{transform:scale(1.25)}[type="range"]:active::-ms-thumb{transform:scale(1.25)}input:not([type="checkbox"],[type="radio"],[type="range"],[type="file"])[type="search"]{padding-inline-start:calc(var(--form-element-spacing-horizontal) + 1.75rem);border-radius:5rem;background-image:var(--icon-search);background-position:center left 1.125rem;background-size:1rem auto;background-repeat:no-repeat}input:not([type="checkbox"],[type="radio"],[type="range"],[type="file"])[type="search"][aria-invalid]{padding-inline-start:calc(var(--form-element-spacing-horizontal) + 1.75rem) !important;background-position:center left 1.125rem, center right 0.75rem}input:not([type="checkbox"],[type="radio"],[type="range"],[type="file"])[type="search"][aria-invalid="false"]{background-image:var(--icon-search),var(--icon-valid)}input:not([type="checkbox"],[type="radio"],[type="range"],[type="file"])[type="search"][aria-invalid="true"]{background-image:var(--icon-search),var(--icon-invalid)}[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none;display:none}[dir="rtl"] :where(input):not([type="checkbox"],[type="radio"],[type="range"],[type="file"])[type="search"]{background-position:center right 1.125rem}[dir="rtl"] :where(input):not([type="checkbox"],[type="radio"],[type="range"],[type="file"])[type="search"][aria-invalid]{background-position:center right 1.125rem, center left 0.75rem}:where(table){width:100%;border-collapse:collapse;border-spacing:0;text-indent:0}th,td{padding:calc(var(--spacing) / 2) var(--spacing);border-bottom:var(--border-width) solid var(--table-border-color);color:var(--color);font-weight:var(--font-weight);font-size:var(--font-size);text-align:left;text-align:start}tfoot th,tfoot td{border-top:var(--border-width) solid var(--table-border-color);border-bottom:0}table[role="grid"] tbody tr:nth-child(odd){background-color:var(--table-row-stripped-background-color)}pre,code,kbd,samp{font-size:0.875em;font-family:var(--font-family)}pre{-ms-overflow-style:scrollbar;overflow:auto}pre,code,kbd{border-radius:var(--border-radius);background:var(--code-background-color);color:var(--code-color);font-weight:var(--font-weight);line-height:initial}code,kbd{display:inline-block;padding:0.375rem 0.5rem}pre{display:block;margin-bottom:var(--spacing);overflow-x:auto}pre>code{display:block;padding:var(--spacing);background:none;font-size:14px;line-height:var(--line-height)}code b{color:var(--code-tag-color);font-weight:var(--font-weight)}code i{color:var(--code-property-color);font-style:normal}code u{color:var(--code-value-color);text-decoration:none}code em{color:var(--code-comment-color);font-style:normal}kbd{background-color:var(--code-kbd-background-color);color:var(--code-kbd-color);vertical-align:baseline}hr{height:0;border:0;border-top:1px solid var(--muted-border-color);color:inherit}[hidden],template{display:none !important}canvas{display:inline-block}details{display:block;margin-bottom:var(--spacing);padding-bottom:var(--spacing);border-bottom:var(--border-width) solid var(--accordion-border-color)}details summary{line-height:1rem;list-style-type:none;cursor:pointer;transition:color var(--transition)}details summary:not([role]){color:var(--accordion-close-summary-color)}details summary::-webkit-details-marker{display:none}details summary::marker{display:none}details summary::-moz-list-bullet{list-style-type:none}details summary::after{display:block;width:1rem;height:1rem;margin-inline-start:calc(var(--spacing, 1rem) * 0.5);float:right;transform:rotate(-90deg);background-image:var(--icon-chevron);background-position:right center;background-size:1rem auto;background-repeat:no-repeat;content:"";transition:transform var(--transition)}details summary:focus{outline:none}details summary:focus:not([role="button"]){color:var(--accordion-active-summary-color)}details summary[role="button"]{width:100%;text-align:left}details summary[role="button"]::after{height:calc(1rem * var(--line-height, 1.5));background-image:var(--icon-chevron-button)}details summary[role="button"]:not(.outline).contrast::after{background-image:var(--icon-chevron-button-inverse)}details[open]>summary{margin-bottom:calc(var(--spacing))}details[open]>summary:not([role]):not(:focus){color:var(--accordion-open-summary-color)}details[open]>summary::after{transform:rotate(0)}[dir="rtl"] details summary{text-align:right}[dir="rtl"] details summary::after{float:left;background-position:left center}article{margin:var(--block-spacing-vertical) 0;padding:var(--block-spacing-vertical) var(--block-spacing-horizontal);border-radius:var(--border-radius);background:var(--card-background-color);box-shadow:var(--card-box-shadow)}article>header,article>footer{margin-right:calc(var(--block-spacing-horizontal) * -1);margin-left:calc(var(--block-spacing-horizontal) * -1);padding:calc(var(--block-spacing-vertical) * 0.66) var(--block-spacing-horizontal);background-color:var(--card-sectionning-background-color)}article>header{margin-top:calc(var(--block-spacing-vertical) * -1);margin-bottom:var(--block-spacing-vertical);border-bottom:var(--border-width) solid var(--card-border-color);border-top-right-radius:var(--border-radius);border-top-left-radius:var(--border-radius)}article>footer{margin-top:var(--block-spacing-vertical);margin-bottom:calc(var(--block-spacing-vertical) * -1);border-top:var(--border-width) solid var(--card-border-color);border-bottom-right-radius:var(--border-radius);border-bottom-left-radius:var(--border-radius)}:root{--scrollbar-width: 0px}dialog{display:flex;z-index:999;position:fixed;top:0;right:0;bottom:0;left:0;align-items:center;justify-content:center;width:inherit;min-width:100%;height:inherit;min-height:100%;padding:var(--spacing);border:0;backdrop-filter:var(--modal-overlay-backdrop-filter);background-color:var(--modal-overlay-background-color);color:var(--color)}dialog article{max-height:calc(100vh - var(--spacing) * 2);overflow:auto}@media (min-width: 576px){dialog article{max-width:510px}}@media (min-width: 768px){dialog article{max-width:700px}}dialog article>header,dialog article>footer{padding:calc(var(--block-spacing-vertical) * 0.5) var(--block-spacing-horizontal)}dialog article>header .close{margin:0;margin-left:var(--spacing);float:right}dialog article>footer{text-align:right}dialog article>footer [role="button"]{margin-bottom:0}dialog article>footer [role="button"]:not(:first-of-type){margin-left:calc(var(--spacing) * 0.5)}dialog article p:last-of-type{margin:0}dialog article .close{display:block;width:1rem;height:1rem;margin-top:calc(var(--block-spacing-vertical) * -0.5);margin-bottom:var(--typography-spacing-vertical);margin-left:auto;background-image:var(--icon-close);background-position:center;background-size:auto 1rem;background-repeat:no-repeat;opacity:0.5;transition:opacity var(--transition)}dialog article .close:is([aria-current], :hover, :active, :focus){opacity:1}dialog:not([open]),dialog[open="false"]{display:none}.modal-is-open{padding-right:var(--scrollbar-width, 0px);overflow:hidden;pointer-events:none;touch-action:none}.modal-is-open dialog{pointer-events:auto}:where(.modal-is-opening, .modal-is-closing) dialog,:where(.modal-is-opening, .modal-is-closing) dialog>article{animation-duration:.2s;animation-timing-function:ease-in-out;animation-fill-mode:both}:where(.modal-is-opening, .modal-is-closing) dialog{animation-duration:.8s;animation-name:modal-overlay}:where(.modal-is-opening, .modal-is-closing) dialog>article{animation-delay:.2s;animation-name:modal}.modal-is-closing dialog,.modal-is-closing dialog>article{animation-delay:0s;animation-direction:reverse}@keyframes modal-overlay{from{backdrop-filter:none;background-color:transparent}}@keyframes modal{from{transform:translateY(-100%);opacity:0}}:where(nav li)::before{float:left;content:"\200B"}nav,nav ul{display:flex}nav{justify-content:space-between}nav ol,nav ul{align-items:center;margin-bottom:0;padding:0;list-style:none}nav ol:first-of-type,nav ul:first-of-type{margin-left:calc(var(--nav-element-spacing-horizontal) * -1)}nav ol:last-of-type,nav ul:last-of-type{margin-right:calc(var(--nav-element-spacing-horizontal) * -1)}nav li{display:inline-block;margin:0;padding:var(--nav-element-spacing-vertical) var(--nav-element-spacing-horizontal)}nav li>*{--spacing: 0}nav :where(a, [role="link"]){display:inline-block;margin:calc(var(--nav-link-spacing-vertical) * -1) calc(var(--nav-link-spacing-horizontal) * -1);padding:var(--nav-link-spacing-vertical) var(--nav-link-spacing-horizontal);border-radius:var(--border-radius);text-decoration:none}nav :where(a, [role="link"]):is([aria-current], :hover, :active, :focus){text-decoration:none}nav[aria-label="breadcrumb"]{align-items:center;justify-content:start}nav[aria-label="breadcrumb"] ul li:not(:first-child){margin-inline-start:var(--nav-link-spacing-horizontal)}nav[aria-label="breadcrumb"] ul li:not(:last-child) ::after{position:absolute;width:calc(var(--nav-link-spacing-horizontal) * 2);margin-inline-start:calc(var(--nav-link-spacing-horizontal) / 2);content:"/";color:var(--muted-color);text-align:center}nav[aria-label="breadcrumb"] a[aria-current]{background-color:transparent;color:inherit;text-decoration:none;pointer-events:none}nav [role="button"]{margin-right:inherit;margin-left:inherit;padding:var(--nav-link-spacing-vertical) var(--nav-link-spacing-horizontal)}aside nav,aside ol,aside ul,aside li{display:block}aside li{padding:calc(var(--nav-element-spacing-vertical) * 0.5) var(--nav-element-spacing-horizontal)}aside li a{display:block}aside li [role="button"]{margin:inherit}[dir="rtl"] nav[aria-label="breadcrumb"] ul li:not(:last-child) ::after{content:"\\"}progress{display:inline-block;vertical-align:baseline}progress{-webkit-appearance:none;-moz-appearance:none;display:inline-block;appearance:none;width:100%;height:0.5rem;margin-bottom:calc(var(--spacing) * 0.5);overflow:hidden;border:0;border-radius:var(--border-radius);background-color:var(--progress-background-color);color:var(--progress-color)}progress::-webkit-progress-bar{border-radius:var(--border-radius);background:none}progress[value]::-webkit-progress-value{background-color:var(--progress-color)}progress::-moz-progress-bar{background-color:var(--progress-color)}@media (prefers-reduced-motion: no-preference){progress:indeterminate{background:var(--progress-background-color) linear-gradient(to right, var(--progress-color) 30%, var(--progress-background-color) 30%) top left/150% 150% no-repeat;animation:progress-indeterminate 1s linear infinite}progress:indeterminate[value]::-webkit-progress-value{background-color:transparent}progress:indeterminate::-moz-progress-bar{background-color:transparent}}@media (prefers-reduced-motion: no-preference){[dir="rtl"] progress:indeterminate{animation-direction:reverse}}@keyframes progress-indeterminate{0%{background-position:200% 0}100%{background-position:-200% 0}}details[role="list"],li[role="list"]{position:relative}details[role="list"] summary+ul,li[role="list"]>ul{display:flex;z-index:99;position:absolute;top:auto;right:0;left:0;flex-direction:column;margin:0;padding:0;border:var(--border-width) solid var(--dropdown-border-color);border-radius:var(--border-radius);border-top-right-radius:0;border-top-left-radius:0;background-color:var(--dropdown-background-color);box-shadow:var(--card-box-shadow);color:var(--dropdown-color);white-space:nowrap}details[role="list"] summary+ul li,li[role="list"]>ul li{width:100%;margin-bottom:0;padding:calc(var(--form-element-spacing-vertical) * 0.5) var(--form-element-spacing-horizontal);list-style:none}details[role="list"] summary+ul li:first-of-type,li[role="list"]>ul li:first-of-type{margin-top:calc(var(--form-element-spacing-vertical) * 0.5)}details[role="list"] summary+ul li:last-of-type,li[role="list"]>ul li:last-of-type{margin-bottom:calc(var(--form-element-spacing-vertical) * 0.5)}details[role="list"] summary+ul li a,li[role="list"]>ul li a{display:block;margin:calc(var(--form-element-spacing-vertical) * -0.5) calc(var(--form-element-spacing-horizontal) * -1);padding:calc(var(--form-element-spacing-vertical) * 0.5) var(--form-element-spacing-horizontal);overflow:hidden;color:var(--dropdown-color);text-decoration:none;text-overflow:ellipsis}details[role="list"] summary+ul li a:hover,li[role="list"]>ul li a:hover{background-color:var(--dropdown-hover-background-color)}details[role="list"] summary::after,li[role="list"]>a::after{display:block;width:1rem;height:calc(1rem * var(--line-height, 1.5));margin-inline-start:0.5rem;float:right;transform:rotate(0deg);background-position:right center;background-size:1rem auto;background-repeat:no-repeat;content:""}details[role="list"]{padding:0;border-bottom:none}details[role="list"] summary{margin-bottom:0}details[role="list"] summary:not([role]){height:calc( 1rem * var(--line-height) + var(--form-element-spacing-vertical) * 2 + var(--border-width) * 2);padding:var(--form-element-spacing-vertical) var(--form-element-spacing-horizontal);border:var(--border-width) solid var(--form-element-border-color);border-radius:var(--border-radius);background-color:var(--form-element-background-color);color:var(--form-element-placeholder-color);line-height:inherit;cursor:pointer;transition:background-color var(--transition),border-color var(--transition),color var(--transition),box-shadow var(--transition)}details[role="list"] summary:not([role]):active,details[role="list"] summary:not([role]):focus{border-color:var(--form-element-active-border-color);background-color:var(--form-element-active-background-color)}details[role="list"] summary:not([role]):focus{box-shadow:0 0 0 var(--outline-width) var(--form-element-focus-color)}details[role="list"][open] summary{border-bottom-right-radius:0;border-bottom-left-radius:0}details[role="list"][open] summary::before{display:block;z-index:1;position:fixed;top:0;right:0;bottom:0;left:0;background:none;content:"";cursor:default}nav details[role="list"] summary,nav li[role="list"] a{display:flex;direction:ltr}nav details[role="list"] summary+ul,nav li[role="list"]>ul{min-width:fit-content;border-radius:var(--border-radius)}nav details[role="list"] summary+ul li a,nav li[role="list"]>ul li a{border-radius:0}nav details[role="list"] summary,nav details[role="list"] summary:not([role]){height:auto;padding:var(--nav-link-spacing-vertical) var(--nav-link-spacing-horizontal)}nav details[role="list"][open] summary{border-radius:var(--border-radius)}nav details[role="list"] summary+ul{margin-top:var(--outline-width);margin-inline-start:0}nav details[role="list"] summary[role="link"]{margin-bottom:calc(var(--nav-link-spacing-vertical) * -1);line-height:var(--line-height)}nav details[role="list"] summary[role="link"]+ul{margin-top:calc(var(--nav-link-spacing-vertical) + var(--outline-width));margin-inline-start:calc(var(--nav-link-spacing-horizontal) * -1)}li[role="list"]:hover>ul,li[role="list"] a:active~ul,li[role="list"] a:focus~ul{display:flex}li[role="list"]>ul{display:none;margin-top:calc(var(--nav-link-spacing-vertical) + var(--outline-width));margin-inline-start:calc( var(--nav-element-spacing-horizontal) - var(--nav-link-spacing-horizontal))}li[role="list"]>a::after{background-image:var(--icon-chevron)}label>details[role="list"]{margin-top:calc(var(--spacing) * .25);margin-bottom:var(--spacing)}[aria-busy="true"]{cursor:progress}[aria-busy="true"]:not(input,select,textarea)::before{display:inline-block;width:1em;height:1em;border:0.1875em solid currentColor;border-radius:1em;border-right-color:transparent;content:"";vertical-align:text-bottom;vertical-align:-.125em;animation:spinner 0.75s linear infinite;opacity:var(--loading-spinner-opacity)}[aria-busy="true"]:not(input,select,textarea):not(:empty)::before{margin-right:calc(var(--spacing) * 0.5);margin-left:0;margin-inline-start:0;margin-inline-end:calc(var(--spacing) * 0.5)}[aria-busy="true"]:not(input,select,textarea):empty{text-align:center}button[aria-busy="true"],input[type="submit"][aria-busy="true"],input[type="button"][aria-busy="true"],input[type="reset"][aria-busy="true"],a[aria-busy="true"]{pointer-events:none}@keyframes spinner{to{transform:rotate(360deg)}}[data-tooltip]{position:relative}[data-tooltip]:not(a,button,input){border-bottom:1px dotted;text-decoration:none;cursor:help}[data-tooltip][data-placement="top"]::before,[data-tooltip][data-placement="top"]::after,[data-tooltip]::before,[data-tooltip]::after{display:block;z-index:99;position:absolute;bottom:100%;left:50%;padding:.25rem .5rem;overflow:hidden;transform:translate(-50%, -0.25rem);border-radius:var(--border-radius);background:var(--tooltip-background-color);content:attr(data-tooltip);color:var(--tooltip-color);font-style:normal;font-weight:var(--font-weight);font-size:.875rem;text-decoration:none;text-overflow:ellipsis;white-space:nowrap;opacity:0;pointer-events:none}[data-tooltip][data-placement="top"]::after,[data-tooltip]::after{padding:0;transform:translate(-50%, 0rem);border-top:.3rem solid;border-right:.3rem solid transparent;border-left:.3rem solid transparent;border-radius:0;background-color:transparent;content:"";color:var(--tooltip-background-color)}[data-tooltip][data-placement="bottom"]::before,[data-tooltip][data-placement="bottom"]::after{top:100%;bottom:auto;transform:translate(-50%, 0.25rem)}[data-tooltip][data-placement="bottom"]:after{transform:translate(-50%, -0.3rem);border:.3rem solid transparent;border-bottom:.3rem solid}[data-tooltip][data-placement="left"]::before,[data-tooltip][data-placement="left"]::after{top:50%;right:100%;bottom:auto;left:auto;transform:translate(-0.25rem, -50%)}[data-tooltip][data-placement="left"]:after{transform:translate(0.3rem, -50%);border:.3rem solid transparent;border-left:.3rem solid}[data-tooltip][data-placement="right"]::before,[data-tooltip][data-placement="right"]::after{top:50%;right:auto;bottom:auto;left:100%;transform:translate(0.25rem, -50%)}[data-tooltip][data-placement="right"]:after{transform:translate(-0.3rem, -50%);border:.3rem solid transparent;border-right:.3rem solid}[data-tooltip]:focus::before,[data-tooltip]:focus::after,[data-tooltip]:hover::before,[data-tooltip]:hover::after{opacity:1}@media (hover: hover) and (pointer: fine){[data-tooltip][data-placement="bottom"]:focus::before,[data-tooltip][data-placement="bottom"]:focus::after,[data-tooltip][data-placement="bottom"]:hover [data-tooltip]:focus::before,[data-tooltip][data-placement="bottom"]:hover [data-tooltip]:focus::after,[data-tooltip]:hover::before,[data-tooltip]:hover::after{animation-duration:.2s;animation-name:tooltip-slide-top}[data-tooltip][data-placement="bottom"]:focus::after,[data-tooltip][data-placement="bottom"]:hover [data-tooltip]:focus::after,[data-tooltip]:hover::after{animation-name:tooltip-caret-slide-top}[data-tooltip][data-placement="bottom"]:focus::before,[data-tooltip][data-placement="bottom"]:focus::after,[data-tooltip][data-placement="bottom"]:hover::before,[data-tooltip][data-placement="bottom"]:hover::after{animation-duration:.2s;animation-name:tooltip-slide-bottom}[data-tooltip][data-placement="bottom"]:focus::after,[data-tooltip][data-placement="bottom"]:hover::after{animation-name:tooltip-caret-slide-bottom}[data-tooltip][data-placement="left"]:focus::before,[data-tooltip][data-placement="left"]:focus::after,[data-tooltip][data-placement="left"]:hover::before,[data-tooltip][data-placement="left"]:hover::after{animation-duration:.2s;animation-name:tooltip-slide-left}[data-tooltip][data-placement="left"]:focus::after,[data-tooltip][data-placement="left"]:hover::after{animation-name:tooltip-caret-slide-left}[data-tooltip][data-placement="right"]:focus::before,[data-tooltip][data-placement="right"]:focus::after,[data-tooltip][data-placement="right"]:hover::before,[data-tooltip][data-placement="right"]:hover::after{animation-duration:.2s;animation-name:tooltip-slide-right}[data-tooltip][data-placement="right"]:focus::after,[data-tooltip][data-placement="right"]:hover::after{animation-name:tooltip-caret-slide-right}}@keyframes tooltip-slide-top{from{transform:translate(-50%, 0.75rem);opacity:0}to{transform:translate(-50%, -0.25rem);opacity:1}}@keyframes tooltip-caret-slide-top{from{opacity:0}50%{transform:translate(-50%, -0.25rem);opacity:0}to{transform:translate(-50%, 0rem);opacity:1}}@keyframes tooltip-slide-bottom{from{transform:translate(-50%, -0.75rem);opacity:0}to{transform:translate(-50%, 0.25rem);opacity:1}}@keyframes tooltip-caret-slide-bottom{from{opacity:0}50%{transform:translate(-50%, -0.5rem);opacity:0}to{transform:translate(-50%, -0.3rem);opacity:1}}@keyframes tooltip-slide-left{from{transform:translate(0.75rem, -50%);opacity:0}to{transform:translate(-0.25rem, -50%);opacity:1}}@keyframes tooltip-caret-slide-left{from{opacity:0}50%{transform:translate(0.05rem, -50%);opacity:0}to{transform:translate(0.3rem, -50%);opacity:1}}@keyframes tooltip-slide-right{from{transform:translate(-0.75rem, -50%);opacity:0}to{transform:translate(0.25rem, -50%);opacity:1}}@keyframes tooltip-caret-slide-right{from{opacity:0}50%{transform:translate(-0.05rem, -50%);opacity:0}to{transform:translate(-0.3rem, -50%);opacity:1}}[aria-controls]{cursor:pointer}[aria-disabled="true"],[disabled]{cursor:not-allowed}[aria-hidden="false"][hidden]{display:initial}[aria-hidden="false"][hidden]:not(:focus){clip:rect(0, 0, 0, 0);position:absolute}a,area,button,input,label,select,summary,textarea,[tabindex]{-ms-touch-action:manipulation}[dir="rtl"]{direction:rtl}@media (prefers-reduced-motion: reduce){*:not([aria-busy="true"]),:not([aria-busy="true"])::before,:not([aria-busy="true"])::after{background-attachment:initial !important;animation-duration:1ms !important;animation-delay:-1ms !important;animation-iteration-count:1 !important;scroll-behavior:auto !important;transition-delay:0s !important;transition-duration:0s !important}} diff --git a/templates/partials/animal_card.html b/templates/partials/animal_card.html new file mode 100644 index 0000000..38ac3b1 --- /dev/null +++ b/templates/partials/animal_card.html @@ -0,0 +1,7 @@ +{% partialdef animal_card %} +{{ animal.full_name }} +{% endpartialdef %} diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..1a6dab0 --- /dev/null +++ b/uv.lock @@ -0,0 +1,1615 @@ +version = 1 +revision = 3 +requires-python = ">=3.14" + +[[package]] +name = "aiohappyeyeballs" +version = "2.6.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/33/c6/61a2d7b7572279226bb2e7f61d7a19ca7c90da0329c93fa0d560cbf288d8/aiohappyeyeballs-2.6.2.tar.gz", hash = "sha256:e202810ee718bd01fc6ef49e8ea53d023d5cb6b581076d7925aa499fa55dbe64", size = 22591, upload-time = "2026-05-20T15:12:24.631Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/fc/a7bf5b6e4e617b45f90f2d9d2a68519c249c81dd4fc2658c7a2a61c4f4b7/aiohappyeyeballs-2.6.2-py3-none-any.whl", hash = "sha256:4708045e2d7a6c6bdf8aafa8ed39649eaf926a4543b54560659129e3365953c4", size = 15062, upload-time = "2026-05-20T15:12:23.328Z" }, +] + +[[package]] +name = "aiohttp" +version = "3.13.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohappyeyeballs" }, + { name = "aiosignal" }, + { name = "attrs" }, + { name = "frozenlist" }, + { name = "multidict" }, + { name = "propcache" }, + { name = "yarl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/77/9a/152096d4808df8e4268befa55fba462f440f14beab85e8ad9bf990516918/aiohttp-3.13.5.tar.gz", hash = "sha256:9d98cc980ecc96be6eb4c1994ce35d28d8b1f5e5208a23b421187d1209dbb7d1", size = 7858271, upload-time = "2026-03-31T22:01:03.343Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5d/ce/46572759afc859e867a5bc8ec3487315869013f59281ce61764f76d879de/aiohttp-3.13.5-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:eb4639f32fd4a9904ab8fb45bf3383ba71137f3d9d4ba25b3b3f3109977c5b8c", size = 745721, upload-time = "2026-03-31T21:58:50.229Z" }, + { url = "https://files.pythonhosted.org/packages/13/fe/8a2efd7626dbe6049b2ef8ace18ffda8a4dfcbe1bcff3ac30c0c7575c20b/aiohttp-3.13.5-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:7e5dc4311bd5ac493886c63cbf76ab579dbe4641268e7c74e48e774c74b6f2be", size = 497663, upload-time = "2026-03-31T21:58:52.232Z" }, + { url = "https://files.pythonhosted.org/packages/9b/91/cc8cc78a111826c54743d88651e1687008133c37e5ee615fee9b57990fac/aiohttp-3.13.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:756c3c304d394977519824449600adaf2be0ccee76d206ee339c5e76b70ded25", size = 499094, upload-time = "2026-03-31T21:58:54.566Z" }, + { url = "https://files.pythonhosted.org/packages/0a/33/a8362cb15cf16a3af7e86ed11962d5cd7d59b449202dc576cdc731310bde/aiohttp-3.13.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecc26751323224cf8186efcf7fbcbc30f4e1d8c7970659daf25ad995e4032a56", size = 1726701, upload-time = "2026-03-31T21:58:56.864Z" }, + { url = "https://files.pythonhosted.org/packages/45/0c/c091ac5c3a17114bd76cbf85d674650969ddf93387876cf67f754204bd77/aiohttp-3.13.5-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:10a75acfcf794edf9d8db50e5a7ec5fc818b2a8d3f591ce93bc7b1210df016d2", size = 1683360, upload-time = "2026-03-31T21:58:59.072Z" }, + { url = "https://files.pythonhosted.org/packages/23/73/bcee1c2b79bc275e964d1446c55c54441a461938e70267c86afaae6fba27/aiohttp-3.13.5-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0f7a18f258d124cd678c5fe072fe4432a4d5232b0657fca7c1847f599233c83a", size = 1773023, upload-time = "2026-03-31T21:59:01.776Z" }, + { url = "https://files.pythonhosted.org/packages/c7/ef/720e639df03004fee2d869f771799d8c23046dec47d5b81e396c7cda583a/aiohttp-3.13.5-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:df6104c009713d3a89621096f3e3e88cc323fd269dbd7c20afe18535094320be", size = 1853795, upload-time = "2026-03-31T21:59:04.568Z" }, + { url = "https://files.pythonhosted.org/packages/bd/c9/989f4034fb46841208de7aeeac2c6d8300745ab4f28c42f629ba77c2d916/aiohttp-3.13.5-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:241a94f7de7c0c3b616627aaad530fe2cb620084a8b144d3be7b6ecfe95bae3b", size = 1730405, upload-time = "2026-03-31T21:59:07.221Z" }, + { url = "https://files.pythonhosted.org/packages/ce/75/ee1fd286ca7dc599d824b5651dad7b3be7ff8d9a7e7b3fe9820d9180f7db/aiohttp-3.13.5-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c974fb66180e58709b6fc402846f13791240d180b74de81d23913abe48e96d94", size = 1558082, upload-time = "2026-03-31T21:59:09.484Z" }, + { url = "https://files.pythonhosted.org/packages/c3/20/1e9e6650dfc436340116b7aa89ff8cb2bbdf0abc11dfaceaad8f74273a10/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:6e27ea05d184afac78aabbac667450c75e54e35f62238d44463131bd3f96753d", size = 1692346, upload-time = "2026-03-31T21:59:12.068Z" }, + { url = "https://files.pythonhosted.org/packages/d8/40/8ebc6658d48ea630ac7903912fe0dd4e262f0e16825aa4c833c56c9f1f56/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a79a6d399cef33a11b6f004c67bb07741d91f2be01b8d712d52c75711b1e07c7", size = 1698891, upload-time = "2026-03-31T21:59:14.552Z" }, + { url = "https://files.pythonhosted.org/packages/d8/78/ea0ae5ec8ba7a5c10bdd6e318f1ba5e76fcde17db8275188772afc7917a4/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c632ce9c0b534fbe25b52c974515ed674937c5b99f549a92127c85f771a78772", size = 1742113, upload-time = "2026-03-31T21:59:17.068Z" }, + { url = "https://files.pythonhosted.org/packages/8a/66/9d308ed71e3f2491be1acb8769d96c6f0c47d92099f3bc9119cada27b357/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:fceedde51fbd67ee2bcc8c0b33d0126cc8b51ef3bbde2f86662bd6d5a6f10ec5", size = 1553088, upload-time = "2026-03-31T21:59:19.541Z" }, + { url = "https://files.pythonhosted.org/packages/da/a6/6cc25ed8dfc6e00c90f5c6d126a98e2cf28957ad06fa1036bd34b6f24a2c/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f92995dfec9420bb69ae629abf422e516923ba79ba4403bc750d94fb4a6c68c1", size = 1757976, upload-time = "2026-03-31T21:59:22.311Z" }, + { url = "https://files.pythonhosted.org/packages/c1/2b/cce5b0ffe0de99c83e5e36d8f828e4161e415660a9f3e58339d07cce3006/aiohttp-3.13.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:20ae0ff08b1f2c8788d6fb85afcb798654ae6ba0b747575f8562de738078457b", size = 1712444, upload-time = "2026-03-31T21:59:24.635Z" }, + { url = "https://files.pythonhosted.org/packages/6c/cf/9e1795b4160c58d29421eafd1a69c6ce351e2f7c8d3c6b7e4ca44aea1a5b/aiohttp-3.13.5-cp314-cp314-win32.whl", hash = "sha256:b20df693de16f42b2472a9c485e1c948ee55524786a0a34345511afdd22246f3", size = 438128, upload-time = "2026-03-31T21:59:27.291Z" }, + { url = "https://files.pythonhosted.org/packages/22/4d/eaedff67fc805aeba4ba746aec891b4b24cebb1a7d078084b6300f79d063/aiohttp-3.13.5-cp314-cp314-win_amd64.whl", hash = "sha256:f85c6f327bf0b8c29da7d93b1cabb6363fb5e4e160a32fa241ed2dce21b73162", size = 464029, upload-time = "2026-03-31T21:59:29.429Z" }, + { url = "https://files.pythonhosted.org/packages/79/11/c27d9332ee20d68dd164dc12a6ecdef2e2e35ecc97ed6cf0d2442844624b/aiohttp-3.13.5-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:1efb06900858bb618ff5cee184ae2de5828896c448403d51fb633f09e109be0a", size = 778758, upload-time = "2026-03-31T21:59:31.547Z" }, + { url = "https://files.pythonhosted.org/packages/04/fb/377aead2e0a3ba5f09b7624f702a964bdf4f08b5b6728a9799830c80041e/aiohttp-3.13.5-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:fee86b7c4bd29bdaf0d53d14739b08a106fdda809ca5fe032a15f52fae5fe254", size = 512883, upload-time = "2026-03-31T21:59:34.098Z" }, + { url = "https://files.pythonhosted.org/packages/bb/a6/aa109a33671f7a5d3bd78b46da9d852797c5e665bfda7d6b373f56bff2ec/aiohttp-3.13.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:20058e23909b9e65f9da62b396b77dfa95965cbe840f8def6e572538b1d32e36", size = 516668, upload-time = "2026-03-31T21:59:36.497Z" }, + { url = "https://files.pythonhosted.org/packages/79/b3/ca078f9f2fa9563c36fb8ef89053ea2bb146d6f792c5104574d49d8acb63/aiohttp-3.13.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cf20a8d6868cb15a73cab329ffc07291ba8c22b1b88176026106ae39aa6df0f", size = 1883461, upload-time = "2026-03-31T21:59:38.723Z" }, + { url = "https://files.pythonhosted.org/packages/b7/e3/a7ad633ca1ca497b852233a3cce6906a56c3225fb6d9217b5e5e60b7419d/aiohttp-3.13.5-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:330f5da04c987f1d5bdb8ae189137c77139f36bd1cb23779ca1a354a4b027800", size = 1747661, upload-time = "2026-03-31T21:59:41.187Z" }, + { url = "https://files.pythonhosted.org/packages/33/b9/cd6fe579bed34a906d3d783fe60f2fa297ef55b27bb4538438ee49d4dc41/aiohttp-3.13.5-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6f1cbf0c7926d315c3c26c2da41fd2b5d2fe01ac0e157b78caefc51a782196cf", size = 1863800, upload-time = "2026-03-31T21:59:43.84Z" }, + { url = "https://files.pythonhosted.org/packages/c0/3f/2c1e2f5144cefa889c8afd5cf431994c32f3b29da9961698ff4e3811b79a/aiohttp-3.13.5-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:53fc049ed6390d05423ba33103ded7281fe897cf97878f369a527070bd95795b", size = 1958382, upload-time = "2026-03-31T21:59:46.187Z" }, + { url = "https://files.pythonhosted.org/packages/66/1d/f31ec3f1013723b3babe3609e7f119c2c2fb6ef33da90061a705ef3e1bc8/aiohttp-3.13.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:898703aa2667e3c5ca4c54ca36cd73f58b7a38ef87a5606414799ebce4d3fd3a", size = 1803724, upload-time = "2026-03-31T21:59:48.656Z" }, + { url = "https://files.pythonhosted.org/packages/0e/b4/57712dfc6f1542f067daa81eb61da282fab3e6f1966fca25db06c4fc62d5/aiohttp-3.13.5-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0494a01ca9584eea1e5fbd6d748e61ecff218c51b576ee1999c23db7066417d8", size = 1640027, upload-time = "2026-03-31T21:59:51.284Z" }, + { url = "https://files.pythonhosted.org/packages/25/3c/734c878fb43ec083d8e31bf029daae1beafeae582d1b35da234739e82ee7/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6cf81fe010b8c17b09495cbd15c1d35afbc8fb405c0c9cf4738e5ae3af1d65be", size = 1806644, upload-time = "2026-03-31T21:59:53.753Z" }, + { url = "https://files.pythonhosted.org/packages/20/a5/f671e5cbec1c21d044ff3078223f949748f3a7f86b14e34a365d74a5d21f/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:c564dd5f09ddc9d8f2c2d0a301cd30a79a2cc1b46dd1a73bef8f0038863d016b", size = 1791630, upload-time = "2026-03-31T21:59:56.239Z" }, + { url = "https://files.pythonhosted.org/packages/0b/63/fb8d0ad63a0b8a99be97deac8c04dacf0785721c158bdf23d679a87aa99e/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:2994be9f6e51046c4f864598fd9abeb4fba6e88f0b2152422c9666dcd4aea9c6", size = 1809403, upload-time = "2026-03-31T21:59:59.103Z" }, + { url = "https://files.pythonhosted.org/packages/59/0c/bfed7f30662fcf12206481c2aac57dedee43fe1c49275e85b3a1e1742294/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:157826e2fa245d2ef46c83ea8a5faf77ca19355d278d425c29fda0beb3318037", size = 1634924, upload-time = "2026-03-31T22:00:02.116Z" }, + { url = "https://files.pythonhosted.org/packages/17/d6/fd518d668a09fd5a3319ae5e984d4d80b9a4b3df4e21c52f02251ef5a32e/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:a8aca50daa9493e9e13c0f566201a9006f080e7c50e5e90d0b06f53146a54500", size = 1836119, upload-time = "2026-03-31T22:00:04.756Z" }, + { url = "https://files.pythonhosted.org/packages/78/b7/15fb7a9d52e112a25b621c67b69c167805cb1f2ab8f1708a5c490d1b52fe/aiohttp-3.13.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3b13560160d07e047a93f23aaa30718606493036253d5430887514715b67c9d9", size = 1772072, upload-time = "2026-03-31T22:00:07.494Z" }, + { url = "https://files.pythonhosted.org/packages/7e/df/57ba7f0c4a553fc2bd8b6321df236870ec6fd64a2a473a8a13d4f733214e/aiohttp-3.13.5-cp314-cp314t-win32.whl", hash = "sha256:9a0f4474b6ea6818b41f82172d799e4b3d29e22c2c520ce4357856fced9af2f8", size = 471819, upload-time = "2026-03-31T22:00:10.277Z" }, + { url = "https://files.pythonhosted.org/packages/62/29/2f8418269e46454a26171bfdd6a055d74febf32234e474930f2f60a17145/aiohttp-3.13.5-cp314-cp314t-win_amd64.whl", hash = "sha256:18a2f6c1182c51baa1d28d68fea51513cb2a76612f038853c0ad3c145423d3d9", size = 505441, upload-time = "2026-03-31T22:00:12.791Z" }, +] + +[[package]] +name = "aiosignal" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "frozenlist" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", size = 7490, upload-time = "2025-07-03T22:54:42.156Z" }, +] + +[[package]] +name = "amqp" +version = "5.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "vine" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/79/fc/ec94a357dfc6683d8c86f8b4cfa5416a4c36b28052ec8260c77aca96a443/amqp-5.3.1.tar.gz", hash = "sha256:cddc00c725449522023bad949f70fff7b48f0b1ade74d170a6f10ab044739432", size = 129013, upload-time = "2024-11-12T19:55:44.051Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/26/99/fc813cd978842c26c82534010ea849eee9ab3a13ea2b74e95cb9c99e747b/amqp-5.3.1-py3-none-any.whl", hash = "sha256:43b3319e1b4e7d1251833a93d672b4af1e40f3d632d479b98661a95f117880a2", size = 50944, upload-time = "2024-11-12T19:55:41.782Z" }, +] + +[[package]] +name = "animals-healthcare-application" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "celery" }, + { name = "cffi" }, + { name = "crispy-bootstrap4" }, + { name = "cryptography" }, + { name = "defusedxml" }, + { name = "discord" }, + { name = "django" }, + { name = "django-appconf" }, + { name = "django-bootstrap-modal-forms" }, + { name = "django-compressor" }, + { name = "django-crispy-forms" }, + { name = "django-libsass" }, + { name = "django-taggit" }, + { name = "django-timezone-field" }, + { name = "djangorestframework" }, + { name = "flower" }, + { name = "httplib2" }, + { name = "icecream" }, + { name = "libsass" }, + { name = "pillow" }, + { name = "psycopg", extra = ["binary"] }, + { name = "pycouchdb" }, + { name = "pyjwt" }, + { name = "python-dateutil" }, + { name = "python-decouple" }, + { name = "python3-openid" }, + { name = "redis" }, + { name = "requests" }, + { name = "requests-oauthlib" }, + { name = "tzdata" }, +] + +[package.dev-dependencies] +dev = [ + { name = "bandit" }, + { name = "codespell" }, + { name = "pre-commit" }, + { name = "pytest" }, + { name = "pytest-cov" }, + { name = "pytest-django" }, + { name = "ruff" }, + { name = "ty" }, +] + +[package.metadata] +requires-dist = [ + { name = "celery", specifier = ">=5.4" }, + { name = "cffi", specifier = ">=1.17" }, + { name = "crispy-bootstrap4" }, + { name = "cryptography", specifier = ">=43" }, + { name = "defusedxml" }, + { name = "discord" }, + { name = "django", specifier = ">=6.0,<6.1" }, + { name = "django-appconf" }, + { name = "django-bootstrap-modal-forms" }, + { name = "django-compressor" }, + { name = "django-crispy-forms" }, + { name = "django-libsass" }, + { name = "django-taggit" }, + { name = "django-timezone-field", specifier = ">=6.1" }, + { name = "djangorestframework", specifier = ">=3.14" }, + { name = "flower" }, + { name = "httplib2" }, + { name = "icecream" }, + { name = "libsass" }, + { name = "pillow", specifier = ">=11.0" }, + { name = "psycopg", extras = ["binary"], specifier = ">=3.2" }, + { name = "pycouchdb" }, + { name = "pyjwt" }, + { name = "python-dateutil" }, + { name = "python-decouple" }, + { name = "python3-openid" }, + { name = "redis", specifier = ">=5.0" }, + { name = "requests" }, + { name = "requests-oauthlib" }, + { name = "tzdata" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "bandit", extras = ["toml"] }, + { name = "codespell" }, + { name = "pre-commit" }, + { name = "pytest" }, + { name = "pytest-cov" }, + { name = "pytest-django" }, + { name = "ruff" }, + { name = "ty" }, +] + +[[package]] +name = "asgiref" +version = "3.11.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/63/40/f03da1264ae8f7cfdbf9146542e5e7e8100a4c66ab48e791df9a03d3f6c0/asgiref-3.11.1.tar.gz", hash = "sha256:5f184dc43b7e763efe848065441eac62229c9f7b0475f41f80e207a114eda4ce", size = 38550, upload-time = "2026-02-03T13:30:14.33Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5c/0a/a72d10ed65068e115044937873362e6e32fab1b7dce0046aeb224682c989/asgiref-3.11.1-py3-none-any.whl", hash = "sha256:e8667a091e69529631969fd45dc268fa79b99c92c5fcdda727757e52146ec133", size = 24345, upload-time = "2026-02-03T13:30:13.039Z" }, +] + +[[package]] +name = "asttokens" +version = "3.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/be/a5/8e3f9b6771b0b408517c82d97aed8f2036509bc247d46114925e32fe33f0/asttokens-3.0.1.tar.gz", hash = "sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7", size = 62308, upload-time = "2025-11-15T16:43:48.578Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl", hash = "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a", size = 27047, upload-time = "2025-11-15T16:43:16.109Z" }, +] + +[[package]] +name = "attrs" +version = "26.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9a/8e/82a0fe20a541c03148528be8cac2408564a6c9a0cc7e9171802bc1d26985/attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32", size = 952055, upload-time = "2026-03-19T14:22:25.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" }, +] + +[[package]] +name = "audioop-lts" +version = "0.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/38/53/946db57842a50b2da2e0c1e34bd37f36f5aadba1a929a3971c5d7841dbca/audioop_lts-0.2.2.tar.gz", hash = "sha256:64d0c62d88e67b98a1a5e71987b7aa7b5bcffc7dcee65b635823dbdd0a8dbbd0", size = 30686, upload-time = "2025-08-05T16:43:17.409Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/d4/94d277ca941de5a507b07f0b592f199c22454eeaec8f008a286b3fbbacd6/audioop_lts-0.2.2-cp313-abi3-macosx_10_13_universal2.whl", hash = "sha256:fd3d4602dc64914d462924a08c1a9816435a2155d74f325853c1f1ac3b2d9800", size = 46523, upload-time = "2025-08-05T16:42:20.836Z" }, + { url = "https://files.pythonhosted.org/packages/f8/5a/656d1c2da4b555920ce4177167bfeb8623d98765594af59702c8873f60ec/audioop_lts-0.2.2-cp313-abi3-macosx_10_13_x86_64.whl", hash = "sha256:550c114a8df0aafe9a05442a1162dfc8fec37e9af1d625ae6060fed6e756f303", size = 27455, upload-time = "2025-08-05T16:42:22.283Z" }, + { url = "https://files.pythonhosted.org/packages/1b/83/ea581e364ce7b0d41456fb79d6ee0ad482beda61faf0cab20cbd4c63a541/audioop_lts-0.2.2-cp313-abi3-macosx_11_0_arm64.whl", hash = "sha256:9a13dc409f2564de15dd68be65b462ba0dde01b19663720c68c1140c782d1d75", size = 26997, upload-time = "2025-08-05T16:42:23.849Z" }, + { url = "https://files.pythonhosted.org/packages/b8/3b/e8964210b5e216e5041593b7d33e97ee65967f17c282e8510d19c666dab4/audioop_lts-0.2.2-cp313-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:51c916108c56aa6e426ce611946f901badac950ee2ddaf302b7ed35d9958970d", size = 85844, upload-time = "2025-08-05T16:42:25.208Z" }, + { url = "https://files.pythonhosted.org/packages/c7/2e/0a1c52faf10d51def20531a59ce4c706cb7952323b11709e10de324d6493/audioop_lts-0.2.2-cp313-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:47eba38322370347b1c47024defbd36374a211e8dd5b0dcbce7b34fdb6f8847b", size = 85056, upload-time = "2025-08-05T16:42:26.559Z" }, + { url = "https://files.pythonhosted.org/packages/75/e8/cd95eef479656cb75ab05dfece8c1f8c395d17a7c651d88f8e6e291a63ab/audioop_lts-0.2.2-cp313-abi3-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ba7c3a7e5f23e215cb271516197030c32aef2e754252c4c70a50aaff7031a2c8", size = 93892, upload-time = "2025-08-05T16:42:27.902Z" }, + { url = "https://files.pythonhosted.org/packages/5c/1e/a0c42570b74f83efa5cca34905b3eef03f7ab09fe5637015df538a7f3345/audioop_lts-0.2.2-cp313-abi3-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:def246fe9e180626731b26e89816e79aae2276f825420a07b4a647abaa84becc", size = 96660, upload-time = "2025-08-05T16:42:28.9Z" }, + { url = "https://files.pythonhosted.org/packages/50/d5/8a0ae607ca07dbb34027bac8db805498ee7bfecc05fd2c148cc1ed7646e7/audioop_lts-0.2.2-cp313-abi3-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e160bf9df356d841bb6c180eeeea1834085464626dc1b68fa4e1d59070affdc3", size = 79143, upload-time = "2025-08-05T16:42:29.929Z" }, + { url = "https://files.pythonhosted.org/packages/12/17/0d28c46179e7910bfb0bb62760ccb33edb5de973052cb2230b662c14ca2e/audioop_lts-0.2.2-cp313-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:4b4cd51a57b698b2d06cb9993b7ac8dfe89a3b2878e96bc7948e9f19ff51dba6", size = 84313, upload-time = "2025-08-05T16:42:30.949Z" }, + { url = "https://files.pythonhosted.org/packages/84/ba/bd5d3806641564f2024e97ca98ea8f8811d4e01d9b9f9831474bc9e14f9e/audioop_lts-0.2.2-cp313-abi3-musllinux_1_2_ppc64le.whl", hash = "sha256:4a53aa7c16a60a6857e6b0b165261436396ef7293f8b5c9c828a3a203147ed4a", size = 93044, upload-time = "2025-08-05T16:42:31.959Z" }, + { url = "https://files.pythonhosted.org/packages/f9/5e/435ce8d5642f1f7679540d1e73c1c42d933331c0976eb397d1717d7f01a3/audioop_lts-0.2.2-cp313-abi3-musllinux_1_2_riscv64.whl", hash = "sha256:3fc38008969796f0f689f1453722a0f463da1b8a6fbee11987830bfbb664f623", size = 78766, upload-time = "2025-08-05T16:42:33.302Z" }, + { url = "https://files.pythonhosted.org/packages/ae/3b/b909e76b606cbfd53875693ec8c156e93e15a1366a012f0b7e4fb52d3c34/audioop_lts-0.2.2-cp313-abi3-musllinux_1_2_s390x.whl", hash = "sha256:15ab25dd3e620790f40e9ead897f91e79c0d3ce65fe193c8ed6c26cffdd24be7", size = 87640, upload-time = "2025-08-05T16:42:34.854Z" }, + { url = "https://files.pythonhosted.org/packages/30/e7/8f1603b4572d79b775f2140d7952f200f5e6c62904585d08a01f0a70393a/audioop_lts-0.2.2-cp313-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:03f061a1915538fd96272bac9551841859dbb2e3bf73ebe4a23ef043766f5449", size = 86052, upload-time = "2025-08-05T16:42:35.839Z" }, + { url = "https://files.pythonhosted.org/packages/b5/96/c37846df657ccdda62ba1ae2b6534fa90e2e1b1742ca8dcf8ebd38c53801/audioop_lts-0.2.2-cp313-abi3-win32.whl", hash = "sha256:3bcddaaf6cc5935a300a8387c99f7a7fbbe212a11568ec6cf6e4bc458c048636", size = 26185, upload-time = "2025-08-05T16:42:37.04Z" }, + { url = "https://files.pythonhosted.org/packages/34/a5/9d78fdb5b844a83da8a71226c7bdae7cc638861085fff7a1d707cb4823fa/audioop_lts-0.2.2-cp313-abi3-win_amd64.whl", hash = "sha256:a2c2a947fae7d1062ef08c4e369e0ba2086049a5e598fda41122535557012e9e", size = 30503, upload-time = "2025-08-05T16:42:38.427Z" }, + { url = "https://files.pythonhosted.org/packages/34/25/20d8fde083123e90c61b51afb547bb0ea7e77bab50d98c0ab243d02a0e43/audioop_lts-0.2.2-cp313-abi3-win_arm64.whl", hash = "sha256:5f93a5db13927a37d2d09637ccca4b2b6b48c19cd9eda7b17a2e9f77edee6a6f", size = 24173, upload-time = "2025-08-05T16:42:39.704Z" }, + { url = "https://files.pythonhosted.org/packages/5c/73/413b5a2804091e2c7d5def1d618e4837f1cb82464e230f827226278556b7/audioop_lts-0.2.2-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:f9ee9b52f5f857fbaf9d605a360884f034c92c1c23021fb90b2e39b8e64bede6", size = 47104, upload-time = "2025-08-05T16:42:58.518Z" }, + { url = "https://files.pythonhosted.org/packages/ae/8c/daa3308dc6593944410c2c68306a5e217f5c05b70a12e70228e7dd42dc5c/audioop_lts-0.2.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:49ee1a41738a23e98d98b937a0638357a2477bc99e61b0f768a8f654f45d9b7a", size = 27754, upload-time = "2025-08-05T16:43:00.132Z" }, + { url = "https://files.pythonhosted.org/packages/4e/86/c2e0f627168fcf61781a8f72cab06b228fe1da4b9fa4ab39cfb791b5836b/audioop_lts-0.2.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5b00be98ccd0fc123dcfad31d50030d25fcf31488cde9e61692029cd7394733b", size = 27332, upload-time = "2025-08-05T16:43:01.666Z" }, + { url = "https://files.pythonhosted.org/packages/c7/bd/35dce665255434f54e5307de39e31912a6f902d4572da7c37582809de14f/audioop_lts-0.2.2-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a6d2e0f9f7a69403e388894d4ca5ada5c47230716a03f2847cfc7bd1ecb589d6", size = 92396, upload-time = "2025-08-05T16:43:02.991Z" }, + { url = "https://files.pythonhosted.org/packages/2d/d2/deeb9f51def1437b3afa35aeb729d577c04bcd89394cb56f9239a9f50b6f/audioop_lts-0.2.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f9b0b8a03ef474f56d1a842af1a2e01398b8f7654009823c6d9e0ecff4d5cfbf", size = 91811, upload-time = "2025-08-05T16:43:04.096Z" }, + { url = "https://files.pythonhosted.org/packages/76/3b/09f8b35b227cee28cc8231e296a82759ed80c1a08e349811d69773c48426/audioop_lts-0.2.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2b267b70747d82125f1a021506565bdc5609a2b24bcb4773c16d79d2bb260bbd", size = 100483, upload-time = "2025-08-05T16:43:05.085Z" }, + { url = "https://files.pythonhosted.org/packages/0b/15/05b48a935cf3b130c248bfdbdea71ce6437f5394ee8533e0edd7cfd93d5e/audioop_lts-0.2.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0337d658f9b81f4cd0fdb1f47635070cc084871a3d4646d9de74fdf4e7c3d24a", size = 103885, upload-time = "2025-08-05T16:43:06.197Z" }, + { url = "https://files.pythonhosted.org/packages/83/80/186b7fce6d35b68d3d739f228dc31d60b3412105854edb975aa155a58339/audioop_lts-0.2.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:167d3b62586faef8b6b2275c3218796b12621a60e43f7e9d5845d627b9c9b80e", size = 84899, upload-time = "2025-08-05T16:43:07.291Z" }, + { url = "https://files.pythonhosted.org/packages/49/89/c78cc5ac6cb5828f17514fb12966e299c850bc885e80f8ad94e38d450886/audioop_lts-0.2.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0d9385e96f9f6da847f4d571ce3cb15b5091140edf3db97276872647ce37efd7", size = 89998, upload-time = "2025-08-05T16:43:08.335Z" }, + { url = "https://files.pythonhosted.org/packages/4c/4b/6401888d0c010e586c2ca50fce4c903d70a6bb55928b16cfbdfd957a13da/audioop_lts-0.2.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:48159d96962674eccdca9a3df280e864e8ac75e40a577cc97c5c42667ffabfc5", size = 99046, upload-time = "2025-08-05T16:43:09.367Z" }, + { url = "https://files.pythonhosted.org/packages/de/f8/c874ca9bb447dae0e2ef2e231f6c4c2b0c39e31ae684d2420b0f9e97ee68/audioop_lts-0.2.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:8fefe5868cd082db1186f2837d64cfbfa78b548ea0d0543e9b28935ccce81ce9", size = 84843, upload-time = "2025-08-05T16:43:10.749Z" }, + { url = "https://files.pythonhosted.org/packages/3e/c0/0323e66f3daebc13fd46b36b30c3be47e3fc4257eae44f1e77eb828c703f/audioop_lts-0.2.2-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:58cf54380c3884fb49fdd37dfb7a772632b6701d28edd3e2904743c5e1773602", size = 94490, upload-time = "2025-08-05T16:43:12.131Z" }, + { url = "https://files.pythonhosted.org/packages/98/6b/acc7734ac02d95ab791c10c3f17ffa3584ccb9ac5c18fd771c638ed6d1f5/audioop_lts-0.2.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:088327f00488cdeed296edd9215ca159f3a5a5034741465789cad403fcf4bec0", size = 92297, upload-time = "2025-08-05T16:43:13.139Z" }, + { url = "https://files.pythonhosted.org/packages/13/c3/c3dc3f564ce6877ecd2a05f8d751b9b27a8c320c2533a98b0c86349778d0/audioop_lts-0.2.2-cp314-cp314t-win32.whl", hash = "sha256:068aa17a38b4e0e7de771c62c60bbca2455924b67a8814f3b0dee92b5820c0b3", size = 27331, upload-time = "2025-08-05T16:43:14.19Z" }, + { url = "https://files.pythonhosted.org/packages/72/bb/b4608537e9ffcb86449091939d52d24a055216a36a8bf66b936af8c3e7ac/audioop_lts-0.2.2-cp314-cp314t-win_amd64.whl", hash = "sha256:a5bf613e96f49712073de86f20dbdd4014ca18efd4d34ed18c75bd808337851b", size = 31697, upload-time = "2025-08-05T16:43:15.193Z" }, + { url = "https://files.pythonhosted.org/packages/f6/22/91616fe707a5c5510de2cac9b046a30defe7007ba8a0c04f9c08f27df312/audioop_lts-0.2.2-cp314-cp314t-win_arm64.whl", hash = "sha256:b492c3b040153e68b9fdaff5913305aaaba5bb433d8a7f73d5cf6a64ed3cc1dd", size = 25206, upload-time = "2025-08-05T16:43:16.444Z" }, +] + +[[package]] +name = "bandit" +version = "1.9.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "pyyaml" }, + { name = "rich" }, + { name = "stevedore" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/aa/c3/0cb80dfe0f3076e5da7e4c5ad8e57bac6ac357ff4a6406205501cade4965/bandit-1.9.4.tar.gz", hash = "sha256:b589e5de2afe70bd4d53fa0c1da6199f4085af666fde00e8a034f152a52cd628", size = 4242677, upload-time = "2026-02-25T06:44:15.503Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/05/a4/a26d5b25671d27e03afb5401a0be5899d94ff8fab6a698b1ac5be3ec29ef/bandit-1.9.4-py3-none-any.whl", hash = "sha256:f89ffa663767f5a0585ea075f01020207e966a9c0f2b9ef56a57c7963a3f6f8e", size = 134741, upload-time = "2026-02-25T06:44:13.694Z" }, +] + +[[package]] +name = "billiard" +version = "4.2.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/58/23/b12ac0bcdfb7360d664f40a00b1bda139cbbbced012c34e375506dbd0143/billiard-4.2.4.tar.gz", hash = "sha256:55f542c371209e03cd5862299b74e52e4fbcba8250ba611ad94276b369b6a85f", size = 156537, upload-time = "2025-11-30T13:28:48.52Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/87/8bab77b323f16d67be364031220069f79159117dd5e43eeb4be2fef1ac9b/billiard-4.2.4-py3-none-any.whl", hash = "sha256:525b42bdec68d2b983347ac312f892db930858495db601b5836ac24e6477cde5", size = 87070, upload-time = "2025-11-30T13:28:47.016Z" }, +] + +[[package]] +name = "celery" +version = "5.6.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "billiard" }, + { name = "click" }, + { name = "click-didyoumean" }, + { name = "click-plugins" }, + { name = "click-repl" }, + { name = "kombu" }, + { name = "python-dateutil" }, + { name = "tzlocal" }, + { name = "vine" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e8/b4/a1233943ab5c8ea05fb877a88a0a0622bf47444b99e4991a8045ac37ea1d/celery-5.6.3.tar.gz", hash = "sha256:177006bd2054b882e9f01be59abd8529e88879ef50d7918a7050c5a9f4e12912", size = 1742243, upload-time = "2026-03-26T12:14:51.76Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cf/c9/6eccdda96e098f7ae843162db2d3c149c6931a24fda69fe4ab84d0027eb5/celery-5.6.3-py3-none-any.whl", hash = "sha256:0808f42f80909c4d5833202360ffafb2a4f83f4d8e23e1285d926610e9a7afa6", size = 451235, upload-time = "2026-03-26T12:14:49.491Z" }, +] + +[[package]] +name = "certifi" +version = "2026.5.20" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/ce/ee2ecad540810a79593028e88299baeae54d346cc7a0d94b6199988b89b1/certifi-2026.5.20.tar.gz", hash = "sha256:69dea482ab64caa7b9f6aba1c6bf48bb6a5448d1c0f1b17ab42ad8c763a5344d", size = 135422, upload-time = "2026-05-20T11:46:50.073Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/59/8c/57e832b7af6d7c5abe66eb3fbe3a3a32f4d11ea23a1aa7131371035be991/certifi-2026.5.20-py3-none-any.whl", hash = "sha256:3c52e209ba0a4ad7aebe60436a4ab349c39e1e602e8c134221e546902ad25897", size = 134134, upload-time = "2026-05-20T11:46:48.578Z" }, +] + +[[package]] +name = "cffi" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320, upload-time = "2025-09-08T23:23:18.087Z" }, + { url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487, upload-time = "2025-09-08T23:23:19.622Z" }, + { url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" }, + { url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" }, + { url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" }, + { url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" }, + { url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" }, + { url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" }, + { url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328, upload-time = "2025-09-08T23:23:44.61Z" }, + { url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650, upload-time = "2025-09-08T23:23:45.848Z" }, + { url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687, upload-time = "2025-09-08T23:23:47.105Z" }, + { url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", size = 188773, upload-time = "2025-09-08T23:23:29.347Z" }, + { url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", size = 185013, upload-time = "2025-09-08T23:23:30.63Z" }, + { url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" }, + { url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" }, + { url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" }, + { url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" }, + { url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" }, + { url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" }, + { url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" }, + { url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" }, + { url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" }, +] + +[[package]] +name = "cfgv" +version = "3.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4e/b5/721b8799b04bf9afe054a3899c6cf4e880fcf8563cc71c15610242490a0c/cfgv-3.5.0.tar.gz", hash = "sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132", size = 7334, upload-time = "2025-11-19T20:55:51.612Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0", size = 7445, upload-time = "2025-11-19T20:55:50.744Z" }, +] + +[[package]] +name = "chardet" +version = "5.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/0d/f7b6ab21ec75897ed80c17d79b15951a719226b9fababf1e40ea74d69079/chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7", size = 2069618, upload-time = "2023-08-01T19:23:02.662Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/6f/f5fbc992a329ee4e0f288c1fe0e2ad9485ed064cac731ed2fe47dcc38cbf/chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970", size = 199385, upload-time = "2023-08-01T19:23:00.661Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/a1/67fe25fac3c7642725500a3f6cfe5821ad557c3abb11c9d20d12c7008d3e/charset_normalizer-3.4.7.tar.gz", hash = "sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5", size = 144271, upload-time = "2026-04-02T09:28:39.342Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/97/c8/c67cb8c70e19ef1960b97b22ed2a1567711de46c4ddf19799923adc836c2/charset_normalizer-3.4.7-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0", size = 309234, upload-time = "2026-04-02T09:27:07.194Z" }, + { url = "https://files.pythonhosted.org/packages/99/85/c091fdee33f20de70d6c8b522743b6f831a2f1cd3ff86de4c6a827c48a76/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a", size = 208042, upload-time = "2026-04-02T09:27:08.749Z" }, + { url = "https://files.pythonhosted.org/packages/87/1c/ab2ce611b984d2fd5d86a5a8a19c1ae26acac6bad967da4967562c75114d/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b", size = 228706, upload-time = "2026-04-02T09:27:09.951Z" }, + { url = "https://files.pythonhosted.org/packages/a8/29/2b1d2cb00bf085f59d29eb773ce58ec2d325430f8c216804a0a5cd83cbca/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41", size = 224727, upload-time = "2026-04-02T09:27:11.175Z" }, + { url = "https://files.pythonhosted.org/packages/47/5c/032c2d5a07fe4d4855fea851209cca2b6f03ebeb6d4e3afdb3358386a684/charset_normalizer-3.4.7-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e", size = 215882, upload-time = "2026-04-02T09:27:12.446Z" }, + { url = "https://files.pythonhosted.org/packages/2c/c2/356065d5a8b78ed04499cae5f339f091946a6a74f91e03476c33f0ab7100/charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae", size = 200860, upload-time = "2026-04-02T09:27:13.721Z" }, + { url = "https://files.pythonhosted.org/packages/0c/cd/a32a84217ced5039f53b29f460962abb2d4420def55afabe45b1c3c7483d/charset_normalizer-3.4.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18", size = 211564, upload-time = "2026-04-02T09:27:15.272Z" }, + { url = "https://files.pythonhosted.org/packages/44/86/58e6f13ce26cc3b8f4a36b94a0f22ae2f00a72534520f4ae6857c4b81f89/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b", size = 211276, upload-time = "2026-04-02T09:27:16.834Z" }, + { url = "https://files.pythonhosted.org/packages/8f/fe/d17c32dc72e17e155e06883efa84514ca375f8a528ba2546bee73fc4df81/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356", size = 201238, upload-time = "2026-04-02T09:27:18.229Z" }, + { url = "https://files.pythonhosted.org/packages/6a/29/f33daa50b06525a237451cdb6c69da366c381a3dadcd833fa5676bc468b3/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab", size = 230189, upload-time = "2026-04-02T09:27:19.445Z" }, + { url = "https://files.pythonhosted.org/packages/b6/6e/52c84015394a6a0bdcd435210a7e944c5f94ea1055f5cc5d56c5fe368e7b/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46", size = 211352, upload-time = "2026-04-02T09:27:20.79Z" }, + { url = "https://files.pythonhosted.org/packages/8c/d7/4353be581b373033fb9198bf1da3cf8f09c1082561e8e922aa7b39bf9fe8/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44", size = 227024, upload-time = "2026-04-02T09:27:22.063Z" }, + { url = "https://files.pythonhosted.org/packages/30/45/99d18aa925bd1740098ccd3060e238e21115fffbfdcb8f3ece837d0ace6c/charset_normalizer-3.4.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72", size = 217869, upload-time = "2026-04-02T09:27:23.486Z" }, + { url = "https://files.pythonhosted.org/packages/5c/05/5ee478aa53f4bb7996482153d4bfe1b89e0f087f0ab6b294fcf92d595873/charset_normalizer-3.4.7-cp314-cp314-win32.whl", hash = "sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10", size = 148541, upload-time = "2026-04-02T09:27:25.146Z" }, + { url = "https://files.pythonhosted.org/packages/48/77/72dcb0921b2ce86420b2d79d454c7022bf5be40202a2a07906b9f2a35c97/charset_normalizer-3.4.7-cp314-cp314-win_amd64.whl", hash = "sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f", size = 159634, upload-time = "2026-04-02T09:27:26.642Z" }, + { url = "https://files.pythonhosted.org/packages/c6/a3/c2369911cd72f02386e4e340770f6e158c7980267da16af8f668217abaa0/charset_normalizer-3.4.7-cp314-cp314-win_arm64.whl", hash = "sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246", size = 148384, upload-time = "2026-04-02T09:27:28.271Z" }, + { url = "https://files.pythonhosted.org/packages/94/09/7e8a7f73d24dba1f0035fbbf014d2c36828fc1bf9c88f84093e57d315935/charset_normalizer-3.4.7-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24", size = 330133, upload-time = "2026-04-02T09:27:29.474Z" }, + { url = "https://files.pythonhosted.org/packages/8d/da/96975ddb11f8e977f706f45cddd8540fd8242f71ecdb5d18a80723dcf62c/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79", size = 216257, upload-time = "2026-04-02T09:27:30.793Z" }, + { url = "https://files.pythonhosted.org/packages/e5/e8/1d63bf8ef2d388e95c64b2098f45f84758f6d102a087552da1485912637b/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960", size = 234851, upload-time = "2026-04-02T09:27:32.44Z" }, + { url = "https://files.pythonhosted.org/packages/9b/40/e5ff04233e70da2681fa43969ad6f66ca5611d7e669be0246c4c7aaf6dc8/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4", size = 233393, upload-time = "2026-04-02T09:27:34.03Z" }, + { url = "https://files.pythonhosted.org/packages/be/c1/06c6c49d5a5450f76899992f1ee40b41d076aee9279b49cf9974d2f313d5/charset_normalizer-3.4.7-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e", size = 223251, upload-time = "2026-04-02T09:27:35.369Z" }, + { url = "https://files.pythonhosted.org/packages/2b/9f/f2ff16fb050946169e3e1f82134d107e5d4ae72647ec8a1b1446c148480f/charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1", size = 206609, upload-time = "2026-04-02T09:27:36.661Z" }, + { url = "https://files.pythonhosted.org/packages/69/d5/a527c0cd8d64d2eab7459784fb4169a0ac76e5a6fc5237337982fd61347e/charset_normalizer-3.4.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44", size = 220014, upload-time = "2026-04-02T09:27:38.019Z" }, + { url = "https://files.pythonhosted.org/packages/7e/80/8a7b8104a3e203074dc9aa2c613d4b726c0e136bad1cc734594b02867972/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e", size = 218979, upload-time = "2026-04-02T09:27:39.37Z" }, + { url = "https://files.pythonhosted.org/packages/02/9a/b759b503d507f375b2b5c153e4d2ee0a75aa215b7f2489cf314f4541f2c0/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3", size = 209238, upload-time = "2026-04-02T09:27:40.722Z" }, + { url = "https://files.pythonhosted.org/packages/c2/4e/0f3f5d47b86bdb79256e7290b26ac847a2832d9a4033f7eb2cd4bcf4bb5b/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0", size = 236110, upload-time = "2026-04-02T09:27:42.33Z" }, + { url = "https://files.pythonhosted.org/packages/96/23/bce28734eb3ed2c91dcf93abeb8a5cf393a7b2749725030bb630e554fdd8/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e", size = 219824, upload-time = "2026-04-02T09:27:43.924Z" }, + { url = "https://files.pythonhosted.org/packages/2c/6f/6e897c6984cc4d41af319b077f2f600fc8214eb2fe2d6bcb79141b882400/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb", size = 233103, upload-time = "2026-04-02T09:27:45.348Z" }, + { url = "https://files.pythonhosted.org/packages/76/22/ef7bd0fe480a0ae9b656189ec00744b60933f68b4f42a7bb06589f6f576a/charset_normalizer-3.4.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe", size = 225194, upload-time = "2026-04-02T09:27:46.706Z" }, + { url = "https://files.pythonhosted.org/packages/c5/a7/0e0ab3e0b5bc1219bd80a6a0d4d72ca74d9250cb2382b7c699c147e06017/charset_normalizer-3.4.7-cp314-cp314t-win32.whl", hash = "sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0", size = 159827, upload-time = "2026-04-02T09:27:48.053Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1d/29d32e0fb40864b1f878c7f5a0b343ae676c6e2b271a2d55cc3a152391da/charset_normalizer-3.4.7-cp314-cp314t-win_amd64.whl", hash = "sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c", size = 174168, upload-time = "2026-04-02T09:27:49.795Z" }, + { url = "https://files.pythonhosted.org/packages/de/32/d92444ad05c7a6e41fb2036749777c163baf7a0301a040cb672d6b2b1ae9/charset_normalizer-3.4.7-cp314-cp314t-win_arm64.whl", hash = "sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d", size = 153018, upload-time = "2026-04-02T09:27:51.116Z" }, + { url = "https://files.pythonhosted.org/packages/db/8f/61959034484a4a7c527811f4721e75d02d653a35afb0b6054474d8185d4c/charset_normalizer-3.4.7-py3-none-any.whl", hash = "sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d", size = 61958, upload-time = "2026-04-02T09:28:37.794Z" }, +] + +[[package]] +name = "click" +version = "8.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9b/98/518d8e5081007684232226f475082b30087d0f585e8457db087298259f49/click-8.4.1.tar.gz", hash = "sha256:918b5633eddf6b41c32d4f454bf0de810065c74e3f7dbf8ee5452f8be88d3e96", size = 353007, upload-time = "2026-05-22T04:08:37.769Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/0d/67e5b4109ea4a837e80daa87c2c696711955e40449a97e8926672534def2/click-8.4.1-py3-none-any.whl", hash = "sha256:482be17c6991b8c19c5429a1e995d9b0efdbb63172824c41f99965dc0ade8ec2", size = 116639, upload-time = "2026-05-22T04:08:35.26Z" }, +] + +[[package]] +name = "click-didyoumean" +version = "0.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/30/ce/217289b77c590ea1e7c24242d9ddd6e249e52c795ff10fac2c50062c48cb/click_didyoumean-0.3.1.tar.gz", hash = "sha256:4f82fdff0dbe64ef8ab2279bd6aa3f6a99c3b28c05aa09cbfc07c9d7fbb5a463", size = 3089, upload-time = "2024-03-24T08:22:07.499Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1b/5b/974430b5ffdb7a4f1941d13d83c64a0395114503cc357c6b9ae4ce5047ed/click_didyoumean-0.3.1-py3-none-any.whl", hash = "sha256:5c4bb6007cfea5f2fd6583a2fb6701a22a41eb98957e63d0fac41c10e7c3117c", size = 3631, upload-time = "2024-03-24T08:22:06.356Z" }, +] + +[[package]] +name = "click-plugins" +version = "1.1.1.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c3/a4/34847b59150da33690a36da3681d6bbc2ec14ee9a846bc30a6746e5984e4/click_plugins-1.1.1.2.tar.gz", hash = "sha256:d7af3984a99d243c131aa1a828331e7630f4a88a9741fd05c927b204bcf92261", size = 8343, upload-time = "2025-06-25T00:47:37.555Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3d/9a/2abecb28ae875e39c8cad711eb1186d8d14eab564705325e77e4e6ab9ae5/click_plugins-1.1.1.2-py2.py3-none-any.whl", hash = "sha256:008d65743833ffc1f5417bf0e78e8d2c23aab04d9745ba817bd3e71b0feb6aa6", size = 11051, upload-time = "2025-06-25T00:47:36.731Z" }, +] + +[[package]] +name = "click-repl" +version = "0.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "prompt-toolkit" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cb/a2/57f4ac79838cfae6912f997b4d1a64a858fb0c86d7fcaae6f7b58d267fca/click-repl-0.3.0.tar.gz", hash = "sha256:17849c23dba3d667247dc4defe1757fff98694e90fe37474f3feebb69ced26a9", size = 10449, upload-time = "2023-06-15T12:43:51.141Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/52/40/9d857001228658f0d59e97ebd4c346fe73e138c6de1bce61dc568a57c7f8/click_repl-0.3.0-py3-none-any.whl", hash = "sha256:fb7e06deb8da8de86180a33a9da97ac316751c094c6899382da7feeeeb51b812", size = 10289, upload-time = "2023-06-15T12:43:48.626Z" }, +] + +[[package]] +name = "codespell" +version = "2.4.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2d/9d/1d0903dff693160f893ca6abcabad545088e7a2ee0a6deae7c24e958be69/codespell-2.4.2.tar.gz", hash = "sha256:3c33be9ae34543807f088aeb4832dfad8cb2dae38da61cac0a7045dd376cfdf3", size = 352058, upload-time = "2026-03-05T18:10:42.936Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/42/a1/52fa05533e95fe45bcc09bcf8a503874b1c08f221a4e35608017e0938f55/codespell-2.4.2-py3-none-any.whl", hash = "sha256:97e0c1060cf46bd1d5db89a936c98db8c2b804e1fdd4b5c645e82a1ec6b1f886", size = 353715, upload-time = "2026-03-05T18:10:41.398Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "coverage" +version = "7.14.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/23/7f/d0720730a397a999ffc0fd3f5bebef347338e3a47b727da66fbb228e2ff2/coverage-7.14.0.tar.gz", hash = "sha256:057a6af2f160a85384cde4ab36f0d2777bae1057bae255f95413cdd382aa5c74", size = 919489, upload-time = "2026-05-10T18:02:31.397Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1c/18/b9a6586d73992807c26f9a5f274131be3d76b56b18a82b9392e2a25d2e45/coverage-7.14.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:9aed9fa983514ca032790f3fe0d1c0e42ca7e16b42432af1706b50a9a46bef5d", size = 220036, upload-time = "2026-05-10T18:01:33.057Z" }, + { url = "https://files.pythonhosted.org/packages/f3/9b/4165a1d56ddc302a0e2d518fd9d412a4fd0b57562618c78c5f21c57194f5/coverage-7.14.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ba3b8390db29296dbbf49e91b6fe08f990743a90c8f447ba4c2ffc29670dfa63", size = 220368, upload-time = "2026-05-10T18:01:34.705Z" }, + { url = "https://files.pythonhosted.org/packages/69/aa/c12e52a5ba148d9995229d557e3be6e554fe469addc0e9241b2f0956d8ea/coverage-7.14.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3a5d8e876dfa2f102e970b183863d6dedd023d3c0eeca1fe7a9787bc5f28b212", size = 251417, upload-time = "2026-05-10T18:01:36.949Z" }, + { url = "https://files.pythonhosted.org/packages/d7/51/ec641c26e6dca1b25a7d2035ba6ecb7c884ef1a100a9e42fbe4ce4405139/coverage-7.14.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5ebb8f4614a3787d567e610bbfdf96a4798dd69a1afb1bd8ad228d4111fe6ff3", size = 253924, upload-time = "2026-05-10T18:01:38.985Z" }, + { url = "https://files.pythonhosted.org/packages/33/c4/59c3de0bd1b538824173fd518fed51c1ce740ca5ed68e74545983f4053a9/coverage-7.14.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b9bf47223dd8db3d4c4b2e443b02bace480d428f0822c3f991600448a176c97", size = 255269, upload-time = "2026-05-10T18:01:40.957Z" }, + { url = "https://files.pythonhosted.org/packages/7b/a9/36dfa153a62040296f6e7febfdb20a5720622f6ef5a81a41e8237b9a5344/coverage-7.14.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3485a836550b303d006d57cc06e3d5afaabc642c77050b7c985a97b13e3776b8", size = 257583, upload-time = "2026-05-10T18:01:42.607Z" }, + { url = "https://files.pythonhosted.org/packages/26/7b/cc2c048d4114d9ab1c2409e9ee365e5ae10736df6dffcfc9444effa6c708/coverage-7.14.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3e7e88110bae996d199d1693ca8ec3fd52441d426401ae963437598667b4c5eb", size = 251434, upload-time = "2026-05-10T18:01:44.537Z" }, + { url = "https://files.pythonhosted.org/packages/ee/df/6770eaa576e604575e9a78055313250faef5faa84bd6f71a39fece519c43/coverage-7.14.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:15228a6800ce7bdf1b74800595e56db7138cecb338fdbf044806e10dcf182dfe", size = 253280, upload-time = "2026-05-10T18:01:46.175Z" }, + { url = "https://files.pythonhosted.org/packages/ad/9e/1c0264514a3f98259a6d64765a397b2c8373e3ba59ee722a4802d3ec0c61/coverage-7.14.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:9d26ac7f5398bafc5b57421ad994e8a4749e8a7a0e62d05ec7d53014d5963bfa", size = 251241, upload-time = "2026-05-10T18:01:48.732Z" }, + { url = "https://files.pythonhosted.org/packages/64/16/4efdf3e3c4079cdbf0ece56a2fea872df9e8a3e15a13a0af4400e1075944/coverage-7.14.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2fb73254ff43c911c967a899e1359bc5049b4b115d6e8fbdde4937d0a2246cd5", size = 255516, upload-time = "2026-05-10T18:01:50.819Z" }, + { url = "https://files.pythonhosted.org/packages/93/69/b1de96346603881b3d1bc8d6447c83200e1c9700ffbaff926ba01ff5724c/coverage-7.14.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:454a380af72c6adada298ed270d38c7a391288198dbfb8467f786f588751a90c", size = 251059, upload-time = "2026-05-10T18:01:52.773Z" }, + { url = "https://files.pythonhosted.org/packages/a4/66/2881853e0363a5e0a724d1103e53650795367471b6afb234f8b49e713bc6/coverage-7.14.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:65c86fb646d2bd2972e96bd1a8b45817ed907cee68655d6295fe7ec031d04cca", size = 252716, upload-time = "2026-05-10T18:01:54.506Z" }, + { url = "https://files.pythonhosted.org/packages/55/5c/0d3305d002c41dcde873dbe456491e663dc55152ca526b630b5c47efd62f/coverage-7.14.0-cp314-cp314-win32.whl", hash = "sha256:6a6516b02a6101398e19a3f44820f69bab2590697f7def4331f668b14adaf828", size = 222788, upload-time = "2026-05-10T18:01:56.487Z" }, + { url = "https://files.pythonhosted.org/packages/f9/58/6e1b8f52fdc3184b47dc5037f5070d83a3d11042db1594b02d2a44d786c8/coverage-7.14.0-cp314-cp314-win_amd64.whl", hash = "sha256:45e0f79d8351fa76e256716df91eab12890d32678b9590df7ae1042e4bd4cf5d", size = 223600, upload-time = "2026-05-10T18:01:58.497Z" }, + { url = "https://files.pythonhosted.org/packages/00/70/a18c408e674bc26281cadaedc7351f929bd2094e191e4b15271c30b084cc/coverage-7.14.0-cp314-cp314-win_arm64.whl", hash = "sha256:4b899594a8b2d81e5cc064a0d7f9cac2081fed91049456cae7676787e41549c9", size = 222168, upload-time = "2026-05-10T18:02:00.411Z" }, + { url = "https://files.pythonhosted.org/packages/3d/89/2681f071d238b62aff8dfc2ab44fc24cfdb38d1c01f391a80522ff5d3a16/coverage-7.14.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:f580f8c80acd94ac72e863efe2cab791d8c38d153e0b463b92dfa000d5c84cd1", size = 220766, upload-time = "2026-05-10T18:02:02.313Z" }, + { url = "https://files.pythonhosted.org/packages/bd/c7/c987babafd9207ffa1995e1ef1f9b26762cf4963aa768a66b6f0501e4616/coverage-7.14.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a2bd259c442cd43c49b30fbafc51776eb19ea396faf159d26a83e6a0a5f13b0c", size = 221035, upload-time = "2026-05-10T18:02:04.017Z" }, + { url = "https://files.pythonhosted.org/packages/5a/e9/d6a5ac3b333088143d6fc877d398a9a674dc03124a2f776e131f03864823/coverage-7.14.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a706b908dfa85538863504c624b237a3cc34232bf403c057414ebfdb3b4d9f84", size = 262405, upload-time = "2026-05-10T18:02:05.915Z" }, + { url = "https://files.pythonhosted.org/packages/38/b1/e70838d29a7c08e22d44398a46db90815bbcbf28de06992bd9210d1a8d8e/coverage-7.14.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7333cd944ee4393b9b3d3c1b598c936d4fc8d70573a4c7dacfec5590dd50e436", size = 264530, upload-time = "2026-05-10T18:02:07.582Z" }, + { url = "https://files.pythonhosted.org/packages/6b/73/5c31ef97763288d03d9995152b96d5475b527c63d91c84b01caea894b83a/coverage-7.14.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f162bc9a15b82d947b02651b0c7e1609d6f7a8735ca330cfadec8481dd97d5a", size = 266932, upload-time = "2026-05-10T18:02:09.401Z" }, + { url = "https://files.pythonhosted.org/packages/e1/76/dd56d80f29c5f05b4d76f7e7c6d47cafacae017189c75c5759d24f9ff0cc/coverage-7.14.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:362cb78e01a5dc82009d88004cf60f2e6b6d6fcbfdec05b05af73b0abf40118f", size = 268062, upload-time = "2026-05-10T18:02:11.399Z" }, + { url = "https://files.pythonhosted.org/packages/6e/c7/27ba85cd5b95614f159ff93ebff1901584a8d192e2e5e24c4943a7453f59/coverage-7.14.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:acebd068fca5512c3a6fde9c045f901613478781a73f0e82b307b214daef23fb", size = 261504, upload-time = "2026-05-10T18:02:13.257Z" }, + { url = "https://files.pythonhosted.org/packages/13/2e/e8149f60ab5d5684c6eee881bdf34b127115cddbb958b196768dd9d63473/coverage-7.14.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:29fe3da551dface75deb2ccbf87b6b66e2e7ef38f6d89050b428be94afff3490", size = 264398, upload-time = "2026-05-10T18:02:15.063Z" }, + { url = "https://files.pythonhosted.org/packages/d9/7f/1261b025285323225f4b4abffa5a643649dfd67e25ddca7ebcbdea3b7cb3/coverage-7.14.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:b4cc4fce8672fffcb09b0eafc167b396b3ba53c4a7230f54b7aaffbf6c835fa9", size = 262000, upload-time = "2026-05-10T18:02:16.756Z" }, + { url = "https://files.pythonhosted.org/packages/d3/dc/829c54f60b9d08389439c00f813c752781c496fc5788c78d8006db4b4f2b/coverage-7.14.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:5d4a51aad8ba8bdcd2b8bd8f03d4aca19693fa2327a3470e4718a25b03481020", size = 265732, upload-time = "2026-05-10T18:02:18.817Z" }, + { url = "https://files.pythonhosted.org/packages/ed/b0/70bd1419941652fa062689cba9c3eeafb8f5e6fbb890bce41c3bdda5dbd6/coverage-7.14.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:9f323af3e1e4f68b60b7b247e37b8515563a61375518fa59de1af48ba28a3db6", size = 260847, upload-time = "2026-05-10T18:02:20.528Z" }, + { url = "https://files.pythonhosted.org/packages/f2/73/be40b2390656c654d35ea0015ea7ba3d945769cf80790ad5e0bb2d56d2ba/coverage-7.14.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:1a0abc7342ea9711c469dd8b821c6c311e6bc6aac1442e5fbd6b27fae0a8f3db", size = 263166, upload-time = "2026-05-10T18:02:22.337Z" }, + { url = "https://files.pythonhosted.org/packages/29/55/4a643f712fcf7cf2881f8ec1e0ccb7b164aff3108f69b51801246c8799f2/coverage-7.14.0-cp314-cp314t-win32.whl", hash = "sha256:a9f864ef57b7172e2db87a096642dd51e179e085ab6b2c371c29e885f65c8fb2", size = 223573, upload-time = "2026-05-10T18:02:24.11Z" }, + { url = "https://files.pythonhosted.org/packages/27/96/3acae5da0953be042c0b4dea6d6789d2f080701c77b88e44d5bd41b9219b/coverage-7.14.0-cp314-cp314t-win_amd64.whl", hash = "sha256:29943e552fdc08e082eb51400fb2f58e118a83b5542bd06531214e084399b644", size = 224680, upload-time = "2026-05-10T18:02:25.896Z" }, + { url = "https://files.pythonhosted.org/packages/93/3d/6ab5d2dd8325d838737c6f8d83d62eb6230e0d70b87b51b57bbfd08fa767/coverage-7.14.0-cp314-cp314t-win_arm64.whl", hash = "sha256:742a73ea621953b012f2c4c2219b512180dd84489acf5b1596b0aafc55b9100b", size = 222703, upload-time = "2026-05-10T18:02:27.822Z" }, + { url = "https://files.pythonhosted.org/packages/61/e8/cb8e80d6f9f55b99588625062822bf946cf03ed06315df4bd8397f5632a1/coverage-7.14.0-py3-none-any.whl", hash = "sha256:8de5b61163aee3d05c8a2beab6f47913df7981dad1baf82c414d99158c286ab1", size = 211764, upload-time = "2026-05-10T18:02:29.538Z" }, +] + +[[package]] +name = "crispy-bootstrap4" +version = "2026.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, + { name = "django-crispy-forms" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5b/cc/638d36595da9fbb2c9d0be98bf6007442a65a521b614cf4645d04311b061/crispy_bootstrap4-2026.2.tar.gz", hash = "sha256:66f8f14bf9c2c16ed94243236ed253a94e5a625afa1ee64022ce29db98c6cd85", size = 34645, upload-time = "2026-02-11T22:45:05.422Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ad/6d/b90d601ea2449cc6b35b4b08be90fb1f6ca1baf2be383ed195f7bfa91a32/crispy_bootstrap4-2026.2-py3-none-any.whl", hash = "sha256:4b2b99dfe3e3cacb548702159462110901bd38792b650b770e50c62284ac2227", size = 23178, upload-time = "2026-02-11T22:45:04.108Z" }, +] + +[[package]] +name = "cryptography" +version = "48.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9f/a9/db8f313fdcd85d767d4973515e1db101f9c71f95fced83233de224673757/cryptography-48.0.0.tar.gz", hash = "sha256:5c3932f4436d1cccb036cb0eaef46e6e2db91035166f1ad6505c3c9d5a635920", size = 832984, upload-time = "2026-05-04T22:59:38.133Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/df/3d/01f6dd9190170a5a241e0e98c2d04be3664a9e6f5b9b872cde63aff1c3dd/cryptography-48.0.0-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:0c558d2cdffd8f4bbb30fc7134c74d2ca9a476f830bb053074498fbc86f41ed6", size = 8001587, upload-time = "2026-05-04T22:57:36.803Z" }, + { url = "https://files.pythonhosted.org/packages/b2/6e/e90527eef33f309beb811cf7c982c3aeffcce8e3edb178baa4ca3ae4a6fa/cryptography-48.0.0-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f5333311663ea94f75dd408665686aaf426563556bb5283554a3539177e03b8c", size = 4690433, upload-time = "2026-05-04T22:57:40.373Z" }, + { url = "https://files.pythonhosted.org/packages/90/04/673510ed51ddff56575f306cf1617d80411ee76831ccd3097599140efdfe/cryptography-48.0.0-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7995ef305d7165c3f11ae07f2517e5a4f1d5c18da1376a0a9ed496336b69e5f3", size = 4710620, upload-time = "2026-05-04T22:57:42.935Z" }, + { url = "https://files.pythonhosted.org/packages/14/d5/e9c4ef932c8d800490c34d8bd589d64a31d5890e27ec9e9ad532be893294/cryptography-48.0.0-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:40ba1f85eaa6959837b1d51c9767e230e14612eea4ef110ee8854ada22da1bf5", size = 4696283, upload-time = "2026-05-04T22:57:45.294Z" }, + { url = "https://files.pythonhosted.org/packages/0c/29/174b9dfb60b12d59ecfc6cfa04bc88c21b42a54f01b8aae09bb6e51e4c7f/cryptography-48.0.0-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:369a6348999f94bbd53435c894377b20ab95f25a9065c283570e70150d8abc3c", size = 5296573, upload-time = "2026-05-04T22:57:47.933Z" }, + { url = "https://files.pythonhosted.org/packages/95/38/0d29a6fd7d0d1373f0c0c88a04ba20e359b257753ac497564cd660fc1d55/cryptography-48.0.0-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:a0e692c683f4df67815a2d258b324e66f4738bd7a96a218c826dce4f4bd05d8f", size = 4743677, upload-time = "2026-05-04T22:57:50.067Z" }, + { url = "https://files.pythonhosted.org/packages/30/be/eef653013d5c63b6a490529e0316f9ac14a37602965d4903efed1399f32b/cryptography-48.0.0-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:18349bbc56f4743c8b12dc32e2bccb2cf83ee8b69a3bba74ef8ae857e26b3d25", size = 4330808, upload-time = "2026-05-04T22:57:52.301Z" }, + { url = "https://files.pythonhosted.org/packages/84/9e/500463e87abb7a0a0f9f256ec21123ecde0a7b5541a15e840ea54551fd81/cryptography-48.0.0-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:7e8eac43dfca5c4cccc6dad9a80504436fca53bb9bc3100a2386d730fbe6b602", size = 4695941, upload-time = "2026-05-04T22:57:54.603Z" }, + { url = "https://files.pythonhosted.org/packages/e3/dc/7303087450c2ec9e7fbb750e17c2abfbc658f23cbd0e54009509b7cc4091/cryptography-48.0.0-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:9ccdac7d40688ecb5a3b4a604b8a88c8002e3442d6c60aead1db2a89a041560c", size = 5252579, upload-time = "2026-05-04T22:57:57.207Z" }, + { url = "https://files.pythonhosted.org/packages/d0/c0/7101d3b7215edcdc90c45da544961fd8ed2d6448f77577460fa75a8443f7/cryptography-48.0.0-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:bd72e68b06bb1e96913f97dd4901119bc17f39d4586a5adf2d3e47bc2b9d58b5", size = 4743326, upload-time = "2026-05-04T22:57:59.535Z" }, + { url = "https://files.pythonhosted.org/packages/ac/d8/5b833bad13016f562ab9d063d68199a4bd121d18458e439515601d3357ec/cryptography-48.0.0-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:59baa2cb386c4f0b9905bd6eb4c2a79a69a128408fd31d32ca4d7102d4156321", size = 4826672, upload-time = "2026-05-04T22:58:01.996Z" }, + { url = "https://files.pythonhosted.org/packages/98/e1/7074eb8bf3c135558c73fc2bcf0f5633f912e6fb87e868a55c454080ef09/cryptography-48.0.0-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:9249e3cd978541d665967ac2cb2787fd6a62bddf1e75b3e347a594d7dacf4f74", size = 4972574, upload-time = "2026-05-04T22:58:03.968Z" }, + { url = "https://files.pythonhosted.org/packages/04/70/e5a1b41d325f797f39427aa44ef8baf0be500065ab6d8e10369d850d4a4f/cryptography-48.0.0-cp311-abi3-win32.whl", hash = "sha256:9c459db21422be75e2809370b829a87eb37f74cd785fc4aa9ea1e5f43b47cda4", size = 3294868, upload-time = "2026-05-04T22:58:06.467Z" }, + { url = "https://files.pythonhosted.org/packages/f4/ac/8ac51b4a5fc5932eb7ee5c517ba7dc8cd834f0048962b6b352f00f41ebf9/cryptography-48.0.0-cp311-abi3-win_amd64.whl", hash = "sha256:5b012212e08b8dd5edc78ef54da83dd9892fd9105323b3993eff6bea65dc21d7", size = 3817107, upload-time = "2026-05-04T22:58:08.845Z" }, + { url = "https://files.pythonhosted.org/packages/6b/84/70e3feea9feea87fd7cbe77efb2712ae1e3e6edf10749dc6e95f4e60e455/cryptography-48.0.0-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:3cb07a3ed6431663cd321ea8a000a1314c74211f823e4177fefa2255e057d1ec", size = 7986556, upload-time = "2026-05-04T22:58:11.172Z" }, + { url = "https://files.pythonhosted.org/packages/89/6e/18e07a618bb5442ba10cf4df16e99c071365528aa570dfcb8c02e25a303b/cryptography-48.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8c7378637d7d88016fa6791c159f698b3d3eed28ebf844ac36b9dc04a14dae18", size = 4684776, upload-time = "2026-05-04T22:58:13.712Z" }, + { url = "https://files.pythonhosted.org/packages/be/6a/4ea3b4c6c6759794d5ee2103c304a5076dc4b19ae1f9fe47dba439e159e9/cryptography-48.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cc90c0b39b2e3c65ef52c804b72e3c58f8a04ab2a1871272798e5f9572c17d20", size = 4698121, upload-time = "2026-05-04T22:58:16.448Z" }, + { url = "https://files.pythonhosted.org/packages/2f/59/6ff6ad6cae03bb887da2a5860b2c9805f8dac969ef01ce563336c49bd1d1/cryptography-48.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:76341972e1eff8b4bea859f09c0d3e64b96ce931b084f9b9b7db8ef364c30eff", size = 4690042, upload-time = "2026-05-04T22:58:18.544Z" }, + { url = "https://files.pythonhosted.org/packages/ca/b4/fc334ed8cfd705aca282fe4d8f5ae64a8e0f74932e9feecb344610cf6e4d/cryptography-48.0.0-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:55b7718303bf06a5753dcdccf2f3945cf18ad7bffde41b61226e4db31ab89a9c", size = 5282526, upload-time = "2026-05-04T22:58:20.75Z" }, + { url = "https://files.pythonhosted.org/packages/11/08/9f8c5386cc4cd90d8255c7cdd0f5baf459a08502a09de30dc51f553d38dc/cryptography-48.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:a64697c641c7b1b2178e573cbc31c7c6684cd56883a478d75143dbb7118036db", size = 4733116, upload-time = "2026-05-04T22:58:23.627Z" }, + { url = "https://files.pythonhosted.org/packages/b8/77/99307d7574045699f8805aa500fa0fb83422d115b5400a064ddd306d7750/cryptography-48.0.0-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:561215ea3879cb1cbbf272867e2efda62476f240fb58c64de6b393ae19246741", size = 4316030, upload-time = "2026-05-04T22:58:25.581Z" }, + { url = "https://files.pythonhosted.org/packages/fd/36/a608b98337af3cb2aff4818e406649d30572b7031918b04c87d979495348/cryptography-48.0.0-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:ad64688338ed4bc1a6618076ba75fd7194a5f1797ac60b47afe926285adb3166", size = 4689640, upload-time = "2026-05-04T22:58:27.747Z" }, + { url = "https://files.pythonhosted.org/packages/dd/a6/825010a291b4438aecc1f568bc428189fc1175515223632477c07dc0a6df/cryptography-48.0.0-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:906cbf0670286c6e0044156bc7d4af9cbb0ef6db9f73e52c3ec56ba6bdde5336", size = 5237657, upload-time = "2026-05-04T22:58:29.848Z" }, + { url = "https://files.pythonhosted.org/packages/b9/09/4e76a09b4caa29aad535ddc806f5d4c5d01885bd978bd984fbc6ca032cae/cryptography-48.0.0-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:ea8990436d914540a40ab24b6a77c0969695ed52f4a4874c5137ccf7045a7057", size = 4732362, upload-time = "2026-05-04T22:58:32.009Z" }, + { url = "https://files.pythonhosted.org/packages/18/78/444fa04a77d0cb95f417dda20d450e13c56ba8e5220fc892a1658f44f882/cryptography-48.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c18684a7f0cc9a3cb60328f496b8e3372def7c5d2df39ac267878b05565aaaae", size = 4819580, upload-time = "2026-05-04T22:58:34.254Z" }, + { url = "https://files.pythonhosted.org/packages/38/85/ea67067c70a1fd4be2c63d35eeed82658023021affccc7b17705f8527dd2/cryptography-48.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9be5aafa5736574f8f15f262adc81b2a9869e2cfe9014d52a44633905b40d52c", size = 4963283, upload-time = "2026-05-04T22:58:36.376Z" }, + { url = "https://files.pythonhosted.org/packages/75/54/cc6d0f3deac3e81c7f847e8a189a12b6cdd65059b43dad25d4316abd849a/cryptography-48.0.0-cp314-cp314t-win32.whl", hash = "sha256:c17dfe85494deaeddc5ce251aebd1d60bbe6afc8b62071bb0b469431a000124f", size = 3270954, upload-time = "2026-05-04T22:58:38.791Z" }, + { url = "https://files.pythonhosted.org/packages/49/67/cc947e288c0758a4e5473d1dcb743037ab7785541265a969240b8885441a/cryptography-48.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27241b1dc9962e056062a8eef1991d02c3a24569c95975bd2322a8a52c6e5e12", size = 3797313, upload-time = "2026-05-04T22:58:40.746Z" }, + { url = "https://files.pythonhosted.org/packages/f2/63/61d4a4e1c6b6bab6ce1e213cd36a24c415d90e76d78c5eb8577c5541d2e8/cryptography-48.0.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:58d00498e8933e4a194f3076aee1b4a97dfec1a6da444535755822fe5d8b0b86", size = 7983482, upload-time = "2026-05-04T22:58:43.769Z" }, + { url = "https://files.pythonhosted.org/packages/d5/ac/f5b5995b87770c693e2596559ffafe195b4033a57f14a82268a2842953f3/cryptography-48.0.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:614d0949f4790582d2cc25553abd09dd723025f0c0e7c67376a1d77196743d6e", size = 4683266, upload-time = "2026-05-04T22:58:46.064Z" }, + { url = "https://files.pythonhosted.org/packages/ec/c6/8b14f67e18338fbc4adb76f66c001f5c3610b3e2d1837f268f47a347dbbb/cryptography-48.0.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7ce4bfae76319a532a2dc68f82cc32f5676ee792a983187dac07183690e5c66f", size = 4696228, upload-time = "2026-05-04T22:58:48.22Z" }, + { url = "https://files.pythonhosted.org/packages/ea/73/f808fbae9514bd91b47875b003f13e284c8c6bdfd904b7944e803937eec1/cryptography-48.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:2eb992bbd4661238c5a397594c83f5b4dc2bc5b848c365c8f991b6780efcc5c7", size = 4689097, upload-time = "2026-05-04T22:58:50.9Z" }, + { url = "https://files.pythonhosted.org/packages/93/01/d86632d7d28db8ae83221995752eeb6639ffb374c2d22955648cf8d52797/cryptography-48.0.0-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:22a5cb272895dce158b2cacdfdc3debd299019659f42947dbdac6f32d68fe832", size = 5283582, upload-time = "2026-05-04T22:58:53.017Z" }, + { url = "https://files.pythonhosted.org/packages/02/e1/50edc7a50334807cc4791fc4a0ce7468b4a1416d9138eab358bfc9a3d70b/cryptography-48.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2b4d59804e8408e2fea7d1fbaf218e5ec984325221db76e6a241a9abd6cdd95c", size = 4730479, upload-time = "2026-05-04T22:58:55.611Z" }, + { url = "https://files.pythonhosted.org/packages/6f/af/99a582b1b1641ff5911ac559beb45097cf79efd4ead4657f578ef1af2d47/cryptography-48.0.0-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:984a20b0f62a26f48a3396c72e4bc34c66e356d356bf370053066b3b6d54634a", size = 4326481, upload-time = "2026-05-04T22:58:57.607Z" }, + { url = "https://files.pythonhosted.org/packages/90/ee/89aa26a06ef0a7d7611788ffd571a7c50e368cc6a4d5eef8b4884e866edb/cryptography-48.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:5a5ed8fde7a1d09376ca0b40e68cd59c69fe23b1f9768bd5824f54681626032a", size = 4688713, upload-time = "2026-05-04T22:59:00.077Z" }, + { url = "https://files.pythonhosted.org/packages/70/ba/bcb1b0bb7a33d4c7c0c4d4c7874b4a62ae4f56113a5f4baefa362dfb1f0f/cryptography-48.0.0-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:8cd666227ef7af430aa5914a9910e0ddd703e75f039cef0825cd0da71b6b711a", size = 5238165, upload-time = "2026-05-04T22:59:02.317Z" }, + { url = "https://files.pythonhosted.org/packages/c9/70/ca4003b1ce5ca3dc3186ada51908c8a9b9ff7d5cab83cc0d43ee14ec144f/cryptography-48.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:9071196d81abc88b3516ac8cdfad32e2b66dd4a5393a8e68a961e9161ddc6239", size = 4729947, upload-time = "2026-05-04T22:59:05.255Z" }, + { url = "https://files.pythonhosted.org/packages/44/a0/4ec7cf774207905aef1a8d11c3750d5a1db805eb380ee4e16df317870128/cryptography-48.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1e2d54c8be6152856a36f0882ab231e70f8ec7f14e93cf87db8a2ed056bf160c", size = 4822059, upload-time = "2026-05-04T22:59:07.802Z" }, + { url = "https://files.pythonhosted.org/packages/1e/75/a2e55f99c16fcac7b5d6c1eb19ad8e00799854d6be5ca845f9259eae1681/cryptography-48.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a5da777e32ffed6f85a7b2b3f7c5cbc88c146bfcd0a1d7baf5fcc6c52ee35dd4", size = 4960575, upload-time = "2026-05-04T22:59:09.851Z" }, + { url = "https://files.pythonhosted.org/packages/b8/23/6e6f32143ab5d8b36ca848a502c4bcd477ae75b9e1677e3530d669062578/cryptography-48.0.0-cp39-abi3-win32.whl", hash = "sha256:77a2ccbbe917f6710e05ba9adaa25fb5075620bf3ea6fb751997875aff4ae4bd", size = 3279117, upload-time = "2026-05-04T22:59:12.019Z" }, + { url = "https://files.pythonhosted.org/packages/9d/9a/0fea98a70cf1749d41d738836f6349d97945f7c89433a259a6c2642eefeb/cryptography-48.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:16cd65b9330583e4619939b3a3843eec1e6e789744bb01e7c7e2e62e33c239c8", size = 3792100, upload-time = "2026-05-04T22:59:14.884Z" }, +] + +[[package]] +name = "defusedxml" +version = "0.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/d5/c66da9b79e5bdb124974bfe172b4daf3c984ebd9c2a06e2b8a4dc7331c72/defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", size = 75520, upload-time = "2021-03-08T10:59:26.269Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604, upload-time = "2021-03-08T10:59:24.45Z" }, +] + +[[package]] +name = "discord" +version = "2.3.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "discord-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7e/9f/0763429949416aeff9c6f33051270831b72e5582273acd28053b9b949462/discord-2.3.2.tar.gz", hash = "sha256:cc1ee2dbe6df218ca51519af355b97e87309f8230f58c7f34885feb8e8a76145", size = 1137, upload-time = "2023-08-10T21:45:07.93Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2d/38/d91ac49e8169b6c0f724f7aad26704eec07c4ecf31e067ca3d46a87e33d6/discord-2.3.2-py3-none-any.whl", hash = "sha256:d7959418799dd3b1e896685812d880169c193468b061b3431fa2a4664febd3da", size = 1132, upload-time = "2023-08-10T21:45:06.334Z" }, +] + +[[package]] +name = "discord-py" +version = "2.7.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohttp" }, + { name = "audioop-lts" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ef/57/9a2d9abdabdc9db8ef28ce0cf4129669e1c8717ba28d607b5ba357c4de3b/discord_py-2.7.1.tar.gz", hash = "sha256:24d5e6a45535152e4b98148a9dd6b550d25dc2c9fb41b6d670319411641249da", size = 1106326, upload-time = "2026-03-03T18:40:46.24Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f7/a7/17208c3b3f92319e7fad259f1c6d5a5baf8fd0654c54846ced329f83c3eb/discord_py-2.7.1-py3-none-any.whl", hash = "sha256:849dca2c63b171146f3a7f3f8acc04248098e9e6203412ce3cf2745f284f7439", size = 1227550, upload-time = "2026-03-03T18:40:44.492Z" }, +] + +[[package]] +name = "distlib" +version = "0.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d", size = 614605, upload-time = "2025-07-17T16:52:00.465Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047, upload-time = "2025-07-17T16:51:58.613Z" }, +] + +[[package]] +name = "django" +version = "6.0.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asgiref" }, + { name = "sqlparse" }, + { name = "tzdata", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5e/f1/bf85f0d29ef76abf901f193fe8fef4769d3da7794197832bc30151c071d8/django-6.0.5.tar.gz", hash = "sha256:bc6d6872e98a2864c836e42edd644b362db311147dd5aa8d5b82ba7a032f5269", size = 10924131, upload-time = "2026-05-05T13:54:39.329Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/5b/1328f8b84fce040c404f76822bf8c57d254e368e8cbd8bd67ec2b26d75f5/django-6.0.5-py3-none-any.whl", hash = "sha256:9d58a7cb49244e74c8e161d5e403a46d6209f1009ba40f5a66d6aa0d0786a8f0", size = 8368680, upload-time = "2026-05-05T13:54:33.532Z" }, +] + +[[package]] +name = "django-appconf" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d1/a2/e58bec8d7941b914af52a67c35b5709eceed2caa2848f28437f1666ed668/django_appconf-1.2.0.tar.gz", hash = "sha256:15a88d60dd942d6059f467412fe4581db632ef03018a3c183fb415d6fc9e5cec", size = 16127, upload-time = "2025-11-08T15:46:27.304Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e8/e6/4c34d94dfb74bbcbc489606e61f1924933de30d22c593dd1f429f35fbd7f/django_appconf-1.2.0-py3-none-any.whl", hash = "sha256:b81bce5ef0ceb9d84df48dfb623a32235d941c78cc5e45dbb6947f154ea277f4", size = 6500, upload-time = "2025-11-08T15:46:25.957Z" }, +] + +[[package]] +name = "django-bootstrap-modal-forms" +version = "3.0.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4f/92/d1d37315c897e2ad311242d617d87e26f507e0446bdfd6a0ef265501d138/django_bootstrap_modal_forms-3.0.5.tar.gz", hash = "sha256:322930953c68e1dcd4c5dc073612c77ff4d68c46074a55d98db2de6e7860050b", size = 38292, upload-time = "2024-09-28T13:39:55.656Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a9/e7/84a437e7d413e14627b82d6f3478960d01e88b5e927f673cee536e6907ba/django_bootstrap_modal_forms-3.0.5-py3-none-any.whl", hash = "sha256:e56bbe05fb29c5aa9e0f3c0277b0d8363b81cc6c4e4aaf152cedea883edae58a", size = 29560, upload-time = "2024-09-28T13:39:53.645Z" }, +] + +[[package]] +name = "django-compressor" +version = "4.6.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, + { name = "django-appconf" }, + { name = "rcssmin" }, + { name = "rjsmin" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a2/e4/c6d87b1341d744ceafa85eeceb2adabb1c62b795b8207cbc580fb70df8f4/django_compressor-4.6.0.tar.gz", hash = "sha256:c7478feab98f3368780591f9ee28a433350f5277dd28811f7f710f5bc6dff3c0", size = 99735, upload-time = "2025-11-10T13:12:11.439Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d5/9d/9a0ba39f33574994e5b33aea55a68e8fad72b8dd923a82300e4e91774f59/django_compressor-4.6.0-py3-none-any.whl", hash = "sha256:6e7b21020a0d86272c5e37000c33accc4ebeb77394a3dd86d775a09aae7aade4", size = 96828, upload-time = "2025-11-10T13:12:10.001Z" }, +] + +[[package]] +name = "django-crispy-forms" +version = "2.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/73/42/c2cfb672493730b963ef377b103e29871c56348a215d0ae8cf362fe8ab1e/django_crispy_forms-2.6.tar.gz", hash = "sha256:4921a1087c6cd4f9fa3c139654c1de1c1c385f8bd6729aaee530bc0121ab4b93", size = 1097838, upload-time = "2026-03-01T09:03:37.138Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/e3/4c5915a732d6ab54da8871400852b67529518eedfb6b78ecf10bbccfcabb/django_crispy_forms-2.6-py3-none-any.whl", hash = "sha256:8ee0ae28b6b0ac41ff48a65944480c049fe8d1b0047086874fd7efabf4ec1374", size = 31479, upload-time = "2026-03-01T09:03:36.048Z" }, +] + +[[package]] +name = "django-libsass" +version = "0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django-compressor" }, + { name = "libsass" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d2/6c/fe7c95536eed569960daf139726c8f83eaf8c4ae01d908c22d94d60f31c2/django-libsass-0.9.tar.gz", hash = "sha256:bfbbb55a8950bb40fa04dd416605f92da34ad1f303b10a41abc3232386ec27b5", size = 6754, upload-time = "2021-07-08T14:16:55.346Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1b/ee/65935acc5a36c418fa17d5190a4aeb339cfdf98b6a93ca1c59134cf1e6aa/django_libsass-0.9-py3-none-any.whl", hash = "sha256:5234d29100889cac79e36a0f44207ec6d275adfd2da1acb6a94b55c89fe2bd97", size = 6572, upload-time = "2021-07-08T14:16:53.501Z" }, +] + +[[package]] +name = "django-taggit" +version = "6.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/34/a6/f1beaf8f552fe90c153cc039316ebab942c23dfbc88588dde081fefca816/django_taggit-6.1.0.tar.gz", hash = "sha256:c4d1199e6df34125dd36db5eb0efe545b254dec3980ce5dd80e6bab3e78757c3", size = 38151, upload-time = "2024-09-29T08:07:39.477Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6b/34/4185c345530b91d05cb82e05d07148f481a5eb5dc2ac44e092b3daa6f206/django_taggit-6.1.0-py3-none-any.whl", hash = "sha256:ab776264bbc76cb3d7e49e1bf9054962457831bd21c3a42db9138b41956e4cf0", size = 75749, upload-time = "2024-09-29T08:07:14.612Z" }, +] + +[[package]] +name = "django-timezone-field" +version = "7.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/da/05/9b93a66452cdb8a08ab26f08d5766d2332673e659a8b2aeb73f2a904d421/django_timezone_field-7.2.1.tar.gz", hash = "sha256:def846f9e7200b7b8f2a28fcce2b78fb2d470f6a9f272b07c4e014f6ba4c6d2e", size = 13096, upload-time = "2025-12-06T23:50:44.591Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/7f/d885667401515b467f84569c56075bc9add72c9fd425fca51a25f4c997e1/django_timezone_field-7.2.1-py3-none-any.whl", hash = "sha256:276915b72c5816f57c3baf9e43f816c695ef940d1b21f91ebf6203c09bf4ad44", size = 13284, upload-time = "2025-12-06T23:50:43.302Z" }, +] + +[[package]] +name = "djangorestframework" +version = "3.17.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ca/d7/c016e69fac19ff8afdc89db9d31d9ae43ae031e4d1993b20aca179b8301a/djangorestframework-3.17.1.tar.gz", hash = "sha256:a6def5f447fe78ff853bff1d47a3c59bf38f5434b031780b351b0c73a62db1a5", size = 905742, upload-time = "2026-03-24T16:58:33.705Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/e1/2c516bdc83652b1a60c6119366ac2c0607b479ed05cd6093f916ca8928f8/djangorestframework-3.17.1-py3-none-any.whl", hash = "sha256:c3c74dd3e83a5a3efc37b3c18d92bd6f86a6791c7b7d4dff62bb068500e76457", size = 898844, upload-time = "2026-03-24T16:58:31.845Z" }, +] + +[[package]] +name = "executing" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/28/c14e053b6762b1044f34a13aab6859bbf40456d37d23aa286ac24cfd9a5d/executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4", size = 1129488, upload-time = "2025-09-01T09:48:10.866Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317, upload-time = "2025-09-01T09:48:08.5Z" }, +] + +[[package]] +name = "filelock" +version = "3.29.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b5/fe/997687a931ab51049acce6fa1f23e8f01216374ea81374ddee763c493db5/filelock-3.29.0.tar.gz", hash = "sha256:69974355e960702e789734cb4871f884ea6fe50bd8404051a3530bc07809cf90", size = 57571, upload-time = "2026-04-19T15:39:10.068Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/47/dd9a212ef6e343a6857485ffe25bba537304f1913bdbed446a23f7f592e1/filelock-3.29.0-py3-none-any.whl", hash = "sha256:96f5f6344709aa1572bbf631c640e4ebeeb519e08da902c39a001882f30ac258", size = 39812, upload-time = "2026-04-19T15:39:08.752Z" }, +] + +[[package]] +name = "flower" +version = "2.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "celery" }, + { name = "humanize" }, + { name = "prometheus-client" }, + { name = "pytz" }, + { name = "tornado" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/09/a1/357f1b5d8946deafdcfdd604f51baae9de10aafa2908d0b7322597155f92/flower-2.0.1.tar.gz", hash = "sha256:5ab717b979530770c16afb48b50d2a98d23c3e9fe39851dcf6bc4d01845a02a0", size = 3220408, upload-time = "2023-08-13T14:37:46.073Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a6/ff/ee2f67c0ff146ec98b5df1df637b2bc2d17beeb05df9f427a67bd7a7d79c/flower-2.0.1-py2.py3-none-any.whl", hash = "sha256:9db2c621eeefbc844c8dd88be64aef61e84e2deb29b271e02ab2b5b9f01068e2", size = 383553, upload-time = "2023-08-13T14:37:41.552Z" }, +] + +[[package]] +name = "frozenlist" +version = "1.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2d/f5/c831fac6cc817d26fd54c7eaccd04ef7e0288806943f7cc5bbf69f3ac1f0/frozenlist-1.8.0.tar.gz", hash = "sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad", size = 45875, upload-time = "2025-10-06T05:38:17.865Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f1/c8/85da824b7e7b9b6e7f7705b2ecaf9591ba6f79c1177f324c2735e41d36a2/frozenlist-1.8.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cee686f1f4cadeb2136007ddedd0aaf928ab95216e7691c63e50a8ec066336d0", size = 86127, upload-time = "2025-10-06T05:37:08.438Z" }, + { url = "https://files.pythonhosted.org/packages/8e/e8/a1185e236ec66c20afd72399522f142c3724c785789255202d27ae992818/frozenlist-1.8.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:119fb2a1bd47307e899c2fac7f28e85b9a543864df47aa7ec9d3c1b4545f096f", size = 49698, upload-time = "2025-10-06T05:37:09.48Z" }, + { url = "https://files.pythonhosted.org/packages/a1/93/72b1736d68f03fda5fdf0f2180fb6caaae3894f1b854d006ac61ecc727ee/frozenlist-1.8.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4970ece02dbc8c3a92fcc5228e36a3e933a01a999f7094ff7c23fbd2beeaa67c", size = 49749, upload-time = "2025-10-06T05:37:10.569Z" }, + { url = "https://files.pythonhosted.org/packages/a7/b2/fabede9fafd976b991e9f1b9c8c873ed86f202889b864756f240ce6dd855/frozenlist-1.8.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:cba69cb73723c3f329622e34bdbf5ce1f80c21c290ff04256cff1cd3c2036ed2", size = 231298, upload-time = "2025-10-06T05:37:11.993Z" }, + { url = "https://files.pythonhosted.org/packages/3a/3b/d9b1e0b0eed36e70477ffb8360c49c85c8ca8ef9700a4e6711f39a6e8b45/frozenlist-1.8.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:778a11b15673f6f1df23d9586f83c4846c471a8af693a22e066508b77d201ec8", size = 232015, upload-time = "2025-10-06T05:37:13.194Z" }, + { url = "https://files.pythonhosted.org/packages/dc/94/be719d2766c1138148564a3960fc2c06eb688da592bdc25adcf856101be7/frozenlist-1.8.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0325024fe97f94c41c08872db482cf8ac4800d80e79222c6b0b7b162d5b13686", size = 225038, upload-time = "2025-10-06T05:37:14.577Z" }, + { url = "https://files.pythonhosted.org/packages/e4/09/6712b6c5465f083f52f50cf74167b92d4ea2f50e46a9eea0523d658454ae/frozenlist-1.8.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:97260ff46b207a82a7567b581ab4190bd4dfa09f4db8a8b49d1a958f6aa4940e", size = 240130, upload-time = "2025-10-06T05:37:15.781Z" }, + { url = "https://files.pythonhosted.org/packages/f8/d4/cd065cdcf21550b54f3ce6a22e143ac9e4836ca42a0de1022da8498eac89/frozenlist-1.8.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:54b2077180eb7f83dd52c40b2750d0a9f175e06a42e3213ce047219de902717a", size = 242845, upload-time = "2025-10-06T05:37:17.037Z" }, + { url = "https://files.pythonhosted.org/packages/62/c3/f57a5c8c70cd1ead3d5d5f776f89d33110b1addae0ab010ad774d9a44fb9/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2f05983daecab868a31e1da44462873306d3cbfd76d1f0b5b69c473d21dbb128", size = 229131, upload-time = "2025-10-06T05:37:18.221Z" }, + { url = "https://files.pythonhosted.org/packages/6c/52/232476fe9cb64f0742f3fde2b7d26c1dac18b6d62071c74d4ded55e0ef94/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:33f48f51a446114bc5d251fb2954ab0164d5be02ad3382abcbfe07e2531d650f", size = 240542, upload-time = "2025-10-06T05:37:19.771Z" }, + { url = "https://files.pythonhosted.org/packages/5f/85/07bf3f5d0fb5414aee5f47d33c6f5c77bfe49aac680bfece33d4fdf6a246/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:154e55ec0655291b5dd1b8731c637ecdb50975a2ae70c606d100750a540082f7", size = 237308, upload-time = "2025-10-06T05:37:20.969Z" }, + { url = "https://files.pythonhosted.org/packages/11/99/ae3a33d5befd41ac0ca2cc7fd3aa707c9c324de2e89db0e0f45db9a64c26/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:4314debad13beb564b708b4a496020e5306c7333fa9a3ab90374169a20ffab30", size = 238210, upload-time = "2025-10-06T05:37:22.252Z" }, + { url = "https://files.pythonhosted.org/packages/b2/60/b1d2da22f4970e7a155f0adde9b1435712ece01b3cd45ba63702aea33938/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:073f8bf8becba60aa931eb3bc420b217bb7d5b8f4750e6f8b3be7f3da85d38b7", size = 231972, upload-time = "2025-10-06T05:37:23.5Z" }, + { url = "https://files.pythonhosted.org/packages/3f/ab/945b2f32de889993b9c9133216c068b7fcf257d8595a0ac420ac8677cab0/frozenlist-1.8.0-cp314-cp314-win32.whl", hash = "sha256:bac9c42ba2ac65ddc115d930c78d24ab8d4f465fd3fc473cdedfccadb9429806", size = 40536, upload-time = "2025-10-06T05:37:25.581Z" }, + { url = "https://files.pythonhosted.org/packages/59/ad/9caa9b9c836d9ad6f067157a531ac48b7d36499f5036d4141ce78c230b1b/frozenlist-1.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:3e0761f4d1a44f1d1a47996511752cf3dcec5bbdd9cc2b4fe595caf97754b7a0", size = 44330, upload-time = "2025-10-06T05:37:26.928Z" }, + { url = "https://files.pythonhosted.org/packages/82/13/e6950121764f2676f43534c555249f57030150260aee9dcf7d64efda11dd/frozenlist-1.8.0-cp314-cp314-win_arm64.whl", hash = "sha256:d1eaff1d00c7751b7c6662e9c5ba6eb2c17a2306ba5e2a37f24ddf3cc953402b", size = 40627, upload-time = "2025-10-06T05:37:28.075Z" }, + { url = "https://files.pythonhosted.org/packages/c0/c7/43200656ecc4e02d3f8bc248df68256cd9572b3f0017f0a0c4e93440ae23/frozenlist-1.8.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d3bb933317c52d7ea5004a1c442eef86f426886fba134ef8cf4226ea6ee1821d", size = 89238, upload-time = "2025-10-06T05:37:29.373Z" }, + { url = "https://files.pythonhosted.org/packages/d1/29/55c5f0689b9c0fb765055629f472c0de484dcaf0acee2f7707266ae3583c/frozenlist-1.8.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8009897cdef112072f93a0efdce29cd819e717fd2f649ee3016efd3cd885a7ed", size = 50738, upload-time = "2025-10-06T05:37:30.792Z" }, + { url = "https://files.pythonhosted.org/packages/ba/7d/b7282a445956506fa11da8c2db7d276adcbf2b17d8bb8407a47685263f90/frozenlist-1.8.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2c5dcbbc55383e5883246d11fd179782a9d07a986c40f49abe89ddf865913930", size = 51739, upload-time = "2025-10-06T05:37:32.127Z" }, + { url = "https://files.pythonhosted.org/packages/62/1c/3d8622e60d0b767a5510d1d3cf21065b9db874696a51ea6d7a43180a259c/frozenlist-1.8.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:39ecbc32f1390387d2aa4f5a995e465e9e2f79ba3adcac92d68e3e0afae6657c", size = 284186, upload-time = "2025-10-06T05:37:33.21Z" }, + { url = "https://files.pythonhosted.org/packages/2d/14/aa36d5f85a89679a85a1d44cd7a6657e0b1c75f61e7cad987b203d2daca8/frozenlist-1.8.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92db2bf818d5cc8d9c1f1fc56b897662e24ea5adb36ad1f1d82875bd64e03c24", size = 292196, upload-time = "2025-10-06T05:37:36.107Z" }, + { url = "https://files.pythonhosted.org/packages/05/23/6bde59eb55abd407d34f77d39a5126fb7b4f109a3f611d3929f14b700c66/frozenlist-1.8.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2dc43a022e555de94c3b68a4ef0b11c4f747d12c024a520c7101709a2144fb37", size = 273830, upload-time = "2025-10-06T05:37:37.663Z" }, + { url = "https://files.pythonhosted.org/packages/d2/3f/22cff331bfad7a8afa616289000ba793347fcd7bc275f3b28ecea2a27909/frozenlist-1.8.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cb89a7f2de3602cfed448095bab3f178399646ab7c61454315089787df07733a", size = 294289, upload-time = "2025-10-06T05:37:39.261Z" }, + { url = "https://files.pythonhosted.org/packages/a4/89/5b057c799de4838b6c69aa82b79705f2027615e01be996d2486a69ca99c4/frozenlist-1.8.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:33139dc858c580ea50e7e60a1b0ea003efa1fd42e6ec7fdbad78fff65fad2fd2", size = 300318, upload-time = "2025-10-06T05:37:43.213Z" }, + { url = "https://files.pythonhosted.org/packages/30/de/2c22ab3eb2a8af6d69dc799e48455813bab3690c760de58e1bf43b36da3e/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:168c0969a329b416119507ba30b9ea13688fafffac1b7822802537569a1cb0ef", size = 282814, upload-time = "2025-10-06T05:37:45.337Z" }, + { url = "https://files.pythonhosted.org/packages/59/f7/970141a6a8dbd7f556d94977858cfb36fa9b66e0892c6dd780d2219d8cd8/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:28bd570e8e189d7f7b001966435f9dac6718324b5be2990ac496cf1ea9ddb7fe", size = 291762, upload-time = "2025-10-06T05:37:46.657Z" }, + { url = "https://files.pythonhosted.org/packages/c1/15/ca1adae83a719f82df9116d66f5bb28bb95557b3951903d39135620ef157/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b2a095d45c5d46e5e79ba1e5b9cb787f541a8dee0433836cea4b96a2c439dcd8", size = 289470, upload-time = "2025-10-06T05:37:47.946Z" }, + { url = "https://files.pythonhosted.org/packages/ac/83/dca6dc53bf657d371fbc88ddeb21b79891e747189c5de990b9dfff2ccba1/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:eab8145831a0d56ec9c4139b6c3e594c7a83c2c8be25d5bcf2d86136a532287a", size = 289042, upload-time = "2025-10-06T05:37:49.499Z" }, + { url = "https://files.pythonhosted.org/packages/96/52/abddd34ca99be142f354398700536c5bd315880ed0a213812bc491cff5e4/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:974b28cf63cc99dfb2188d8d222bc6843656188164848c4f679e63dae4b0708e", size = 283148, upload-time = "2025-10-06T05:37:50.745Z" }, + { url = "https://files.pythonhosted.org/packages/af/d3/76bd4ed4317e7119c2b7f57c3f6934aba26d277acc6309f873341640e21f/frozenlist-1.8.0-cp314-cp314t-win32.whl", hash = "sha256:342c97bf697ac5480c0a7ec73cd700ecfa5a8a40ac923bd035484616efecc2df", size = 44676, upload-time = "2025-10-06T05:37:52.222Z" }, + { url = "https://files.pythonhosted.org/packages/89/76/c615883b7b521ead2944bb3480398cbb07e12b7b4e4d073d3752eb721558/frozenlist-1.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:06be8f67f39c8b1dc671f5d83aaefd3358ae5cdcf8314552c57e7ed3e6475bdd", size = 49451, upload-time = "2025-10-06T05:37:53.425Z" }, + { url = "https://files.pythonhosted.org/packages/e0/a3/5982da14e113d07b325230f95060e2169f5311b1017ea8af2a29b374c289/frozenlist-1.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:102e6314ca4da683dca92e3b1355490fed5f313b768500084fbe6371fddfdb79", size = 42507, upload-time = "2025-10-06T05:37:54.513Z" }, + { url = "https://files.pythonhosted.org/packages/9a/9a/e35b4a917281c0b8419d4207f4334c8e8c5dbf4f3f5f9ada73958d937dcc/frozenlist-1.8.0-py3-none-any.whl", hash = "sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d", size = 13409, upload-time = "2025-10-06T05:38:16.721Z" }, +] + +[[package]] +name = "httplib2" +version = "0.31.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyparsing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c1/1f/e86365613582c027dda5ddb64e1010e57a3d53e99ab8a72093fa13d565ec/httplib2-0.31.2.tar.gz", hash = "sha256:385e0869d7397484f4eab426197a4c020b606edd43372492337c0b4010ae5d24", size = 250800, upload-time = "2026-01-23T11:04:44.165Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2f/90/fd509079dfcab01102c0fdd87f3a9506894bc70afcf9e9785ef6b2b3aff6/httplib2-0.31.2-py3-none-any.whl", hash = "sha256:dbf0c2fa3862acf3c55c078ea9c0bc4481d7dc5117cae71be9514912cf9f8349", size = 91099, upload-time = "2026-01-23T11:04:42.78Z" }, +] + +[[package]] +name = "humanize" +version = "4.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/66/a3921783d54be8a6870ac4ccffcd15c4dc0dd7fcce51c6d63b8c63935276/humanize-4.15.0.tar.gz", hash = "sha256:1dd098483eb1c7ee8e32eb2e99ad1910baefa4b75c3aff3a82f4d78688993b10", size = 83599, upload-time = "2025-12-20T20:16:13.19Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c5/7b/bca5613a0c3b542420cf92bd5e5fb8ebd5435ce1011a091f66bb7693285e/humanize-4.15.0-py3-none-any.whl", hash = "sha256:b1186eb9f5a9749cd9cb8565aee77919dd7c8d076161cf44d70e59e3301e1769", size = 132203, upload-time = "2025-12-20T20:16:11.67Z" }, +] + +[[package]] +name = "icecream" +version = "2.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asttokens" }, + { name = "colorama" }, + { name = "executing" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/10/84/6ebc95844feae8a6a29c7fd57e9e3a7ac4817ffab384dc4f0ed53b8e3c46/icecream-2.2.0.tar.gz", hash = "sha256:9d7f244187f00a13f4ac77d176990e187e9c279d6cac4f7548e338291ad97343", size = 14267, upload-time = "2026-04-03T17:42:51.387Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7a/82/9707c7b0336bca53b75f52fc350956a93da66eb6be632b370bc933216fb4/icecream-2.2.0-py3-none-any.whl", hash = "sha256:f8df7343b3e787023eec22f42fbe4722df2f93099d394fd820b91e16b2e6cb56", size = 16707, upload-time = "2026-04-03T17:42:50.001Z" }, +] + +[[package]] +name = "identify" +version = "2.6.19" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/52/63/51723b5f116cc04b061cb6f5a561790abf249d25931d515cd375e063e0f4/identify-2.6.19.tar.gz", hash = "sha256:6be5020c38fcb07da56c53733538a3081ea5aa70d36a156f83044bfbf9173842", size = 99567, upload-time = "2026-04-17T18:39:50.265Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/84/d9273cd09688070a6523c4aee4663a8538721b2b755c4962aafae0011e72/identify-2.6.19-py2.py3-none-any.whl", hash = "sha256:20e6a87f786f768c092a721ad107fc9df0eb89347be9396cadf3f4abbd1fb78a", size = 99397, upload-time = "2026-04-17T18:39:49.221Z" }, +] + +[[package]] +name = "idna" +version = "3.16" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1a/88/bcf9709822fe69d02c2a6a77956c98ce6ea8ca8767a9aadcedc7eb6a2390/idna-3.16.tar.gz", hash = "sha256:d7a6da03db833450fca25d2358ac9ff06cd624577a4aea3a596d5c0f77b8e03d", size = 203770, upload-time = "2026-05-22T00:16:18.781Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/16/70255075a9859a0e3adb789b68ceb0e210dec03934245fd98d248226572f/idna-3.16-py3-none-any.whl", hash = "sha256:cc246e3a3f89580c3a951b5ad298ca4638078b2cdd4f115654332b5c26daded5", size = 74165, upload-time = "2026-05-22T00:16:16.698Z" }, +] + +[[package]] +name = "iniconfig" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, +] + +[[package]] +name = "kombu" +version = "5.6.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "amqp" }, + { name = "packaging" }, + { name = "tzdata" }, + { name = "vine" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b6/a5/607e533ed6c83ae1a696969b8e1c137dfebd5759a2e9682e26ff1b97740b/kombu-5.6.2.tar.gz", hash = "sha256:8060497058066c6f5aed7c26d7cd0d3b574990b09de842a8c5aaed0b92cc5a55", size = 472594, upload-time = "2025-12-29T20:30:07.779Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/0f/834427d8c03ff1d7e867d3db3d176470c64871753252b21b4f4897d1fa45/kombu-5.6.2-py3-none-any.whl", hash = "sha256:efcfc559da324d41d61ca311b0c64965ea35b4c55cc04ee36e55386145dace93", size = 214219, upload-time = "2025-12-29T20:30:05.74Z" }, +] + +[[package]] +name = "libsass" +version = "0.23.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/79/b4/ab091585eaa77299558e3289ca206846aefc123fb320b5656ab2542c20ad/libsass-0.23.0.tar.gz", hash = "sha256:6f209955ede26684e76912caf329f4ccb57e4a043fd77fe0e7348dd9574f1880", size = 316068, upload-time = "2024-01-06T18:53:05.404Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/13/fc1bea1de880ca935137183727c7d4dd921c4128fc08b8ddc3698ba5a8a3/libsass-0.23.0-cp38-abi3-macosx_11_0_x86_64.whl", hash = "sha256:34cae047cbbfc4ffa832a61cbb110f3c95f5471c6170c842d3fed161e40814dc", size = 1086783, upload-time = "2024-01-06T19:02:38.903Z" }, + { url = "https://files.pythonhosted.org/packages/55/2f/6af938651ff3aec0a0b00742209df1172bc297fa73531f292801693b7315/libsass-0.23.0-cp38-abi3-macosx_14_0_arm64.whl", hash = "sha256:ea97d1b45cdc2fc3590cb9d7b60f1d8915d3ce17a98c1f2d4dd47ee0d9c68ce6", size = 982759, upload-time = "2024-01-06T19:02:41.331Z" }, + { url = "https://files.pythonhosted.org/packages/fd/5a/eb5b62641df0459a3291fc206cf5bd669c0feed7814dded8edef4ade8512/libsass-0.23.0-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:4a218406d605f325d234e4678bd57126a66a88841cb95bee2caeafdc6f138306", size = 9444543, upload-time = "2024-01-06T19:02:43.191Z" }, + { url = "https://files.pythonhosted.org/packages/e5/fc/275783f5120970d859ae37d04b6a60c13bdec2aa4294b9dfa8a37b5c2513/libsass-0.23.0-cp38-abi3-win32.whl", hash = "sha256:31e86d92a5c7a551df844b72d83fc2b5e50abc6fbbb31e296f7bebd6489ed1b4", size = 775481, upload-time = "2024-01-06T19:02:46.05Z" }, + { url = "https://files.pythonhosted.org/packages/ef/20/caf3c7cf2432d85263119798c45221ddf67bdd7dae8f626d14ff8db04040/libsass-0.23.0-cp38-abi3-win_amd64.whl", hash = "sha256:a2ec85d819f353cbe807432d7275d653710d12b08ec7ef61c124a580a8352f3c", size = 872914, upload-time = "2024-01-06T19:02:47.61Z" }, +] + +[[package]] +name = "markdown-it-py" +version = "4.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, +] + +[[package]] +name = "multidict" +version = "6.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1a/c2/c2d94cbe6ac1753f3fc980da97b3d930efe1da3af3c9f5125354436c073d/multidict-6.7.1.tar.gz", hash = "sha256:ec6652a1bee61c53a3e5776b6049172c53b6aaba34f18c9ad04f82712bac623d", size = 102010, upload-time = "2026-01-26T02:46:45.979Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/91/cc/db74228a8be41884a567e88a62fd589a913708fcf180d029898c17a9a371/multidict-6.7.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8f333ec9c5eb1b7105e3b84b53141e66ca05a19a605368c55450b6ba208cb9ee", size = 75190, upload-time = "2026-01-26T02:45:10.651Z" }, + { url = "https://files.pythonhosted.org/packages/d5/22/492f2246bb5b534abd44804292e81eeaf835388901f0c574bac4eeec73c5/multidict-6.7.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:a407f13c188f804c759fc6a9f88286a565c242a76b27626594c133b82883b5c2", size = 44486, upload-time = "2026-01-26T02:45:11.938Z" }, + { url = "https://files.pythonhosted.org/packages/f1/4f/733c48f270565d78b4544f2baddc2fb2a245e5a8640254b12c36ac7ac68e/multidict-6.7.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0e161ddf326db5577c3a4cc2d8648f81456e8a20d40415541587a71620d7a7d1", size = 43219, upload-time = "2026-01-26T02:45:14.346Z" }, + { url = "https://files.pythonhosted.org/packages/24/bb/2c0c2287963f4259c85e8bcbba9182ced8d7fca65c780c38e99e61629d11/multidict-6.7.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1e3a8bb24342a8201d178c3b4984c26ba81a577c80d4d525727427460a50c22d", size = 245132, upload-time = "2026-01-26T02:45:15.712Z" }, + { url = "https://files.pythonhosted.org/packages/a7/f9/44d4b3064c65079d2467888794dea218d1601898ac50222ab8a9a8094460/multidict-6.7.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97231140a50f5d447d3164f994b86a0bed7cd016e2682f8650d6a9158e14fd31", size = 252420, upload-time = "2026-01-26T02:45:17.293Z" }, + { url = "https://files.pythonhosted.org/packages/8b/13/78f7275e73fa17b24c9a51b0bd9d73ba64bb32d0ed51b02a746eb876abe7/multidict-6.7.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6b10359683bd8806a200fd2909e7c8ca3a7b24ec1d8132e483d58e791d881048", size = 233510, upload-time = "2026-01-26T02:45:19.356Z" }, + { url = "https://files.pythonhosted.org/packages/4b/25/8167187f62ae3cbd52da7893f58cb036b47ea3fb67138787c76800158982/multidict-6.7.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:283ddac99f7ac25a4acadbf004cb5ae34480bbeb063520f70ce397b281859362", size = 264094, upload-time = "2026-01-26T02:45:20.834Z" }, + { url = "https://files.pythonhosted.org/packages/a1/e7/69a3a83b7b030cf283fb06ce074a05a02322359783424d7edf0f15fe5022/multidict-6.7.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:538cec1e18c067d0e6103aa9a74f9e832904c957adc260e61cd9d8cf0c3b3d37", size = 260786, upload-time = "2026-01-26T02:45:22.818Z" }, + { url = "https://files.pythonhosted.org/packages/fe/3b/8ec5074bcfc450fe84273713b4b0a0dd47c0249358f5d82eb8104ffe2520/multidict-6.7.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7eee46ccb30ff48a1e35bb818cc90846c6be2b68240e42a78599166722cea709", size = 248483, upload-time = "2026-01-26T02:45:24.368Z" }, + { url = "https://files.pythonhosted.org/packages/48/5a/d5a99e3acbca0e29c5d9cba8f92ceb15dce78bab963b308ae692981e3a5d/multidict-6.7.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fa263a02f4f2dd2d11a7b1bb4362aa7cb1049f84a9235d31adf63f30143469a0", size = 248403, upload-time = "2026-01-26T02:45:25.982Z" }, + { url = "https://files.pythonhosted.org/packages/35/48/e58cd31f6c7d5102f2a4bf89f96b9cf7e00b6c6f3d04ecc44417c00a5a3c/multidict-6.7.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:2e1425e2f99ec5bd36c15a01b690a1a2456209c5deed58f95469ffb46039ccbb", size = 240315, upload-time = "2026-01-26T02:45:27.487Z" }, + { url = "https://files.pythonhosted.org/packages/94/33/1cd210229559cb90b6786c30676bb0c58249ff42f942765f88793b41fdce/multidict-6.7.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:497394b3239fc6f0e13a78a3e1b61296e72bf1c5f94b4c4eb80b265c37a131cd", size = 245528, upload-time = "2026-01-26T02:45:28.991Z" }, + { url = "https://files.pythonhosted.org/packages/64/f2/6e1107d226278c876c783056b7db43d800bb64c6131cec9c8dfb6903698e/multidict-6.7.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:233b398c29d3f1b9676b4b6f75c518a06fcb2ea0b925119fb2c1bc35c05e1601", size = 258784, upload-time = "2026-01-26T02:45:30.503Z" }, + { url = "https://files.pythonhosted.org/packages/4d/c1/11f664f14d525e4a1b5327a82d4de61a1db604ab34c6603bb3c2cc63ad34/multidict-6.7.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:93b1818e4a6e0930454f0f2af7dfce69307ca03cdcfb3739bf4d91241967b6c1", size = 251980, upload-time = "2026-01-26T02:45:32.603Z" }, + { url = "https://files.pythonhosted.org/packages/e1/9f/75a9ac888121d0c5bbd4ecf4eead45668b1766f6baabfb3b7f66a410e231/multidict-6.7.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f33dc2a3abe9249ea5d8360f969ec7f4142e7ac45ee7014d8f8d5acddf178b7b", size = 243602, upload-time = "2026-01-26T02:45:34.043Z" }, + { url = "https://files.pythonhosted.org/packages/9a/e7/50bf7b004cc8525d80dbbbedfdc7aed3e4c323810890be4413e589074032/multidict-6.7.1-cp314-cp314-win32.whl", hash = "sha256:3ab8b9d8b75aef9df299595d5388b14530839f6422333357af1339443cff777d", size = 40930, upload-time = "2026-01-26T02:45:36.278Z" }, + { url = "https://files.pythonhosted.org/packages/e0/bf/52f25716bbe93745595800f36fb17b73711f14da59ed0bb2eba141bc9f0f/multidict-6.7.1-cp314-cp314-win_amd64.whl", hash = "sha256:5e01429a929600e7dab7b166062d9bb54a5eed752384c7384c968c2afab8f50f", size = 45074, upload-time = "2026-01-26T02:45:37.546Z" }, + { url = "https://files.pythonhosted.org/packages/97/ab/22803b03285fa3a525f48217963da3a65ae40f6a1b6f6cf2768879e208f9/multidict-6.7.1-cp314-cp314-win_arm64.whl", hash = "sha256:4885cb0e817aef5d00a2e8451d4665c1808378dc27c2705f1bf4ef8505c0d2e5", size = 42471, upload-time = "2026-01-26T02:45:38.889Z" }, + { url = "https://files.pythonhosted.org/packages/e0/6d/f9293baa6146ba9507e360ea0292b6422b016907c393e2f63fc40ab7b7b5/multidict-6.7.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:0458c978acd8e6ea53c81eefaddbbee9c6c5e591f41b3f5e8e194780fe026581", size = 82401, upload-time = "2026-01-26T02:45:40.254Z" }, + { url = "https://files.pythonhosted.org/packages/7a/68/53b5494738d83558d87c3c71a486504d8373421c3e0dbb6d0db48ad42ee0/multidict-6.7.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:c0abd12629b0af3cf590982c0b413b1e7395cd4ec026f30986818ab95bfaa94a", size = 48143, upload-time = "2026-01-26T02:45:41.635Z" }, + { url = "https://files.pythonhosted.org/packages/37/e8/5284c53310dcdc99ce5d66563f6e5773531a9b9fe9ec7a615e9bc306b05f/multidict-6.7.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:14525a5f61d7d0c94b368a42cff4c9a4e7ba2d52e2672a7b23d84dc86fb02b0c", size = 46507, upload-time = "2026-01-26T02:45:42.99Z" }, + { url = "https://files.pythonhosted.org/packages/e4/fc/6800d0e5b3875568b4083ecf5f310dcf91d86d52573160834fb4bfcf5e4f/multidict-6.7.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:17307b22c217b4cf05033dabefe68255a534d637c6c9b0cc8382718f87be4262", size = 239358, upload-time = "2026-01-26T02:45:44.376Z" }, + { url = "https://files.pythonhosted.org/packages/41/75/4ad0973179361cdf3a113905e6e088173198349131be2b390f9fa4da5fc6/multidict-6.7.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7a7e590ff876a3eaf1c02a4dfe0724b6e69a9e9de6d8f556816f29c496046e59", size = 246884, upload-time = "2026-01-26T02:45:47.167Z" }, + { url = "https://files.pythonhosted.org/packages/c3/9c/095bb28b5da139bd41fb9a5d5caff412584f377914bd8787c2aa98717130/multidict-6.7.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5fa6a95dfee63893d80a34758cd0e0c118a30b8dcb46372bf75106c591b77889", size = 225878, upload-time = "2026-01-26T02:45:48.698Z" }, + { url = "https://files.pythonhosted.org/packages/07/d0/c0a72000243756e8f5a277b6b514fa005f2c73d481b7d9e47cd4568aa2e4/multidict-6.7.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a0543217a6a017692aa6ae5cc39adb75e587af0f3a82288b1492eb73dd6cc2a4", size = 253542, upload-time = "2026-01-26T02:45:50.164Z" }, + { url = "https://files.pythonhosted.org/packages/c0/6b/f69da15289e384ecf2a68837ec8b5ad8c33e973aa18b266f50fe55f24b8c/multidict-6.7.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f99fe611c312b3c1c0ace793f92464d8cd263cc3b26b5721950d977b006b6c4d", size = 252403, upload-time = "2026-01-26T02:45:51.779Z" }, + { url = "https://files.pythonhosted.org/packages/a2/76/b9669547afa5a1a25cd93eaca91c0da1c095b06b6d2d8ec25b713588d3a1/multidict-6.7.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9004d8386d133b7e6135679424c91b0b854d2d164af6ea3f289f8f2761064609", size = 244889, upload-time = "2026-01-26T02:45:53.27Z" }, + { url = "https://files.pythonhosted.org/packages/7e/a9/a50d2669e506dad33cfc45b5d574a205587b7b8a5f426f2fbb2e90882588/multidict-6.7.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e628ef0e6859ffd8273c69412a2465c4be4a9517d07261b33334b5ec6f3c7489", size = 241982, upload-time = "2026-01-26T02:45:54.919Z" }, + { url = "https://files.pythonhosted.org/packages/c5/bb/1609558ad8b456b4827d3c5a5b775c93b87878fd3117ed3db3423dfbce1b/multidict-6.7.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:841189848ba629c3552035a6a7f5bf3b02eb304e9fea7492ca220a8eda6b0e5c", size = 232415, upload-time = "2026-01-26T02:45:56.981Z" }, + { url = "https://files.pythonhosted.org/packages/d8/59/6f61039d2aa9261871e03ab9dc058a550d240f25859b05b67fd70f80d4b3/multidict-6.7.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:ce1bbd7d780bb5a0da032e095c951f7014d6b0a205f8318308140f1a6aba159e", size = 240337, upload-time = "2026-01-26T02:45:58.698Z" }, + { url = "https://files.pythonhosted.org/packages/a1/29/fdc6a43c203890dc2ae9249971ecd0c41deaedfe00d25cb6564b2edd99eb/multidict-6.7.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b26684587228afed0d50cf804cc71062cc9c1cdf55051c4c6345d372947b268c", size = 248788, upload-time = "2026-01-26T02:46:00.862Z" }, + { url = "https://files.pythonhosted.org/packages/a9/14/a153a06101323e4cf086ecee3faadba52ff71633d471f9685c42e3736163/multidict-6.7.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:9f9af11306994335398293f9958071019e3ab95e9a707dc1383a35613f6abcb9", size = 242842, upload-time = "2026-01-26T02:46:02.824Z" }, + { url = "https://files.pythonhosted.org/packages/41/5f/604ae839e64a4a6efc80db94465348d3b328ee955e37acb24badbcd24d83/multidict-6.7.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b4938326284c4f1224178a560987b6cf8b4d38458b113d9b8c1db1a836e640a2", size = 240237, upload-time = "2026-01-26T02:46:05.898Z" }, + { url = "https://files.pythonhosted.org/packages/5f/60/c3a5187bf66f6fb546ff4ab8fb5a077cbdd832d7b1908d4365c7f74a1917/multidict-6.7.1-cp314-cp314t-win32.whl", hash = "sha256:98655c737850c064a65e006a3df7c997cd3b220be4ec8fe26215760b9697d4d7", size = 48008, upload-time = "2026-01-26T02:46:07.468Z" }, + { url = "https://files.pythonhosted.org/packages/0c/f7/addf1087b860ac60e6f382240f64fb99f8bfb532bb06f7c542b83c29ca61/multidict-6.7.1-cp314-cp314t-win_amd64.whl", hash = "sha256:497bde6223c212ba11d462853cfa4f0ae6ef97465033e7dc9940cdb3ab5b48e5", size = 53542, upload-time = "2026-01-26T02:46:08.809Z" }, + { url = "https://files.pythonhosted.org/packages/4c/81/4629d0aa32302ef7b2ec65c75a728cc5ff4fa410c50096174c1632e70b3e/multidict-6.7.1-cp314-cp314t-win_arm64.whl", hash = "sha256:2bbd113e0d4af5db41d5ebfe9ccaff89de2120578164f86a5d17d5a576d1e5b2", size = 44719, upload-time = "2026-01-26T02:46:11.146Z" }, + { url = "https://files.pythonhosted.org/packages/81/08/7036c080d7117f28a4af526d794aab6a84463126db031b007717c1a6676e/multidict-6.7.1-py3-none-any.whl", hash = "sha256:55d97cc6dae627efa6a6e548885712d4864b81110ac76fa4e534c03819fa4a56", size = 12319, upload-time = "2026-01-26T02:46:44.004Z" }, +] + +[[package]] +name = "nodeenv" +version = "1.10.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611, upload-time = "2025-12-20T14:08:54.006Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" }, +] + +[[package]] +name = "oauthlib" +version = "3.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0b/5f/19930f824ffeb0ad4372da4812c50edbd1434f678c90c2733e1188edfc63/oauthlib-3.3.1.tar.gz", hash = "sha256:0f0f8aa759826a193cf66c12ea1af1637f87b9b4622d46e866952bb022e538c9", size = 185918, upload-time = "2025-06-19T22:48:08.269Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/be/9c/92789c596b8df838baa98fa71844d84283302f7604ed565dafe5a6b5041a/oauthlib-3.3.1-py3-none-any.whl", hash = "sha256:88119c938d2b8fb88561af5f6ee0eec8cc8d552b7bb1f712743136eb7523b7a1", size = 160065, upload-time = "2025-06-19T22:48:06.508Z" }, +] + +[[package]] +name = "packaging" +version = "26.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" }, +] + +[[package]] +name = "pillow" +version = "12.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8c/21/c2bcdd5906101a30244eaffc1b6e6ce71a31bd0742a01eb89e660ebfac2d/pillow-12.2.0.tar.gz", hash = "sha256:a830b1a40919539d07806aa58e1b114df53ddd43213d9c8b75847eee6c0182b5", size = 46987819, upload-time = "2026-04-01T14:46:17.687Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bf/98/4595daa2365416a86cb0d495248a393dfc84e96d62ad080c8546256cb9c0/pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:3adc9215e8be0448ed6e814966ecf3d9952f0ea40eb14e89a102b87f450660d8", size = 4100848, upload-time = "2026-04-01T14:44:48.48Z" }, + { url = "https://files.pythonhosted.org/packages/0b/79/40184d464cf89f6663e18dfcf7ca21aae2491fff1a16127681bf1fa9b8cf/pillow-12.2.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:6a9adfc6d24b10f89588096364cc726174118c62130c817c2837c60cf08a392b", size = 4176515, upload-time = "2026-04-01T14:44:51.353Z" }, + { url = "https://files.pythonhosted.org/packages/b0/63/703f86fd4c422a9cf722833670f4f71418fb116b2853ff7da722ea43f184/pillow-12.2.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:6a6e67ea2e6feda684ed370f9a1c52e7a243631c025ba42149a2cc5934dec295", size = 3640159, upload-time = "2026-04-01T14:44:53.588Z" }, + { url = "https://files.pythonhosted.org/packages/71/e0/fb22f797187d0be2270f83500aab851536101b254bfa1eae10795709d283/pillow-12.2.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:2bb4a8d594eacdfc59d9e5ad972aa8afdd48d584ffd5f13a937a664c3e7db0ed", size = 5312185, upload-time = "2026-04-01T14:44:56.039Z" }, + { url = "https://files.pythonhosted.org/packages/ba/8c/1a9e46228571de18f8e28f16fabdfc20212a5d019f3e3303452b3f0a580d/pillow-12.2.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:80b2da48193b2f33ed0c32c38140f9d3186583ce7d516526d462645fd98660ae", size = 4695386, upload-time = "2026-04-01T14:44:58.663Z" }, + { url = "https://files.pythonhosted.org/packages/70/62/98f6b7f0c88b9addd0e87c217ded307b36be024d4ff8869a812b241d1345/pillow-12.2.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22db17c68434de69d8ecfc2fe821569195c0c373b25cccb9cbdacf2c6e53c601", size = 6280384, upload-time = "2026-04-01T14:45:01.5Z" }, + { url = "https://files.pythonhosted.org/packages/5e/03/688747d2e91cfbe0e64f316cd2e8005698f76ada3130d0194664174fa5de/pillow-12.2.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7b14cc0106cd9aecda615dd6903840a058b4700fcb817687d0ee4fc8b6e389be", size = 8091599, upload-time = "2026-04-01T14:45:04.5Z" }, + { url = "https://files.pythonhosted.org/packages/f6/35/577e22b936fcdd66537329b33af0b4ccfefaeabd8aec04b266528cddb33c/pillow-12.2.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cbeb542b2ebc6fcdacabf8aca8c1a97c9b3ad3927d46b8723f9d4f033288a0f", size = 6396021, upload-time = "2026-04-01T14:45:07.117Z" }, + { url = "https://files.pythonhosted.org/packages/11/8d/d2532ad2a603ca2b93ad9f5135732124e57811d0168155852f37fbce2458/pillow-12.2.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4bfd07bc812fbd20395212969e41931001fd59eb55a60658b0e5710872e95286", size = 7083360, upload-time = "2026-04-01T14:45:09.763Z" }, + { url = "https://files.pythonhosted.org/packages/5e/26/d325f9f56c7e039034897e7380e9cc202b1e368bfd04d4cbe6a441f02885/pillow-12.2.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9aba9a17b623ef750a4d11b742cbafffeb48a869821252b30ee21b5e91392c50", size = 6507628, upload-time = "2026-04-01T14:45:12.378Z" }, + { url = "https://files.pythonhosted.org/packages/5f/f7/769d5632ffb0988f1c5e7660b3e731e30f7f8ec4318e94d0a5d674eb65a4/pillow-12.2.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:deede7c263feb25dba4e82ea23058a235dcc2fe1f6021025dc71f2b618e26104", size = 7209321, upload-time = "2026-04-01T14:45:15.122Z" }, + { url = "https://files.pythonhosted.org/packages/6a/7a/c253e3c645cd47f1aceea6a8bacdba9991bf45bb7dfe927f7c893e89c93c/pillow-12.2.0-cp314-cp314-win32.whl", hash = "sha256:632ff19b2778e43162304d50da0181ce24ac5bb8180122cbe1bf4673428328c7", size = 6479723, upload-time = "2026-04-01T14:45:17.797Z" }, + { url = "https://files.pythonhosted.org/packages/cd/8b/601e6566b957ca50e28725cb6c355c59c2c8609751efbecd980db44e0349/pillow-12.2.0-cp314-cp314-win_amd64.whl", hash = "sha256:4e6c62e9d237e9b65fac06857d511e90d8461a32adcc1b9065ea0c0fa3a28150", size = 7217400, upload-time = "2026-04-01T14:45:20.529Z" }, + { url = "https://files.pythonhosted.org/packages/d6/94/220e46c73065c3e2951bb91c11a1fb636c8c9ad427ac3ce7d7f3359b9b2f/pillow-12.2.0-cp314-cp314-win_arm64.whl", hash = "sha256:b1c1fbd8a5a1af3412a0810d060a78b5136ec0836c8a4ef9aa11807f2a22f4e1", size = 2554835, upload-time = "2026-04-01T14:45:23.162Z" }, + { url = "https://files.pythonhosted.org/packages/b6/ab/1b426a3974cb0e7da5c29ccff4807871d48110933a57207b5a676cccc155/pillow-12.2.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:57850958fe9c751670e49b2cecf6294acc99e562531f4bd317fa5ddee2068463", size = 5314225, upload-time = "2026-04-01T14:45:25.637Z" }, + { url = "https://files.pythonhosted.org/packages/19/1e/dce46f371be2438eecfee2a1960ee2a243bbe5e961890146d2dee1ff0f12/pillow-12.2.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d5d38f1411c0ed9f97bcb49b7bd59b6b7c314e0e27420e34d99d844b9ce3b6f3", size = 4698541, upload-time = "2026-04-01T14:45:28.355Z" }, + { url = "https://files.pythonhosted.org/packages/55/c3/7fbecf70adb3a0c33b77a300dc52e424dc22ad8cdc06557a2e49523b703d/pillow-12.2.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5c0a9f29ca8e79f09de89293f82fc9b0270bb4af1d58bc98f540cc4aedf03166", size = 6322251, upload-time = "2026-04-01T14:45:30.924Z" }, + { url = "https://files.pythonhosted.org/packages/1c/3c/7fbc17cfb7e4fe0ef1642e0abc17fc6c94c9f7a16be41498e12e2ba60408/pillow-12.2.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1610dd6c61621ae1cf811bef44d77e149ce3f7b95afe66a4512f8c59f25d9ebe", size = 8127807, upload-time = "2026-04-01T14:45:33.908Z" }, + { url = "https://files.pythonhosted.org/packages/ff/c3/a8ae14d6defd2e448493ff512fae903b1e9bd40b72efb6ec55ce0048c8ce/pillow-12.2.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a34329707af4f73cf1782a36cd2289c0368880654a2c11f027bcee9052d35dd", size = 6433935, upload-time = "2026-04-01T14:45:36.623Z" }, + { url = "https://files.pythonhosted.org/packages/6e/32/2880fb3a074847ac159d8f902cb43278a61e85f681661e7419e6596803ed/pillow-12.2.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e9c4f5b3c546fa3458a29ab22646c1c6c787ea8f5ef51300e5a60300736905e", size = 7116720, upload-time = "2026-04-01T14:45:39.258Z" }, + { url = "https://files.pythonhosted.org/packages/46/87/495cc9c30e0129501643f24d320076f4cc54f718341df18cc70ec94c44e1/pillow-12.2.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fb043ee2f06b41473269765c2feae53fc2e2fbf96e5e22ca94fb5ad677856f06", size = 6540498, upload-time = "2026-04-01T14:45:41.879Z" }, + { url = "https://files.pythonhosted.org/packages/18/53/773f5edca692009d883a72211b60fdaf8871cbef075eaa9d577f0a2f989e/pillow-12.2.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f278f034eb75b4e8a13a54a876cc4a5ab39173d2cdd93a638e1b467fc545ac43", size = 7239413, upload-time = "2026-04-01T14:45:44.705Z" }, + { url = "https://files.pythonhosted.org/packages/c9/e4/4b64a97d71b2a83158134abbb2f5bd3f8a2ea691361282f010998f339ec7/pillow-12.2.0-cp314-cp314t-win32.whl", hash = "sha256:6bb77b2dcb06b20f9f4b4a8454caa581cd4dd0643a08bacf821216a16d9c8354", size = 6482084, upload-time = "2026-04-01T14:45:47.568Z" }, + { url = "https://files.pythonhosted.org/packages/ba/13/306d275efd3a3453f72114b7431c877d10b1154014c1ebbedd067770d629/pillow-12.2.0-cp314-cp314t-win_amd64.whl", hash = "sha256:6562ace0d3fb5f20ed7290f1f929cae41b25ae29528f2af1722966a0a02e2aa1", size = 7225152, upload-time = "2026-04-01T14:45:50.032Z" }, + { url = "https://files.pythonhosted.org/packages/ff/6e/cf826fae916b8658848d7b9f38d88da6396895c676e8086fc0988073aaf8/pillow-12.2.0-cp314-cp314t-win_arm64.whl", hash = "sha256:aa88ccfe4e32d362816319ed727a004423aab09c5cea43c01a4b435643fa34eb", size = 2556579, upload-time = "2026-04-01T14:45:52.529Z" }, +] + +[[package]] +name = "platformdirs" +version = "4.9.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9f/4a/0883b8e3802965322523f0b200ecf33d31f10991d0401162f4b23c698b42/platformdirs-4.9.6.tar.gz", hash = "sha256:3bfa75b0ad0db84096ae777218481852c0ebc6c727b3168c1b9e0118e458cf0a", size = 29400, upload-time = "2026-04-09T00:04:10.812Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/75/a6/a0a304dc33b49145b21f4808d763822111e67d1c3a32b524a1baf947b6e1/platformdirs-4.9.6-py3-none-any.whl", hash = "sha256:e61adb1d5e5cb3441b4b7710bea7e4c12250ca49439228cc1021c00dcfac0917", size = 21348, upload-time = "2026-04-09T00:04:09.463Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + +[[package]] +name = "pre-commit" +version = "4.6.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cfgv" }, + { name = "identify" }, + { name = "nodeenv" }, + { name = "pyyaml" }, + { name = "virtualenv" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8e/22/2de9408ac81acbb8a7d05d4cc064a152ccf33b3d480ebe0cd292153db239/pre_commit-4.6.0.tar.gz", hash = "sha256:718d2208cef53fdc38206e40524a6d4d9576d103eb16f0fec11c875e7716e9d9", size = 198525, upload-time = "2026-04-21T20:31:41.613Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/80/6e/4b28b62ecb6aae56769c34a8ff1d661473ec1e9519e2d5f8b2c150086b26/pre_commit-4.6.0-py2.py3-none-any.whl", hash = "sha256:e2cf246f7299edcabcf15f9b0571fdce06058527f0a06535068a86d38089f29b", size = 226472, upload-time = "2026-04-21T20:31:40.092Z" }, +] + +[[package]] +name = "prometheus-client" +version = "0.25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/fb/d9aa83ffe43ce1f19e557c0971d04b90561b0cfd50762aafb01968285553/prometheus_client-0.25.0.tar.gz", hash = "sha256:5e373b75c31afb3c86f1a52fa1ad470c9aace18082d39ec0d2f918d11cc9ba28", size = 86035, upload-time = "2026-04-09T19:53:42.359Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/9b/d4b1e644385499c8346fa9b622a3f030dce14cd6ef8a1871c221a17a67e7/prometheus_client-0.25.0-py3-none-any.whl", hash = "sha256:d5aec89e349a6ec230805d0df882f3807f74fd6c1a2fa86864e3c2279059fed1", size = 64154, upload-time = "2026-04-09T19:53:41.324Z" }, +] + +[[package]] +name = "prompt-toolkit" +version = "3.0.52" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wcwidth" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a1/96/06e01a7b38dce6fe1db213e061a4602dd6032a8a97ef6c1a862537732421/prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855", size = 434198, upload-time = "2025-08-27T15:24:02.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" }, +] + +[[package]] +name = "propcache" +version = "0.5.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ec/44/c87281c333769159c50594f22610f77398a47ccbfbbf23074e744e86f87c/propcache-0.5.2.tar.gz", hash = "sha256:01c4fc7480cd0598bb4b57022df55b9ca296da7fc5a8760bd8451a7e63a7d427", size = 50208, upload-time = "2026-05-08T21:02:12.199Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e2/ea/23ee535d90ce8bcc465a3028eb3cc0ce3bd1005f4bb27710b30587de798d/propcache-0.5.2-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:46088abff4cba581dea21ae0467a480526cb25aa5f3c269e909f800328bc3999", size = 94662, upload-time = "2026-05-08T21:01:22.683Z" }, + { url = "https://files.pythonhosted.org/packages/b5/06/c5a52f419b5d8972f8d46a7577476090d8e3263ff589ce40b5ca4968d5be/propcache-0.5.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fc88b26f08d634f7bc819a7852e5214f5802641ab8d9fd5326892292eee1993e", size = 53928, upload-time = "2026-05-08T21:01:23.986Z" }, + { url = "https://files.pythonhosted.org/packages/63/b1/4260d67d6bd85e58a66b72d54ce15d5de789b6f3870cc6bedf8ff9667401/propcache-0.5.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:97797ebb098e670a2f92dd66f32897e30d7615b14e7f59711de23e30a9072539", size = 54650, upload-time = "2026-05-08T21:01:25.305Z" }, + { url = "https://files.pythonhosted.org/packages/70/06/2f46c318e3307cd7a6a7481def374ce838c0fe20084b39dd54b0879d0e99/propcache-0.5.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba57fffe4ac99c5d30076161b5866336d97600769bad35cc68f7774b15298a4e", size = 59912, upload-time = "2026-05-08T21:01:26.545Z" }, + { url = "https://files.pythonhosted.org/packages/4c/29/fe1aebec2ce57ab985a9c382bded1124431f85078113aa222c5d278430d4/propcache-0.5.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:583c19759d9eec1e5b69e2fbef36a7d9c326041be9746cb822d335c8cedc2979", size = 63300, upload-time = "2026-05-08T21:01:27.937Z" }, + { url = "https://files.pythonhosted.org/packages/b4/18/2334b26768b6c82be8c69e83671b767d5ef426aa09b0cba6c2ea47816774/propcache-0.5.2-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d0326e2e5e1f3163fa306c834e48e8d490e5fae607a097a40c0648109b47ba80", size = 64208, upload-time = "2026-05-08T21:01:29.484Z" }, + { url = "https://files.pythonhosted.org/packages/2b/76/7f1bfd6afff4c5e38e36a3c6d68eb5f4b7311ea80baf693db78d95b603c4/propcache-0.5.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e00820e192c8dbebcafb383ebbf99030895f09905e7a0eb2e0340a0bcc2bc825", size = 61633, upload-time = "2026-05-08T21:01:31.068Z" }, + { url = "https://files.pythonhosted.org/packages/c4/46/b3ff8aba2b4953a3e50de2cf72f1b5748b8eca93b15f3dc2c84339084c09/propcache-0.5.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c66afea89b1e43725731d2004732a046fe6fe955d51f952c3e95a7314a284a39", size = 61724, upload-time = "2026-05-08T21:01:32.374Z" }, + { url = "https://files.pythonhosted.org/packages/c5/01/814cfcafbcff954f94c01cf30e097ddc88a076b5440fbcf4570753437d40/propcache-0.5.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d4dc37dec6c6cdad0b57881a5658fd14fbf53e333b1a86cf86559f190e1d9ec4", size = 60069, upload-time = "2026-05-08T21:01:33.67Z" }, + { url = "https://files.pythonhosted.org/packages/da/68/5c6f7622d510cc666a300687e06fd060c1a43361c0c9b20d284f06d8096a/propcache-0.5.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:5570dbcc97571c15f68068e529c92715a12f8d54030e272d264b377e22bd17a5", size = 57099, upload-time = "2026-05-08T21:01:34.915Z" }, + { url = "https://files.pythonhosted.org/packages/55/27/9cb0b4c679124085327957d42521c99dba04c88c90c3e55a6f0b633ebccc/propcache-0.5.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:f814362777a9f841adddb200ecdf8f5cb1e5a3c4b7a86378edbd6ccb26edd702", size = 63391, upload-time = "2026-05-08T21:01:36.231Z" }, + { url = "https://files.pythonhosted.org/packages/f0/9d/7258aaa5bdf60fc6f27591eef6fe52768cb0beda7140be477c8b12c9794a/propcache-0.5.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:196913dea116aeb5a2ba95af4ddcb7ea85559ae07d8eee8751688310d09168c3", size = 61626, upload-time = "2026-05-08T21:01:37.545Z" }, + { url = "https://files.pythonhosted.org/packages/8e/0d/41c602003e8a9b16fe1e7eadf62c7bfba9d5474370b24200bf48b315f45f/propcache-0.5.2-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:6e7b8719005dd1175be4ab1cd25e9b98659a5e0347331506ec6760d2773a7fb5", size = 64781, upload-time = "2026-05-08T21:01:38.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/f3/38e66b1856e9bd079deea015bc4a55f7767c0e4db2f7dcf69e7e680ba4ce/propcache-0.5.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:51f96d685ab16e88cab128cd37a52c5da540809c8b879fa047731bfcb4ad35a4", size = 62570, upload-time = "2026-05-08T21:01:40.415Z" }, + { url = "https://files.pythonhosted.org/packages/95/ca/bbfe9b910ce57dde8bb4876b4520fc02a4e89497c10de26be936758a3aaa/propcache-0.5.2-cp314-cp314-win32.whl", hash = "sha256:cc6fc3cc62e8501d3ed62894425040d2728ecddb1ed072737a5c70bd537aa9f0", size = 39436, upload-time = "2026-05-08T21:01:41.654Z" }, + { url = "https://files.pythonhosted.org/packages/61/d2/45c9defbaa1ea297035d9d4cce9e8f80daafbf19319c6007f157c6256ea9/propcache-0.5.2-cp314-cp314-win_amd64.whl", hash = "sha256:81e3a30b0bb60caa22033dd0f8a3618d1d67356212514f62c57db75cb0ef410c", size = 42373, upload-time = "2026-05-08T21:01:43.041Z" }, + { url = "https://files.pythonhosted.org/packages/44/68/9ea5103f41d5217d7d6ec24db90018e23aebec070c3f9a6e54d12b841fd8/propcache-0.5.2-cp314-cp314-win_arm64.whl", hash = "sha256:0d2c9bf8528f135dbb805ce027567e09164f7efa51a2be07458a2c0420f292d0", size = 38554, upload-time = "2026-05-08T21:01:44.336Z" }, + { url = "https://files.pythonhosted.org/packages/8a/81/fadf555f42d3b762eea8a53950b0489fdc0aa9da5f8ed9e10ce0a4e01b48/propcache-0.5.2-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:4bc8ff1feffc6a61c7002ffe84634c41b822e104990ae009f44a0834430070bb", size = 99395, upload-time = "2026-05-08T21:01:45.883Z" }, + { url = "https://files.pythonhosted.org/packages/f5/c9/c61e134a686949cf7971af3a390148b1156f7be81c73bc0cd12c873e2d48/propcache-0.5.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:79aa3ff0a9b566633b642fa9caf7e21ed1c13d6feca718187873f199e1514078", size = 56653, upload-time = "2026-05-08T21:01:47.307Z" }, + { url = "https://files.pythonhosted.org/packages/cb/73/daf935ea7048ddd7ec8eec5345b4a40b619d2d178b3c0a0900796bc3c794/propcache-0.5.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1b31822f4474c4036bae62de9402710051d431a606d6a0f907fec79935a071aa", size = 56914, upload-time = "2026-05-08T21:01:48.573Z" }, + { url = "https://files.pythonhosted.org/packages/79/9f/aba959b435ea18617edd7cf0a7ad0b9c574b8fc7e3d2cd55fb59cb255d33/propcache-0.5.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13fef48778b5a2a756523fdb781326b028ca75e32858b04f2cdd19f394564917", size = 62567, upload-time = "2026-05-08T21:01:49.903Z" }, + { url = "https://files.pythonhosted.org/packages/6c/a1/859942de9a791ff42f6141736f5b37749b8f53e65edfa49638c67dd67e6a/propcache-0.5.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8b73ab70f1a3351fbc71f663b3e645af6dd0329100c353081cf69c37433fc6fe", size = 65542, upload-time = "2026-05-08T21:01:51.204Z" }, + { url = "https://files.pythonhosted.org/packages/b5/61/315bc0fd6c0fc7f80a528b8afd209e5fc4a875ea79571b91b8f50f442907/propcache-0.5.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5538d2c13d93e4698af7e092b57bc7298fd35d1d58e656ae18f23ee0d0378e03", size = 66845, upload-time = "2026-05-08T21:01:52.539Z" }, + { url = "https://files.pythonhosted.org/packages/47/f7/9f8122e3132e8e354ac41975ef8f1099be7d5a16bc7ae562734e993665c0/propcache-0.5.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cd645f03898405cabe694fb8bc35241e3a9c332ec85627584fe3de201452b335", size = 63985, upload-time = "2026-05-08T21:01:53.847Z" }, + { url = "https://files.pythonhosted.org/packages/c8/54/c317819ec157cbf6f35df9df9657a6f82daf34d5faf15948b2f639c2192e/propcache-0.5.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a473b3440261e0c60706e732b2ed2f517857344fc21bf48fdfe211e2d98eb285", size = 63999, upload-time = "2026-05-08T21:01:55.179Z" }, + { url = "https://files.pythonhosted.org/packages/5a/56/387e3f7dfce0a9233df41fb888aa1c30222cb4bbbf09537c02dd9bd85fe2/propcache-0.5.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7afa37062e6650640e932e4cc9297d81f9f42d9944029cc386b8247dea4da837", size = 62779, upload-time = "2026-05-08T21:01:57.489Z" }, + { url = "https://files.pythonhosted.org/packages/a1/9c/596784cb5824ed61ee960d3f8655a3f0993e107c6e98ab6c818b7fb92ccb/propcache-0.5.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:8a90efd5777e996e42d568db9ac740b944d691e565cbfd31b2f7832f9184b2b8", size = 59796, upload-time = "2026-05-08T21:01:58.736Z" }, + { url = "https://files.pythonhosted.org/packages/c2/3d/1a6cfa1726a48542c1e8784a0761421476a5b68e09b7f36bf95eb954aaba/propcache-0.5.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:f19bb891234d72535764d703bfed1153cc34f4214d5bd7150aee1eec9e8f4366", size = 66023, upload-time = "2026-05-08T21:02:00.228Z" }, + { url = "https://files.pythonhosted.org/packages/e4/0e/05fd6990369477076e4e280bcb970de760fddf0161a46e988bc95f7940ec/propcache-0.5.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:32775082acd2d807ee3db715c7770d38767b817870acfa08c29e057f3c4d5b56", size = 64448, upload-time = "2026-05-08T21:02:01.888Z" }, + { url = "https://files.pythonhosted.org/packages/cd/86/5f8da315a4309c62c10c0b2516b17492d5d3bbe1bb862b96604db67e2a37/propcache-0.5.2-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:9282fb1a3bccd038da9f768b927b24a0c753e466c086b7c4f3c6982851eefb2d", size = 67329, upload-time = "2026-05-08T21:02:03.484Z" }, + { url = "https://files.pythonhosted.org/packages/da/d3/3368efe79ab21f0cdf86ef49895811c9cc933131d4cde1f28a624e22e712/propcache-0.5.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cc49723e2f60d6b32a0f0b08a3fd6d13203c07f1cd9566cfce0f12a917c967a2", size = 65172, upload-time = "2026-05-08T21:02:04.745Z" }, + { url = "https://files.pythonhosted.org/packages/d5/07/127e8b0bacfb325396196f9d976a22453049b89b9b2b08477cc3145faa44/propcache-0.5.2-cp314-cp314t-win32.whl", hash = "sha256:2d7aa89ebca5acc98cba9d1472d976e394782f587bad6661003602a619fd1821", size = 43813, upload-time = "2026-05-08T21:02:06.025Z" }, + { url = "https://files.pythonhosted.org/packages/88/fb/46dad6c0ae49ed230ab1b16c890c2b6314e2403e6c412976f4a72d64a527/propcache-0.5.2-cp314-cp314t-win_amd64.whl", hash = "sha256:d447bb0b3054be5818458fbb171208b1d9ff11eba14e18ca18b90cbb45767370", size = 47764, upload-time = "2026-05-08T21:02:07.353Z" }, + { url = "https://files.pythonhosted.org/packages/e7/c4/a47d0a63aa309d10d59ede6e9d4cff03a344a79d1f0f4cd0cd74997b53e0/propcache-0.5.2-cp314-cp314t-win_arm64.whl", hash = "sha256:fe67a3d11cd9b4efabfa45c3d00ffba2b26811442a73a581a94b67c2b5faccf6", size = 41140, upload-time = "2026-05-08T21:02:09.065Z" }, + { url = "https://files.pythonhosted.org/packages/3a/ed/1cdcab6ba3d6ab7feca11fc14f0eeea80755bb53ef4e892079f31b10a25f/propcache-0.5.2-py3-none-any.whl", hash = "sha256:be1ddfcbb376e3de5d2e2db1d58d6d67463e6b4f9f040c000de8e300295465fe", size = 14036, upload-time = "2026-05-08T21:02:10.673Z" }, +] + +[[package]] +name = "psycopg" +version = "3.3.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "tzdata", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/db/2f/cb91e5502ec9de1de6f1b76cfbf69531932725361168bb06963620c77e2e/psycopg-3.3.4.tar.gz", hash = "sha256:e21207764952cff81b6b8bdacad9a3939f2793367fdac2987b3aac36a651b5bc", size = 165799, upload-time = "2026-05-01T23:31:55.179Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5c/e0/7b3dee031daae7743609ce3c746565d4a3ed7c2c186479eb48e34e838c64/psycopg-3.3.4-py3-none-any.whl", hash = "sha256:b6bbc25ccf05c8fad3b061d9db2ef0909a555171b84b07f29458a447253d679a", size = 213001, upload-time = "2026-05-01T23:20:50.816Z" }, +] + +[package.optional-dependencies] +binary = [ + { name = "psycopg-binary", marker = "implementation_name != 'pypy'" }, +] + +[[package]] +name = "psycopg-binary" +version = "3.3.4" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/48/a6/828c9185701dab71b234c2a76c38a08b098ebfec5020716b4e93807492b5/psycopg_binary-3.3.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:28b7398fdd19db3232c884fb24550bdfe951221f510e195e233299e4c9b78f97", size = 4607292, upload-time = "2026-05-01T23:30:38.962Z" }, + { url = "https://files.pythonhosted.org/packages/92/58/5b40dbc9d839045c9dae956960e4fb6d20bcabe6c59a2aa34fc3a371913f/psycopg_binary-3.3.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1fbaa292a3c8bb61b45df1ad3da1908ccee7cb889db9425e3557d9e34e2a4829", size = 4687023, upload-time = "2026-05-01T23:30:47.227Z" }, + { url = "https://files.pythonhosted.org/packages/85/a9/793f0ac107a9003b48441d0d1f9f616d96e0f37458dd8dc12528ceff55fb/psycopg_binary-3.3.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:94596f9e7633ee3f6440711d43bb70aa31cc0a46a900ab8b4201a366ace5c9e7", size = 5486985, upload-time = "2026-05-01T23:30:55.517Z" }, + { url = "https://files.pythonhosted.org/packages/8f/26/42e8533497e2592334f68ec529cf5f840f7fa4e99575a4bb61aa184dbfbf/psycopg_binary-3.3.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8c0056529e68dbe9184cd4019a1f3d8f3a4ead2f6fc7a5afcf27d3314edd1277", size = 5168745, upload-time = "2026-05-01T23:31:01.904Z" }, + { url = "https://files.pythonhosted.org/packages/15/af/b7151776cc08d5935d45c833ec818a9beb417cf7c08239af1aafbdae78ee/psycopg_binary-3.3.4-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c09aad7051326e7603c14e50636db9c01f78272dc54b3accff03d46370461e6", size = 6761486, upload-time = "2026-05-01T23:31:14.511Z" }, + { url = "https://files.pythonhosted.org/packages/d0/ed/c92533b9124712d592cbf1cd6c76da933a2e0acea81dfe1fbe7e735f0cff/psycopg_binary-3.3.4-cp314-cp314-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:514404ed543efd620c85602b747df2a23cf1241b4067199e1a66f2d2757aaa41", size = 4997427, upload-time = "2026-05-01T23:31:20.901Z" }, + { url = "https://files.pythonhosted.org/packages/a2/23/ccadfd0de416aa188356daa199453af24087b042e296088706d190ae0295/psycopg_binary-3.3.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:46893c26858be12cc49ca4226ed6a60b4bfccadd946b3bebb783a60b38788228", size = 4533549, upload-time = "2026-05-01T23:31:26.204Z" }, + { url = "https://files.pythonhosted.org/packages/fd/a0/c8f43cee36386f7bc891ab41a9d31ea07cf9826038e732da79f26b1e5f34/psycopg_binary-3.3.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:df1d567fc430f6df15c9fcf67d87685fc49bdb325adc0db5af1adfb2f44eb5c9", size = 4210256, upload-time = "2026-05-01T23:31:33.884Z" }, + { url = "https://files.pythonhosted.org/packages/4e/2c/c1547871be3790676e8868b38655496422f94f0978dfb66b74bdba2f1676/psycopg_binary-3.3.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:6b9016b1714da4dd5ecaaa75b82098aa5a0b87854ce9b092e21c27c4ae23e014", size = 3946204, upload-time = "2026-05-01T23:31:39.626Z" }, + { url = "https://files.pythonhosted.org/packages/c4/b1/f6670f00fa7ea601584623f6c11602ab92117d83eaff885e0210f6de7418/psycopg_binary-3.3.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:47c656a8a7ba6eb0cff1801a4caaa9c8bdc12d03080e273aff1c8ac39971a77e", size = 4255811, upload-time = "2026-05-01T23:31:44.986Z" }, + { url = "https://files.pythonhosted.org/packages/eb/e6/5fff07a70d1f945ed90ae131c3bd76cab32beff7c58c6db15ad5820b6d1f/psycopg_binary-3.3.4-cp314-cp314-win_amd64.whl", hash = "sha256:c37e024c07308cd06cf3ec51bfd0e7f6157585a4d84d1bce4a7f5f7913719bf8", size = 3666849, upload-time = "2026-05-01T23:31:51.165Z" }, +] + +[[package]] +name = "pycouchdb" +version = "1.16.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "chardet" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c1/b4/4f699a686a2ce14ab31cb17902693f2cf201ba51c3a6fb7aba210725c154/pycouchdb-1.16.0.tar.gz", hash = "sha256:309d71c3ce3f98bbee5731db00f514753438b81e6e7adefbb8c134312200a4f9", size = 11351, upload-time = "2024-05-29T10:00:11.726Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4c/63/b4397a7215c089c7951afb258069cc58a06788224f1bb6a0d4f976f2d476/pycouchdb-1.16.0-py3-none-any.whl", hash = "sha256:e26ce58f626fcabbe2f5b15b3ad2b89cdd3f6d666da673632037476d1191ab67", size = 12560, upload-time = "2024-05-29T10:00:09.31Z" }, +] + +[[package]] +name = "pycparser" +version = "3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, +] + +[[package]] +name = "pygments" +version = "2.20.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, +] + +[[package]] +name = "pyjwt" +version = "2.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/81/58d0ac84e1ef3a3843791d6954d94c0b33d526c75eeb1efbce9d0a4c4077/pyjwt-2.13.0.tar.gz", hash = "sha256:41571c89ca91598c79e8ef18a2d07367d4810fbbd6f637794879baf1b7703423", size = 107515, upload-time = "2026-05-21T19:54:36.618Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a3/5e/ecf12fdb62546d64385c158514e9b2b671f7832108ef2ecd2020ce0af2d1/pyjwt-2.13.0-py3-none-any.whl", hash = "sha256:66adcc2aff09b3f1bbd95fc1e1577df8ac8723c978552fd43304c8a290ac5728", size = 31274, upload-time = "2026-05-21T19:54:35.362Z" }, +] + +[[package]] +name = "pyparsing" +version = "3.3.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/91/9c6ee907786a473bf81c5f53cf703ba0957b23ab84c264080fb5a450416f/pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc", size = 6851574, upload-time = "2026-01-21T03:57:59.36Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" }, +] + +[[package]] +name = "pytest" +version = "9.0.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c", size = 1572165, upload-time = "2026-04-07T17:16:18.027Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9", size = 375249, upload-time = "2026-04-07T17:16:16.13Z" }, +] + +[[package]] +name = "pytest-cov" +version = "7.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "coverage" }, + { name = "pluggy" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/51/a849f96e117386044471c8ec2bd6cfebacda285da9525c9106aeb28da671/pytest_cov-7.1.0.tar.gz", hash = "sha256:30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2", size = 55592, upload-time = "2026-03-21T20:11:16.284Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl", hash = "sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678", size = 22876, upload-time = "2026-03-21T20:11:14.438Z" }, +] + +[[package]] +name = "pytest-django" +version = "4.12.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/13/2b/db9a193df89e5660137f5428063bcc2ced7ad790003b26974adf5c5ceb3b/pytest_django-4.12.0.tar.gz", hash = "sha256:df94ec819a83c8979c8f6de13d9cdfbe76e8c21d39473cfe2b40c9fc9be3c758", size = 91156, upload-time = "2026-02-14T18:40:49.235Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/a5/41d091f697c09609e7ef1d5d61925494e0454ebf51de7de05f0f0a728f1d/pytest_django-4.12.0-py3-none-any.whl", hash = "sha256:3ff300c49f8350ba2953b90297d23bf5f589db69545f56f1ec5f8cff5da83e85", size = 26123, upload-time = "2026-02-14T18:40:47.381Z" }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, +] + +[[package]] +name = "python-decouple" +version = "3.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e1/97/373dcd5844ec0ea5893e13c39a2c67e7537987ad8de3842fe078db4582fa/python-decouple-3.8.tar.gz", hash = "sha256:ba6e2657d4f376ecc46f77a3a615e058d93ba5e465c01bbe57289bfb7cce680f", size = 9612, upload-time = "2023-03-01T19:38:38.143Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a2/d4/9193206c4563ec771faf2ccf54815ca7918529fe81f6adb22ee6d0e06622/python_decouple-3.8-py3-none-any.whl", hash = "sha256:d0d45340815b25f4de59c974b855bb38d03151d81b037d9e3f463b0c9f8cbd66", size = 9947, upload-time = "2023-03-01T19:38:36.015Z" }, +] + +[[package]] +name = "python-discovery" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "filelock" }, + { name = "platformdirs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/48/60/e88788207d81e46362cfbef0d4aaf4c0f49efc3c12d4c3fa3f542c34ebec/python_discovery-1.3.1.tar.gz", hash = "sha256:62f6db28064c9613e7ca76cb3f00c38c839a07c31c00dfe7ed0986493d2150a6", size = 68011, upload-time = "2026-05-12T20:53:36.336Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/6f/a05a317a66fee0aad270011461f1a63a453ed12471249f172f7d2e2bc7b4/python_discovery-1.3.1-py3-none-any.whl", hash = "sha256:ed188687ebb3b82c01a17cd5ac62fc94d9f6487a7f1a0f9dfe89753fec91039c", size = 33185, upload-time = "2026-05-12T20:53:34.969Z" }, +] + +[[package]] +name = "python3-openid" +version = "3.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "defusedxml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5f/4a/29feb8da6c44f77007dcd29518fea73a3d5653ee02a587ae1f17f1f5ddb5/python3-openid-3.2.0.tar.gz", hash = "sha256:33fbf6928f401e0b790151ed2b5290b02545e8775f982485205a066f874aaeaf", size = 305600, upload-time = "2020-06-29T12:15:49.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/a5/c6ba13860bdf5525f1ab01e01cc667578d6f1efc8a1dba355700fb04c29b/python3_openid-3.2.0-py3-none-any.whl", hash = "sha256:6626f771e0417486701e0b4daff762e7212e820ca5b29fcc0d05f6f8736dfa6b", size = 133681, upload-time = "2020-06-29T12:15:47.502Z" }, +] + +[[package]] +name = "pytz" +version = "2026.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ff/46/dd499ec9038423421951e4fad73051febaa13d2df82b4064f87af8b8c0c3/pytz-2026.2.tar.gz", hash = "sha256:0e60b47b29f21574376f218fe21abc009894a2321ea16c6754f3cad6eb7cdd6a", size = 320861, upload-time = "2026-05-04T01:35:29.667Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/dd/96da98f892250475bdf2328112d7468abdd4acc7b902b6af23f4ed958ea0/pytz-2026.2-py2.py3-none-any.whl", hash = "sha256:04156e608bee23d3792fd45c94ae47fae1036688e75032eea2e3bf0323d1f126", size = 510141, upload-time = "2026-05-04T01:35:27.408Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, + { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, + { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, + { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, + { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, +] + +[[package]] +name = "rcssmin" +version = "1.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/81/af/c9654b4f9b054ec163ed7cb20d8db0e5ae05e2e9ce99a4c11d91a2180b3f/rcssmin-1.2.2.tar.gz", hash = "sha256:806986eaf7414545edc28a1d29523e9560e49e151ff4a337d9d1f0271d6e1cc4", size = 587012, upload-time = "2025-10-12T10:48:08.932Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/40/9c4cb3133f6d4ddfbeada76988a10ff2a974706fd6fcbb97edd8c0f4cc76/rcssmin-1.2.2-cp314-cp314-manylinux1_i686.whl", hash = "sha256:540dd3aa586b5f8f4c4b90db37e6a31c04718cdf90dbe9bec43c3b4dd50519e7", size = 49032, upload-time = "2025-10-12T10:48:53.014Z" }, + { url = "https://files.pythonhosted.org/packages/07/84/a411a48fd4179a88c68a2ad3649b408fa7887a421d3435c10ae6f5724e3a/rcssmin-1.2.2-cp314-cp314-manylinux1_x86_64.whl", hash = "sha256:6ea38a38eec263858b70bed6715478dcfed7fbc5d63333a8c512631ee22baad9", size = 49497, upload-time = "2025-10-12T10:48:54.009Z" }, + { url = "https://files.pythonhosted.org/packages/a1/32/5663a71a9304e0c9f33b765264508229d026359cfff746e1d0a593d809ea/rcssmin-1.2.2-cp314-cp314-manylinux2014_aarch64.whl", hash = "sha256:07dc7d352e8eb08de82fc4c545dd04f9f487466c8370051e0bee4eb1e4dc85d0", size = 50382, upload-time = "2025-10-12T10:48:55.079Z" }, + { url = "https://files.pythonhosted.org/packages/d7/28/e411eb191ffff7bd712f2eb0f691cb7ca514b1876d6bff2f5ae61359b8db/rcssmin-1.2.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:cdccb0e08281f0dd5d463c16ec61a06bd1534de50206dc72918be3c10dcb82e5", size = 50962, upload-time = "2025-10-12T10:48:56.494Z" }, + { url = "https://files.pythonhosted.org/packages/fb/3f/cdb99526d294c5dd4b919dc4ef492b7bd11e08b585d15ec641dfb9423493/rcssmin-1.2.2-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:2b6d5e2e2fd65738d57ef65aaaed2cff2288eccff7f704bf3d579e6f451cb60a", size = 52504, upload-time = "2025-10-12T10:48:57.886Z" }, + { url = "https://files.pythonhosted.org/packages/e8/60/a8183401fa64e93e1d52b2cdf275a2c11e0993f5f3162c573a67872b535d/rcssmin-1.2.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7018d4197713c7797d1a67ed47ab53d4706c2e9ed134123c30a47d389dda5386", size = 50561, upload-time = "2025-10-12T10:48:58.935Z" }, + { url = "https://files.pythonhosted.org/packages/47/5e/496d6c9c309e2fe79e6a69f25f7a6d18f545edb4ea3584f461b9f84b0d60/rcssmin-1.2.2-cp314-cp314t-manylinux1_i686.whl", hash = "sha256:0162c32ce946978edc834d4fba705ac5f9422d7f556f3264cc4fc67c7ee39171", size = 51214, upload-time = "2025-10-12T10:49:00.021Z" }, + { url = "https://files.pythonhosted.org/packages/5e/78/87da6706d5856ceee71421ba831d2f5d93c3e6865acfbb56ace8d54587cc/rcssmin-1.2.2-cp314-cp314t-manylinux1_x86_64.whl", hash = "sha256:f17dc92553a46412c49f972f0ab31088032b9482a9c421bc2d39691a5d8842aa", size = 51608, upload-time = "2025-10-12T10:49:01.422Z" }, + { url = "https://files.pythonhosted.org/packages/cd/6c/204b0262c11ac2da2b8df2d8fed76f1959273fbc8376450d0ac022d754b7/rcssmin-1.2.2-cp314-cp314t-manylinux2014_aarch64.whl", hash = "sha256:40c7dfba098bbd129d8c35dd8b604275585f9dc0496e5d17dbe7fd6b873b0233", size = 53349, upload-time = "2025-10-12T10:49:02.512Z" }, + { url = "https://files.pythonhosted.org/packages/c3/7b/9aae16756d3f33cbc512760ba3e69c3856a51aa293e463f2ca97760d1b1b/rcssmin-1.2.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d0197fab78ebbe33f5df9caf2572ef2d44bbe243a9130881a0c5c53ba03641fa", size = 53066, upload-time = "2025-10-12T10:49:03.589Z" }, + { url = "https://files.pythonhosted.org/packages/4e/18/b06fadfa9b85e486bb1571050217cb539c062d1ae4cd32b1a31c36f67fd4/rcssmin-1.2.2-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:19e53c58768369366fdaef00da59f275f724f229994ea885309df6ca368ff3c8", size = 54271, upload-time = "2025-10-12T10:49:04.735Z" }, + { url = "https://files.pythonhosted.org/packages/79/55/f29ce21f8e5a1f3c19d43b67b907268d227b7edcda2ca200ca0028734a5e/rcssmin-1.2.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8d3de1a870e00d157f3a7b1797498fdc09a3774629079572350f75783bb94b9a", size = 52423, upload-time = "2025-10-12T10:49:06.04Z" }, +] + +[[package]] +name = "redis" +version = "7.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7b/7f/3759b1d0d72b7c92f0d70ffd9dc962b7b7b5ee74e135f9d7d8ab06b8a318/redis-7.4.0.tar.gz", hash = "sha256:64a6ea7bf567ad43c964d2c30d82853f8df927c5c9017766c55a1d1ed95d18ad", size = 4943913, upload-time = "2026-03-24T09:14:37.53Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/74/3a/95deec7db1eb53979973ebd156f3369a72732208d1391cd2e5d127062a32/redis-7.4.0-py3-none-any.whl", hash = "sha256:a9c74a5c893a5ef8455a5adb793a31bb70feb821c86eccb62eebef5a19c429ec", size = 409772, upload-time = "2026-03-24T09:14:35.968Z" }, +] + +[[package]] +name = "requests" +version = "2.34.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ac/c3/e2a2b89f2d3e2179abd6d00ebd70bff6273f37fb3e0cc209f48b39d00cbf/requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed", size = 142856, upload-time = "2026-05-14T19:25:27.735Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", size = 73075, upload-time = "2026-05-14T19:25:26.443Z" }, +] + +[[package]] +name = "requests-oauthlib" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "oauthlib" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/42/f2/05f29bc3913aea15eb670be136045bf5c5bbf4b99ecb839da9b422bb2c85/requests-oauthlib-2.0.0.tar.gz", hash = "sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9", size = 55650, upload-time = "2024-03-22T20:32:29.939Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3b/5d/63d4ae3b9daea098d5d6f5da83984853c1bbacd5dc826764b249fe119d24/requests_oauthlib-2.0.0-py2.py3-none-any.whl", hash = "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36", size = 24179, upload-time = "2024-03-22T20:32:28.055Z" }, +] + +[[package]] +name = "rich" +version = "15.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" }, +] + +[[package]] +name = "rjsmin" +version = "1.2.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/59/16/14288d309d0f42c6586440c47bf6ec1a880218f698f30293fa3782db4008/rjsmin-1.2.5.tar.gz", hash = "sha256:a3f8040b0273dec773e0e807e86a4d0a9535516c0a0a35aa1bb6de6e15bb1f09", size = 427399, upload-time = "2025-10-12T10:50:27.422Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b8/ed/b472d5a3fd7d63c016893f7d438e677901fea28089b5d30cd1a115bcc887/rjsmin-1.2.5-cp314-cp314-manylinux1_i686.whl", hash = "sha256:7096357ed596fdfe0acb750f8cbfca338f3c845cc12def3861e23ed811589d15", size = 31983, upload-time = "2025-10-12T10:51:11.361Z" }, + { url = "https://files.pythonhosted.org/packages/9c/e8/e76fa527fde17fd08288e4efef25c0aba7979ed5740eeab7bdff507bdeba/rjsmin-1.2.5-cp314-cp314-manylinux1_x86_64.whl", hash = "sha256:4e80b05803749502995fe33b6f5fd589b51dc46e50d873baf0b515c8f6e7b668", size = 32002, upload-time = "2025-10-12T10:51:12.257Z" }, + { url = "https://files.pythonhosted.org/packages/87/6c/ee395ef8ee117ba2d158a23a9502bc4a706e02f63bfdf6d01b802ae6ee9a/rjsmin-1.2.5-cp314-cp314-manylinux2014_aarch64.whl", hash = "sha256:b6d0bc092acc3f54ea63ec1dcb808edaac5e956141d89fd0d038e80de5322052", size = 32435, upload-time = "2025-10-12T10:51:13.147Z" }, + { url = "https://files.pythonhosted.org/packages/1a/78/c157d33aa6148f0e8c57bb91a41969e1a4aab929f3bb0a8d9ff3b5e21556/rjsmin-1.2.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1e2943259be7beafdcb0847c2a901f223bf9044bdfa8105e1be1ad67d6c47795", size = 32877, upload-time = "2025-10-12T10:51:14.545Z" }, + { url = "https://files.pythonhosted.org/packages/e9/49/6252145bf85d87c815aaf441c5efdf1ce918db5ab6e915cf6d0d99ca3969/rjsmin-1.2.5-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:e0387568c27fb49e55c1d0dfc27b54fc63d04b7756b1fed9743078130262907f", size = 32957, upload-time = "2025-10-12T10:51:15.964Z" }, + { url = "https://files.pythonhosted.org/packages/15/7e/c321c047b1a2fb7fa5ac818c37c1a15d348e1c12a1148de8ca5192a83b8f/rjsmin-1.2.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:8196f1ecb0dff6c8647d4622e496869e94f1be92567ea2e941aa18d49a1a4347", size = 32456, upload-time = "2025-10-12T10:51:16.885Z" }, + { url = "https://files.pythonhosted.org/packages/5b/d7/2d190ce5ad10832df62edd4d9b1ae7092fd259ca58b39a1e202337f511a9/rjsmin-1.2.5-cp314-cp314t-manylinux1_i686.whl", hash = "sha256:9dd9f66568be9c8676278f140aa54102fab9af7feb59adf0c7a85bef49fe70df", size = 34115, upload-time = "2025-10-12T10:51:17.911Z" }, + { url = "https://files.pythonhosted.org/packages/76/ab/e7bcf261ede4cef7a0693927d7dcd1612bb59ba6c05191f58a92deec9f01/rjsmin-1.2.5-cp314-cp314t-manylinux1_x86_64.whl", hash = "sha256:5b8f72f7d96e5e1d30a33182cb39d4eb4516ddcd9b2f984813a9eefe66f8e180", size = 33977, upload-time = "2025-10-12T10:51:18.996Z" }, + { url = "https://files.pythonhosted.org/packages/a7/75/f1ff5f2199437b534204b40aa46c55c703489063cf7806c948a1a665575e/rjsmin-1.2.5-cp314-cp314t-manylinux2014_aarch64.whl", hash = "sha256:8c5906bd8830f616e992ad5e7277d0ea12c530110da188b2b9da23e9524a7cbc", size = 34604, upload-time = "2025-10-12T10:51:20.031Z" }, + { url = "https://files.pythonhosted.org/packages/d2/dc/acd463d88c56476cc683f1c6cce893c590007dccd390747e824b8e923d63/rjsmin-1.2.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8207bac0d3bab7791fd667f0863b5f32e51047845179b94b28c716e6514a9234", size = 34775, upload-time = "2025-10-12T10:51:21.364Z" }, + { url = "https://files.pythonhosted.org/packages/ce/56/e6f61718d1c36e646aabe552ad1f8f77744a4c57524eaa782b5b44eba220/rjsmin-1.2.5-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:1e3ab93a51d7581ba0a3b6a383df2929b86d9d55f9516764678f9b4e409826e8", size = 34682, upload-time = "2025-10-12T10:51:22.755Z" }, + { url = "https://files.pythonhosted.org/packages/00/f3/37a4672ddb1307eb57d9b54ba89a48f483a04a63cac4e1471fdb4cba76e6/rjsmin-1.2.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:47dad1732a2c4779bdc76d5b3183fdf2ec27838f31071fa9dfcc79483d3480e2", size = 34161, upload-time = "2025-10-12T10:51:23.761Z" }, +] + +[[package]] +name = "ruff" +version = "0.15.14" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/dc/8a/8bce2894573e9dae6ff4d77fe34ad727d79b9e6238ad288c5638990d90f6/ruff-0.15.14.tar.gz", hash = "sha256:48e866b165be4a9bdbf310f7d3c9a07edef2fe8cd63ffeb4e00bb590506ebf9f", size = 4700910, upload-time = "2026-05-21T14:34:55.177Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/c8/74a92c6ff9fcfb4f1f947126d3ebee8389276e161ecc85de5bda7cda51bd/ruff-0.15.14-py3-none-linux_armv6l.whl", hash = "sha256:8dd2db9416e487c8d4b01fa7056bb02c4d05969d4f8d17a08c229c2f4ff3c108", size = 10739177, upload-time = "2026-05-21T14:34:37.332Z" }, + { url = "https://files.pythonhosted.org/packages/45/91/254a35c20acc38a7223c9d2d594af12e794432464f2cdeb52af1dc4a892d/ruff-0.15.14-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:be4ff55af755bd71a00ab3dc6bd7ffc467bd76e0df6881e286c2e3d23e8fb43b", size = 11144969, upload-time = "2026-05-21T14:34:43.978Z" }, + { url = "https://files.pythonhosted.org/packages/56/9e/d13e40f83b8d0a94430e6778ce1d94a43b38cf2efe63278bdd2b4c65abbf/ruff-0.15.14-py3-none-macosx_11_0_arm64.whl", hash = "sha256:48d5909d7d06276ce7dde6d32bfa4b0d4cb2651145cd8ee4b440722cbc77832f", size = 10478207, upload-time = "2026-05-21T14:34:48.378Z" }, + { url = "https://files.pythonhosted.org/packages/8d/f1/b15a7839fa4f332f8acec78e20564f26bb2d866e3d21710b877fd0263000/ruff-0.15.14-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca8cbfa94c4f90984a67561978602746d4cd27103568f745fa90eee3f0d4107d", size = 10818459, upload-time = "2026-05-21T14:34:22.318Z" }, + { url = "https://files.pythonhosted.org/packages/45/33/53d651177f84f94b400a0e27f8824eeada3dddc9d5ee8aeb048f4352a520/ruff-0.15.14-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a6bbc0333f1ab053423bcbf6226477d266ca7cec7738c4c8e3f55647803f3c4", size = 10541800, upload-time = "2026-05-21T14:34:20.209Z" }, + { url = "https://files.pythonhosted.org/packages/b8/a6/868f87e0bf9786ed24b5d0d0ad8676b8a94fd1912f42cddf9cfc7857818a/ruff-0.15.14-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8a24a4f7605d7003a6674d4387651effd939dead3fddd0f36561eb77a9a2e542", size = 11342149, upload-time = "2026-05-21T14:34:46.365Z" }, + { url = "https://files.pythonhosted.org/packages/a7/8b/38cd5c19faffdcc05a408d2b78edccc69492ab9720eadb49ea15ef80d768/ruff-0.15.14-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:049b5326e53ed80978f2fc041a280603f69dd6b0c95464342a2bb4572d9d9e2f", size = 12212563, upload-time = "2026-05-21T14:34:28.579Z" }, + { url = "https://files.pythonhosted.org/packages/3e/4d/a3c5b874a556d5731e3e657aaf04311bb76f0a5c3ec220ed43051be6b64b/ruff-0.15.14-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d4ed42e6696c8dfa5f06728e6441993901f548eb92d73bc472cb5a38d1395fbf", size = 11493299, upload-time = "2026-05-21T14:34:41.836Z" }, + { url = "https://files.pythonhosted.org/packages/1e/c0/56472c251d09858a53e51efbd485b09e1995d8731668b76d52e5dd6ee0f1/ruff-0.15.14-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:715c543cf450c4888251f91c52f1942a800541d9bddd7ac060aa4e6b77ae7cba", size = 11455931, upload-time = "2026-05-21T14:34:57.276Z" }, + { url = "https://files.pythonhosted.org/packages/2c/4a/e2e7b4d8dbf233d4eace59c75bc3435fa6d8bd3bae82d351d4e4300c0fd1/ruff-0.15.14-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:72ebab6013ec887d439d8b7593737a0a4ffb06d45d209d4e4bf2e92813082d3f", size = 11400794, upload-time = "2026-05-21T14:34:39.773Z" }, + { url = "https://files.pythonhosted.org/packages/97/c7/83c0539fe34c3e09136204d1e75d6052492364e0b3cb05e9465423f567d7/ruff-0.15.14-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:49072d36abdbe97a8dd7f480afe9c675699c0c495d4c84076e2c1203c4550581", size = 10804759, upload-time = "2026-05-21T14:34:31.045Z" }, + { url = "https://files.pythonhosted.org/packages/86/a6/18f2bfc095a2ab4a78745644e428205532ce6653a5d0fa8501572891534d/ruff-0.15.14-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:958522aee105068640c2c2ceae08f413ae44d922f52a1374ac13d6a96032fc93", size = 10539517, upload-time = "2026-05-21T14:34:53.064Z" }, + { url = "https://files.pythonhosted.org/packages/54/3a/5a8b3b69c654d4e4bf1d246ac5b49cbcdac6eaab6905925f8915f31e3b80/ruff-0.15.14-py3-none-musllinux_1_2_i686.whl", hash = "sha256:f3707da619a143a2e8830e2abab8224478d69ace2d28cb6c20543ae97c36bf61", size = 11065169, upload-time = "2026-05-21T14:34:24.484Z" }, + { url = "https://files.pythonhosted.org/packages/ed/c5/8864e4e7925b836ea354b31d57641ec03830564e281a8b6f061f8c3e0ec1/ruff-0.15.14-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:bb01d645694e3ec0102105d07ef2d53703970407d59c04e59d3ba0b7a1d53553", size = 11560214, upload-time = "2026-05-21T14:34:50.975Z" }, + { url = "https://files.pythonhosted.org/packages/36/38/012bf76752e1f89ed50b77b99532d90f3a3e287bc7918e1fc0948ac866ac/ruff-0.15.14-py3-none-win32.whl", hash = "sha256:6d0c1ad2a0ab718d39b6d8fd2217981ce4d625cd96a720095f798fb47d8b13e6", size = 10805548, upload-time = "2026-05-21T14:34:33.453Z" }, + { url = "https://files.pythonhosted.org/packages/d1/b7/4ea2c170f10ad760fff2a5250beb18897719dc8b52b53a24cddbb9dd3f19/ruff-0.15.14-py3-none-win_amd64.whl", hash = "sha256:802342981e056db3851a7836e5b070f8f15f67d4a685ae2a6160939d364b2902", size = 11939523, upload-time = "2026-05-21T14:34:18.077Z" }, + { url = "https://files.pythonhosted.org/packages/62/d5/bc97ff895ec35cf3925d4bd60f3b39d822f377a446906ec9bcc87405e59b/ruff-0.15.14-py3-none-win_arm64.whl", hash = "sha256:ff47b90a9ef6a40c9e2f3b479c1fb78531adf055b94c1eba0a7ba04b31951826", size = 11208607, upload-time = "2026-05-21T14:34:26.525Z" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + +[[package]] +name = "sqlparse" +version = "0.5.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/90/76/437d71068094df0726366574cf3432a4ed754217b436eb7429415cf2d480/sqlparse-0.5.5.tar.gz", hash = "sha256:e20d4a9b0b8585fdf63b10d30066c7c94c5d7a7ec47c889a2d83a3caa93ff28e", size = 120815, upload-time = "2025-12-19T07:17:45.073Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/49/4b/359f28a903c13438ef59ebeee215fb25da53066db67b305c125f1c6d2a25/sqlparse-0.5.5-py3-none-any.whl", hash = "sha256:12a08b3bf3eec877c519589833aed092e2444e68240a3577e8e26148acc7b1ba", size = 46138, upload-time = "2025-12-19T07:17:46.573Z" }, +] + +[[package]] +name = "stevedore" +version = "5.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e9/88/35e4d27d9177d7df76d060e0a18f69c6c5794c96960c94042e20a12c8ba2/stevedore-5.8.0.tar.gz", hash = "sha256:b49867b32ca3016e94100e68dbf26e72aa7b8708d0a3f73c08aeb220370ac715", size = 514710, upload-time = "2026-05-18T09:15:27.731Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f5/ac/19f9941c74add59d17694930ec8105d5eddeee4ce56dd8632b765ca16d6c/stevedore-5.8.0-py3-none-any.whl", hash = "sha256:88eede9e66ca80e34085b9174e2327da2c61ac91f24f70e41c3ad76e4bb4872b", size = 54553, upload-time = "2026-05-18T09:15:25.82Z" }, +] + +[[package]] +name = "tornado" +version = "6.5.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/f1/3173dfa4a18db4a9b03e5d55325559dab51ee653763bb8745a75af491286/tornado-6.5.5.tar.gz", hash = "sha256:192b8f3ea91bd7f1f50c06955416ed76c6b72f96779b962f07f911b91e8d30e9", size = 516006, upload-time = "2026-03-10T21:31:02.067Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/59/8c/77f5097695f4dd8255ecbd08b2a1ed8ba8b953d337804dd7080f199e12bf/tornado-6.5.5-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:487dc9cc380e29f58c7ab88f9e27cdeef04b2140862e5076a66fb6bb68bb1bfa", size = 445983, upload-time = "2026-03-10T21:30:44.28Z" }, + { url = "https://files.pythonhosted.org/packages/ab/5e/7625b76cd10f98f1516c36ce0346de62061156352353ef2da44e5c21523c/tornado-6.5.5-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:65a7f1d46d4bb41df1ac99f5fcb685fb25c7e61613742d5108b010975a9a6521", size = 444246, upload-time = "2026-03-10T21:30:46.571Z" }, + { url = "https://files.pythonhosted.org/packages/b2/04/7b5705d5b3c0fab088f434f9c83edac1573830ca49ccf29fb83bf7178eec/tornado-6.5.5-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e74c92e8e65086b338fd56333fb9a68b9f6f2fe7ad532645a290a464bcf46be5", size = 447229, upload-time = "2026-03-10T21:30:48.273Z" }, + { url = "https://files.pythonhosted.org/packages/34/01/74e034a30ef59afb4097ef8659515e96a39d910b712a89af76f5e4e1f93c/tornado-6.5.5-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:435319e9e340276428bbdb4e7fa732c2d399386d1de5686cb331ec8eee754f07", size = 448192, upload-time = "2026-03-10T21:30:51.22Z" }, + { url = "https://files.pythonhosted.org/packages/be/00/fe9e02c5a96429fce1a1d15a517f5d8444f9c412e0bb9eadfbe3b0fc55bf/tornado-6.5.5-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:3f54aa540bdbfee7b9eb268ead60e7d199de5021facd276819c193c0fb28ea4e", size = 448039, upload-time = "2026-03-10T21:30:53.52Z" }, + { url = "https://files.pythonhosted.org/packages/82/9e/656ee4cec0398b1d18d0f1eb6372c41c6b889722641d84948351ae19556d/tornado-6.5.5-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:36abed1754faeb80fbd6e64db2758091e1320f6bba74a4cf8c09cd18ccce8aca", size = 447445, upload-time = "2026-03-10T21:30:55.541Z" }, + { url = "https://files.pythonhosted.org/packages/5a/76/4921c00511f88af86a33de770d64141170f1cfd9c00311aea689949e274e/tornado-6.5.5-cp39-abi3-win32.whl", hash = "sha256:dd3eafaaeec1c7f2f8fdcd5f964e8907ad788fe8a5a32c4426fbbdda621223b7", size = 448582, upload-time = "2026-03-10T21:30:57.142Z" }, + { url = "https://files.pythonhosted.org/packages/2c/23/f6c6112a04d28eed765e374435fb1a9198f73e1ec4b4024184f21faeb1ad/tornado-6.5.5-cp39-abi3-win_amd64.whl", hash = "sha256:6443a794ba961a9f619b1ae926a2e900ac20c34483eea67be4ed8f1e58d3ef7b", size = 448990, upload-time = "2026-03-10T21:30:58.857Z" }, + { url = "https://files.pythonhosted.org/packages/b7/c8/876602cbc96469911f0939f703453c1157b0c826ecb05bdd32e023397d4e/tornado-6.5.5-cp39-abi3-win_arm64.whl", hash = "sha256:2c9a876e094109333f888539ddb2de4361743e5d21eece20688e3e351e4990a6", size = 448016, upload-time = "2026-03-10T21:31:00.43Z" }, +] + +[[package]] +name = "ty" +version = "0.0.39" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/8d/7b5c74dc287fbcb37bae9853cec13bf44717c1735298500e4aeba31579a9/ty-0.0.39.tar.gz", hash = "sha256:f750277e76a01ecd86185960eca73823c26a53c51103568d56d4d904575159fd", size = 5702365, upload-time = "2026-05-22T21:09:56.403Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/08/17/9b89802c26d12d0f7a27bc25d4066d941d42891e8898f9f26499f0067e32/ty-0.0.39-py3-none-linux_armv6l.whl", hash = "sha256:c1bb7ac70f1f7d70cc6655fd96558039e4562b10f489fa49c7ebfd5fcee73ad1", size = 11360431, upload-time = "2026-05-22T21:09:18.689Z" }, + { url = "https://files.pythonhosted.org/packages/9c/c6/663ded50e823dbf9fb9d002eca46b7cb1fb2c72b744b84f22ce732a0ee0b/ty-0.0.39-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:3435b64c1e59c14c9aa39c20cc018823937cd38d55db853e74d95b8f420569b0", size = 11096281, upload-time = "2026-05-22T21:09:15.383Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ae/5d38ba9a6456ff4c78d212cf464fd8b9a25d8118465197b0b2dc891c0b19/ty-0.0.39-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5f136377ce46c73677701a9e1ad730bf72f699bcec046e422eb79d0886cac3ab", size = 10529674, upload-time = "2026-05-22T21:09:46.471Z" }, + { url = "https://files.pythonhosted.org/packages/be/6f/43638cb8106445d3c8817256a0731cde9dd7b6a53ae2e881294bc1930ca3/ty-0.0.39-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36b65fb0cc17f03e851d40e210d420be94ab8bc52d041328ad1e45f616036a61", size = 11055561, upload-time = "2026-05-22T21:09:36.981Z" }, + { url = "https://files.pythonhosted.org/packages/91/17/95e62cf4458527ce78dc386eba18f8b10c3fb64cd8c9e7e59b262ff6029d/ty-0.0.39-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4967967bfadf3860ff84c3fccdbaec8edf8aa20d0d727521084733d853de6657", size = 11127185, upload-time = "2026-05-22T21:09:31.395Z" }, + { url = "https://files.pythonhosted.org/packages/4e/c0/93666c213db5c71ab1b1f1a0db5f66bf8c7c0e0b0bf59859f5da8f0b3c36/ty-0.0.39-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e10ecb1297099ddf9a1f054f8bd921d1863ce85fb819a3c96ed27865a1ba6ed", size = 11608459, upload-time = "2026-05-22T21:09:12.862Z" }, + { url = "https://files.pythonhosted.org/packages/79/85/3b26585afc8b50230d6464bb0642feef4fab3f847e38b1f0ffa971a81446/ty-0.0.39-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9b19cca70e465d71b0510656343883d62372bbe74b7845cae7c0e701d6d5264b", size = 12177101, upload-time = "2026-05-22T21:09:40.519Z" }, + { url = "https://files.pythonhosted.org/packages/49/4a/1039e4f6afc576dc1c3a4d22a6478904a1ad3766597cd0b93c077ab9dfce/ty-0.0.39-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:56c6704b01b9b3d80ff26b2918423b742516d1e469bef830e9254dcedc9185bf", size = 11827815, upload-time = "2026-05-22T21:09:49.89Z" }, + { url = "https://files.pythonhosted.org/packages/e2/c5/4688652870e350a76a8157f7ffb59ad54f37d5d10725aa7076f66ac94ec8/ty-0.0.39-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40b7840ff46764b6a6757f4ade1cd0530fc3e8a0b435ca93e7602360e4cb90b6", size = 11694429, upload-time = "2026-05-22T21:09:21.568Z" }, + { url = "https://files.pythonhosted.org/packages/fc/72/8a1c4e823bb5bdc935a1c8140e100304e36a68a4139592f170aa9736fdb7/ty-0.0.39-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:1c62a3a87ce26b50819f0dbf03bd95f23f19eeb87bbc7aa732ec64277c77f1aa", size = 11869846, upload-time = "2026-05-22T21:09:28.053Z" }, + { url = "https://files.pythonhosted.org/packages/17/9f/cf982457b861ae22d657c5dcdbc631199f7f90264279db1d17230dfbc3ff/ty-0.0.39-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f8c34bc81a9c3516e49904e9d8330aac385377cca98390193ea02b903a40fcf0", size = 11029763, upload-time = "2026-05-22T21:09:06.791Z" }, + { url = "https://files.pythonhosted.org/packages/46/c9/95b64f6d43ae6e8f0b7e13dacf9c196d35819af22b1924171fba31383156/ty-0.0.39-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:66f5ab11586a64e79cb692ad685ee5469325c31b5f30bd3554f52f36dbe28cc4", size = 11146761, upload-time = "2026-05-22T21:09:10.178Z" }, + { url = "https://files.pythonhosted.org/packages/52/69/0a89cfb06f7632a05bf56c78e0affb4a40f81759e275376cea75c9c5abe9/ty-0.0.39-py3-none-musllinux_1_2_i686.whl", hash = "sha256:e8d89732bcbbcb091f439e556dfc4932f198b118b47d5b85212c60662099670e", size = 11281843, upload-time = "2026-05-22T21:09:34.234Z" }, + { url = "https://files.pythonhosted.org/packages/0e/53/64c4a27067a46643fea2b3fcf21a8a2f838d91a65ffdd14f2e82945b9538/ty-0.0.39-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:eceb6c91dcd05a231119f82abdd9aa337513de23ca6ac990bc44f88791dc1799", size = 11792477, upload-time = "2026-05-22T21:09:24.923Z" }, + { url = "https://files.pythonhosted.org/packages/1a/e8/02f4dd4a12bcdbda0006f9c7ff3b99a4be06bd0d257d3bd4a5b66de074e6/ty-0.0.39-py3-none-win32.whl", hash = "sha256:891c3262314dbc80bf3e872634d23dd216306945daa9a9fcc206ce5ed21ac4c9", size = 10615377, upload-time = "2026-05-22T21:09:43.167Z" }, + { url = "https://files.pythonhosted.org/packages/b5/5a/aaeb22faa8d4dae90a287d4c3636c671edcff3b99be5f4fc8b79ad71eef6/ty-0.0.39-py3-none-win_amd64.whl", hash = "sha256:ba7f2d54452535419e90f6f03ff39282999e87b43c21c00559f6d7ad711a36d5", size = 11710711, upload-time = "2026-05-22T21:09:53.179Z" }, + { url = "https://files.pythonhosted.org/packages/a3/17/ae7339651bfcaa5f54698c8c70eaf5031baa400ecb67baec31d03a56cbd4/ty-0.0.39-py3-none-win_arm64.whl", hash = "sha256:eb4cf0fefbbfedf9a352597bb2431ebdcb7eb3a595c0f825f228e897a0ec285d", size = 11081409, upload-time = "2026-05-22T21:09:03.741Z" }, +] + +[[package]] +name = "tzdata" +version = "2026.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/19/1b9b0e29f30c6d35cb345486df41110984ea67ae69dddbc0e8a100999493/tzdata-2026.2.tar.gz", hash = "sha256:9173fde7d80d9018e02a662e168e5a2d04f87c41ea174b139fbef642eda62d10", size = 198254, upload-time = "2026-04-24T15:22:08.651Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/e4/dccd7f47c4b64213ac01ef921a1337ee6e30e8c6466046018326977efd95/tzdata-2026.2-py2.py3-none-any.whl", hash = "sha256:bbe9af844f658da81a5f95019480da3a89415801f6cc966806612cc7169bffe7", size = 349321, upload-time = "2026-04-24T15:22:05.876Z" }, +] + +[[package]] +name = "tzlocal" +version = "5.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "tzdata", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8b/2e/c14812d3d4d9cd1773c6be938f89e5735a1f11a9f184ac3639b93cef35d5/tzlocal-5.3.1.tar.gz", hash = "sha256:cceffc7edecefea1f595541dbd6e990cb1ea3d19bf01b2809f362a03dd7921fd", size = 30761, upload-time = "2025-03-05T21:17:41.549Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c2/14/e2a54fabd4f08cd7af1c07030603c3356b74da07f7cc056e600436edfa17/tzlocal-5.3.1-py3-none-any.whl", hash = "sha256:eb1a66c3ef5847adf7a834f1be0800581b683b5608e74f86ecbcef8ab91bb85d", size = 18026, upload-time = "2025-03-05T21:17:39.857Z" }, +] + +[[package]] +name = "urllib3" +version = "2.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" }, +] + +[[package]] +name = "vine" +version = "5.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bd/e4/d07b5f29d283596b9727dd5275ccbceb63c44a1a82aa9e4bfd20426762ac/vine-5.1.0.tar.gz", hash = "sha256:8b62e981d35c41049211cf62a0a1242d8c1ee9bd15bb196ce38aefd6799e61e0", size = 48980, upload-time = "2023-11-05T08:46:53.857Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/03/ff/7c0c86c43b3cbb927e0ccc0255cb4057ceba4799cd44ae95174ce8e8b5b2/vine-5.1.0-py3-none-any.whl", hash = "sha256:40fdf3c48b2cfe1c38a49e9ae2da6fda88e4794c810050a728bd7413811fb1dc", size = 9636, upload-time = "2023-11-05T08:46:51.205Z" }, +] + +[[package]] +name = "virtualenv" +version = "21.3.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "distlib" }, + { name = "filelock" }, + { name = "platformdirs" }, + { name = "python-discovery" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/15/ba/1f6e8c957e4932be060dcdc482d339c12e0216351478add3645cdaa53c05/virtualenv-21.3.3.tar.gz", hash = "sha256:f5bda277e553b1c2b3c1a8debfc30496e1288cc93ce6b7b71b3280047e317328", size = 7613784, upload-time = "2026-05-13T18:01:30.19Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/34/a9dbe051de88a63eb7408ea66630bac38e72f7f6077d4be58737106860d9/virtualenv-21.3.3-py3-none-any.whl", hash = "sha256:7d5987d8369e098e41406efb780a3d4ca79280097293899e351a6407ee153ab3", size = 7594554, upload-time = "2026-05-13T18:01:27.815Z" }, +] + +[[package]] +name = "wcwidth" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2c/ee/afaf0f85a9a18fe47a67f1e4422ed6cf1fe642f0ae0a2f81166231303c52/wcwidth-0.7.0.tar.gz", hash = "sha256:90e3a7ea092341c44b99562e75d09e4d5160fe7a3974c6fb842a101a95e7eed0", size = 182132, upload-time = "2026-05-02T16:04:12.653Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/52/e465037f5375f43533d1a80b6923955201596a99142ed524d77b571a1418/wcwidth-0.7.0-py3-none-any.whl", hash = "sha256:5d69154c429a82910e241c738cd0e2976fac8a2dd47a1a805f4afed1c0f136f2", size = 110825, upload-time = "2026-05-02T16:04:11.033Z" }, +] + +[[package]] +name = "yarl" +version = "1.24.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "multidict" }, + { name = "propcache" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/79/12/1e8f37460ea0f7eb59c221fdaf0ed75e7ac43e97f8093b9c6f411df50a78/yarl-1.24.2.tar.gz", hash = "sha256:9ac374123c6fd7abf64d1fec93962b0bd4ee2c19751755a762a72dd96c0378f8", size = 210798, upload-time = "2026-05-19T21:31:05.599Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/0e/e08087695fc12789263821c5dc0f8dc52b5b17efd0887cacf419f8a43ba3/yarl-1.24.2-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:f9312b3c02d9b3d23840f67952913c9c8721d7f1b7db305289faefa878f364c2", size = 129670, upload-time = "2026-05-19T21:29:56.631Z" }, + { url = "https://files.pythonhosted.org/packages/3a/98/ab4b5ed1b1b5cd973c8a3eb994c3a6aefb6ce6d399e21bb5f0316c33815c/yarl-1.24.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:a4f4d6cd615823bfc7fb7e9b5987c3f41666371d870d51058f77e2680fbe9630", size = 91916, upload-time = "2026-05-19T21:29:58.645Z" }, + { url = "https://files.pythonhosted.org/packages/ba/b1/5297bb6a7df4782f7605bffc43b31f5044070935fbbcaa6c705a07e6ac65/yarl-1.24.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0c3063e5c0a8e8e62fae6c2596fa01da1561e4cd1da6fec5789f5cf99a8aefd8", size = 91625, upload-time = "2026-05-19T21:30:00.412Z" }, + { url = "https://files.pythonhosted.org/packages/02/a7/45baabfff76829264e623b185cff0c340d7e11bf3e1cd9ea37e7d17934bd/yarl-1.24.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fecd17873a096036c1c87ab3486f1aef7f269ada7f23f7f856f93b1cc7744f14", size = 104574, upload-time = "2026-05-19T21:30:02.544Z" }, + { url = "https://files.pythonhosted.org/packages/f3/40/3a5ab144d3d650ca37d4f4b57e56169be8af3ca34c448793e064b30baaed/yarl-1.24.2-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a46d1ab4ba4d32e6dc80daf8a28ce0bd83d08df52fbc32f3e288663427734535", size = 97534, upload-time = "2026-05-19T21:30:04.319Z" }, + { url = "https://files.pythonhosted.org/packages/9c/b5/5658fef3681fb5776b4513b052bec750009f47b3a592251c705d75375798/yarl-1.24.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:73e68edf6dfd5f73f9ca127d84e2a6f9213c65bdffb736bda19524c0564fcd14", size = 111481, upload-time = "2026-05-19T21:30:05.988Z" }, + { url = "https://files.pythonhosted.org/packages/4c/06/fdcd7dde037f00866dce123ed4ba23dba94beb56fc4cf561668d27be37f2/yarl-1.24.2-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a296ca617f2d25fbceafb962b88750d627e5984e75732c712154d058ae8d79a3", size = 111529, upload-time = "2026-05-19T21:30:07.738Z" }, + { url = "https://files.pythonhosted.org/packages/c2/53/d81269aaafccea0d33396c03035de997b743f11e648e6e27a0df99c72980/yarl-1.24.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e51b2cf5ec89a8b8470177641ed62a3ba22d74e1e898e06ad53aa77972487208", size = 107338, upload-time = "2026-05-19T21:30:09.713Z" }, + { url = "https://files.pythonhosted.org/packages/ae/04/23049463f729bd899df203a7960505a75333edd499cda8aa1d5a82b64df5/yarl-1.24.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:310fc687f7b2044ec54e372c8cbe923bb88f5c37bded0d3079e5791c2fc3cf50", size = 106147, upload-time = "2026-05-19T21:30:11.365Z" }, + { url = "https://files.pythonhosted.org/packages/14/18/04a4b5830b43ed5e4c5015b40e9f6241ad91487d71611061b4e111d6ac80/yarl-1.24.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:297a2fe352ecf858b30a98f87948746ec16f001d279f84aebdbd3bd965e2f1bd", size = 104272, upload-time = "2026-05-19T21:30:12.978Z" }, + { url = "https://files.pythonhosted.org/packages/5a/f7/8cffdf319aee7a7c1dbd07b61d91c3e3fda460c7a93b5f93e445f3806c4c/yarl-1.24.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:2a263e76b97bc42bdcd7c5f4953dec1f7cd62a1112fa7f869e57255229390d67", size = 99962, upload-time = "2026-05-19T21:30:15.001Z" }, + { url = "https://files.pythonhosted.org/packages/d7/39/b3cce3b7dbef64ac700ad4cea156a207d01bede0f507587616c364b5468e/yarl-1.24.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:822519b64cf0b474f1a0aaef1dc621438ea46bb77c94df97a5b4d213a7d8a8b1", size = 111063, upload-time = "2026-05-19T21:30:16.683Z" }, + { url = "https://files.pythonhosted.org/packages/a1/ea/100818505e7ebf165c7242ff17fdf7d9fee79e27234aeca871c1082920d7/yarl-1.24.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:b6067060d9dc594899ba83e6db6c48c68d1e494a6dab158156ed86977ca7bcb1", size = 105438, upload-time = "2026-05-19T21:30:18.769Z" }, + { url = "https://files.pythonhosted.org/packages/8f/d2/e075a0b32aa6625087de9e653087df0759fed5de4a435fef594181102a77/yarl-1.24.2-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:0063adad533e57171b79db3943b229d40dfafeeee579767f96541f106bac5f1b", size = 111458, upload-time = "2026-05-19T21:30:21.024Z" }, + { url = "https://files.pythonhosted.org/packages/e6/5c/ceea7ba98b65c8eb8d947fdc52f9bedfcd43c6a57c9e3c90c17be8f324a3/yarl-1.24.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ee8e3fb34513e8dc082b586ef4910c98335d43a6fab688cd44d4851bacfce3e8", size = 107589, upload-time = "2026-05-19T21:30:23.412Z" }, + { url = "https://files.pythonhosted.org/packages/fa/d9/5582d57e2b2db9b85eb6663a22efdd78e08805f3f5389566e9fcad254d1b/yarl-1.24.2-cp314-cp314-win_amd64.whl", hash = "sha256:afb00d7fd8e0f285ca29a44cc50df2d622ff2f7a6d933fa641577b5f9d5f3db0", size = 94424, upload-time = "2026-05-19T21:30:25.425Z" }, + { url = "https://files.pythonhosted.org/packages/92/10/7dc07a0e22806a9280f42a57361395506e800c64e22737cd7b0886feab42/yarl-1.24.2-cp314-cp314-win_arm64.whl", hash = "sha256:68cf6eacd6028ef1142bc4b48376b81566385ca6f9e7dde3b0fa91be08ffcb57", size = 88690, upload-time = "2026-05-19T21:30:27.623Z" }, + { url = "https://files.pythonhosted.org/packages/9e/13/d5b8e2c8667db955bcb3de233f18798fefe7edf1d7429c2c9d4f9c401114/yarl-1.24.2-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:221ce1dd921ac4f603957f17d7c18c5cc0797fbb52f156941f92e04605d1d67b", size = 136248, upload-time = "2026-05-19T21:30:29.297Z" }, + { url = "https://files.pythonhosted.org/packages/de/46/a4a97c05c9c9b8fd266bb2a0df12992c7fbd02391eb9640583411b6dab32/yarl-1.24.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5f3224db28173a00d7afacdee07045cc4673dfab2b15492c7ae10deddbece761", size = 95084, upload-time = "2026-05-19T21:30:31.031Z" }, + { url = "https://files.pythonhosted.org/packages/95/b2/845cf2074a015e6fe0d0808cf1a2d9e868386c4220d657ebd8302b199043/yarl-1.24.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c557165320d6244ebe3a02431b2a201a20080e02f41f0cfa0ccc47a183765da8", size = 95272, upload-time = "2026-05-19T21:30:33.062Z" }, + { url = "https://files.pythonhosted.org/packages/fe/16/e69d4aa244aef45235ddfebc0e04036a6829842bc5a6a795aedc6c998d23/yarl-1.24.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:904065e6e85b1fa54d0d87438bd58c14c0bad97aad654ad1077fd9d87e8478ed", size = 101497, upload-time = "2026-05-19T21:30:34.842Z" }, + { url = "https://files.pythonhosted.org/packages/15/94/c07107715d621076863ee88b3ddf183fa5e9d4aba5769623c9979828410a/yarl-1.24.2-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8cec2a38d70edc10e0e856ceda886af5327a017ccbde8e1de1bd44d300357543", size = 94002, upload-time = "2026-05-19T21:30:37.724Z" }, + { url = "https://files.pythonhosted.org/packages/a9/35/fc1bbdd895b5e4010b8fdd037f7ed3aa289d3863e08231b30231ca9a0815/yarl-1.24.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e7484b9361ed222ee1ca5b4337aa4cbdcc4618ce5aff57d9ef1582fd95893fc0", size = 106524, upload-time = "2026-05-19T21:30:40.196Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f2/32b66d0a4ba47c296cf86d03e2c67bff58399fe6d6d84d5205c04c66cc6d/yarl-1.24.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:84f9670b89f34db07f81e53aee83e0b938a3412329d51c8f922488be7fcc4024", size = 106165, upload-time = "2026-05-19T21:30:41.888Z" }, + { url = "https://files.pythonhosted.org/packages/95/47/37cb5ff50c5e825d4d38e81bb04d1b7e96bf960f7ab89f9850b162f3f114/yarl-1.24.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:abb2759733d63a28b4956500a5dd57140f26486c92b2caedfb964ab7d9b79dbf", size = 103010, upload-time = "2026-05-19T21:30:43.985Z" }, + { url = "https://files.pythonhosted.org/packages/6f/d2/4597912315096f7bb359e46e13bf8b60994fcbb2db29b804c0902ef4eff5/yarl-1.24.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:081c2bf54efe03774d0311172bc04fedf9ca01e644d4cd8c805688e527209bdc", size = 101128, upload-time = "2026-05-19T21:30:46.291Z" }, + { url = "https://files.pythonhosted.org/packages/b9/d5/c8e86e120521e646013d02a8e3b8884392e28494be8f392366e50d208efc/yarl-1.24.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:86746bef442aa479107fe28132e1277237f9c24c2f00b0b0cf22b3ee0904f2bb", size = 101382, upload-time = "2026-05-19T21:30:48.085Z" }, + { url = "https://files.pythonhosted.org/packages/fa/98/70b229236118f89dbeb739b76f10225bbf53b5497725502594c9a01d699a/yarl-1.24.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:2d07d21d0bc4b17558e8de0b02fbfdf1e347d3bb3699edd00bb92e7c57925420", size = 95964, upload-time = "2026-05-19T21:30:49.785Z" }, + { url = "https://files.pythonhosted.org/packages/87/f8/56c386981e3c8648d279fdef2397ffec577e8320fd5649745e34d54faeb7/yarl-1.24.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:4fb1ac3fc5fecd8ae7453ea237e4d22b49befa70266dfe1629924245c21a0c7f", size = 106204, upload-time = "2026-05-19T21:30:51.862Z" }, + { url = "https://files.pythonhosted.org/packages/1a/1e/765afe97811ca35933e2a7de70ac57b1997ea2e4ee895719ee7a231fb7e5/yarl-1.24.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:4da31a5512ed1729ca8d8aacde3f7faeb8843cde3165d6bcf7f88f74f17bb8aa", size = 101510, upload-time = "2026-05-19T21:30:53.62Z" }, + { url = "https://files.pythonhosted.org/packages/ee/78/393913f4b9039e1edd09ae8a9bbb9d539be909a8abf6d8a2084585bed4b7/yarl-1.24.2-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:533ded4dceb5f1f3da7906244f4e82cf46cfd40d84c69a1faf5ac506aa65ecbe", size = 105584, upload-time = "2026-05-19T21:30:55.962Z" }, + { url = "https://files.pythonhosted.org/packages/78/87/deb17b7049bbe74ea11a713b86f8f27800cc1c8648b0b797243ebb4830ba/yarl-1.24.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:7b3a85525f6e7eeabcfdd372862b21ee1915db1b498a04e8bf0e389b607ff0bd", size = 103410, upload-time = "2026-05-19T21:30:57.962Z" }, + { url = "https://files.pythonhosted.org/packages/8f/be/f9f7594e23b5b93affff0318e4593c1920331bcaefda326cabcad94296a1/yarl-1.24.2-cp314-cp314t-win_amd64.whl", hash = "sha256:a7624b1ca46ca5d7b864ef0d2f8efe3091454085ee1855b4e992314529972215", size = 102980, upload-time = "2026-05-19T21:30:59.735Z" }, + { url = "https://files.pythonhosted.org/packages/65/a4/ba80dccd3593ff1f01051a818694d07b58cb8232677ee9a22a5a1f93a9fc/yarl-1.24.2-cp314-cp314t-win_arm64.whl", hash = "sha256:e434a45ce2e7a947f951fc5a8944c8cc080b7e59f9c50ae80fd39107cf88126d", size = 91219, upload-time = "2026-05-19T21:31:01.934Z" }, + { url = "https://files.pythonhosted.org/packages/fd/4d/4b880086bd0d3e034d25647be1d830afc3e3f610e98c4ab3490af6b1b6d5/yarl-1.24.2-py3-none-any.whl", hash = "sha256:2783d9226db8797636cd6896e4de81feed252d1db72265686c9558d97a4d94b9", size = 53576, upload-time = "2026-05-19T21:31:03.909Z" }, +]