1
0
Fork 0
mirror of https://codeberg.org/Mo8it/AdvLabDB.git synced 2024-12-04 22:40:30 +00:00

Compare commits

...

19 commits

Author SHA1 Message Date
e15a420ef2 Remove deploy script after docker-compose 2022-11-19 19:54:10 +01:00
d054b0ddcb isort 2022-11-19 19:52:29 +01:00
79f76dc1a9 Raise version 2022-11-19 19:52:21 +01:00
57bb2459b7 Replace README 2022-11-19 19:51:00 +01:00
23091bdc61 Remove outdated server_setup documentation 2022-11-19 19:39:27 +01:00
a1c4d7682d Remove nginx for now 2022-11-19 18:17:01 +01:00
87627eeeee Fix tilde problem 2022-11-19 16:47:21 +01:00
e54cb97159 Fix gunicorn command 2022-11-19 16:42:56 +01:00
b54c9c5061 Name traefik network 2022-11-19 16:00:47 +01:00
d62fa116ce Name Dockerfile 2022-11-19 15:58:07 +01:00
742a38c3f9 Fix typo 2022-11-19 15:55:44 +01:00
42feee1917 Add restart unless-stopped 2022-11-19 15:54:28 +01:00
0a88cb18e8 Add advlabdb compose file 2022-11-19 15:45:18 +01:00
a75be7b7e2 Add traefik compose file 2022-11-19 15:45:12 +01:00
a8c43831fa Move files to deploy 2022-11-19 15:45:05 +01:00
ebcf997f8e Improve cache usage 2022-11-19 15:44:36 +01:00
ea9e3f1c82 Ignore more files in the container 2022-11-19 15:44:26 +01:00
a4b760ded0 Add Containerfile 2022-11-19 14:09:11 +01:00
131d22771f Update deps 2022-11-19 14:08:49 +01:00
16 changed files with 399 additions and 779 deletions

8
.containerignore Normal file
View file

@ -0,0 +1,8 @@
/.*
/dev_data/
/docs/
/migrations/
/poetry.lock
*.pyc
__pycache__/
/pyproject.toml

13
Containerfile Normal file
View file

@ -0,0 +1,13 @@
FROM docker.io/library/python:3.11-slim
EXPOSE 80
WORKDIR /volumes/repo
COPY requirements.txt .
RUN pip3 install -r requirements.txt
COPY . .
CMD ["gunicorn", "--bind", "0.0.0.0:80", "--workers", "5", "--log-file", "/volumes/logs/gunicorn.log", "run:create_app()"]

View file

@ -1,22 +0,0 @@
= AdvLabDB
image:https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white[pre-commit, link=https://github.com/pre-commit/pre-commit] image:https://img.shields.io/badge/code%20style-black-000000.svg[Code style: black, link=https://github.com/psf/black] image:https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336[Imports: isort, link=https://pycqa.github.io/isort/] image:https://img.shields.io/badge/security-bandit-yellow.svg[Security: bandit, link=https://github.com/PyCQA/bandit]
== About
AdvLabDB is a database with a web interface for labs.
// TODO: Screenshots
// TODO: Features
Admins have an interface to manage students, groups, experiments, appointments, marks and analyse data.
Assistants have a separate interface to set marks and schedule appointments with students.
== Status
The software is still in beta and under active development. Do not hesitate to open issues!
// TODO: New setup with containers
== What does the name mean?
**Adv**anced **Lab** **D**ata**B**ase

27
README.md Normal file
View file

@ -0,0 +1,27 @@
# AdvLabDB
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336)](https://pycqa.github.io/isort/)
[![security: bandit](https://img.shields.io/badge/security-bandit-yellow.svg)](https://github.com/PyCQA/bandit)
## About
AdvLabDB is a database with a web interface for labs.
// TODO: Screenshots
// TODO: Features
Admins have an interface to manage students, groups, experiments, appointments, marks and analyse data.
Assistants have a separate interface to set marks and schedule appointments with students.
## Status
Advlabdb is near the end of the beta stage and under active development. Do not hesitate to open issues!
// TODO: Setup with containers
## What does the name mean?
**Adv**anced **Lab** **D**ata**B**ase

View file

@ -2,7 +2,7 @@ from flask import Blueprint, redirect, url_for
from flask_login import current_user
from flask_security.decorators import auth_required
from . import settings, security
from . import security, settings
from .model_dependent_funs import active_semester_str
bp = Blueprint("main", __name__, root_path="/", template_folder="templates")

19
compose.yml Normal file
View file

@ -0,0 +1,19 @@
services:
advlabdb:
build:
context: .
dockerfile: Containerfile
container_name: advlabdb
restart: unless-stopped
volumes:
- ../data:/volumes/data:Z
- ../logs:/volumes/logs:Z
environment:
- ADVLABDB_DATA_DIR=/volumes/data
- TZ=Europe/Berlin
networks:
- traefik
networks:
traefik:
external: true

View file

@ -0,0 +1,20 @@
services:
traefik:
image: docker.io/library/traefik:latest
container_name: traefik
restart: unless-stopped
volumes:
- ./etc:/etc/traefik:Z,ro
- ./logs:/volumes/logs:Z
- ./certs:/volumes/certs:Z
environment:
- TZ=Europe/Berlin
networks:
- traefik
ports:
- "80:80"
- "443:443"
networks:
traefik:
name: traefik

View file

@ -12,4 +12,4 @@ http:
advlabdb:
loadBalancer:
servers:
- url: http://advlabdb-nginx
- url: http://advlabdb

View file

@ -1,181 +0,0 @@
= Server setup
== Server specifications
The setup was tested on Debian 11.3. It should also work on other Debian based Linux distributions. For distributions not based on Debian, some modifications might be necessary in the setup script `server_setup.py`.
Two CPU cores should be more than enough for the server.
The needed disk space depends on the database size after long usage.
== Setup
. Root setup
.. `ssh` as `root`:
+
[source,bash]
----
ssh root@SERVER_NAME
----
.. Run the following (as root):
+
[source,bash]
----
# Install needed packages
apt update
apt install sudo python3 git -y
# Add a sudo user with the name 'admin'
sudo useradd admin
sudo usermod -aG sudo admin
sudo mkhomedir_helper admin
# Enter a new password for 'admin'
sudo passwd admin
# Break the SSH connection
exit
----
. Admin setup
.. `ssh` again with the new user `admin` and password:
+
[source,bash]
----
ssh admin@SERVER_NAME
----
.. Clone the repository with `git clone` into `/home/admin/advlabdb`.
.. `cd` into the new cloned repository:
+
[source,bash]
----
cd ~/advlabdb
----
.. Settings
... Copy the example file for the settings:
+
[source,bash]
----
cp settings_example.ini settings.ini
----
... Enter your SERVER_NAME in `settings.ini`.
.. Timezone
... List all available timezones:
+
[source,bash]
----
sudo timedatectl list-timezones
----
... Choose your timezone and enter it as showed while listing as your timezone using this command (with Europe/Berlin as example):
+
[source,bash]
----
sudo timedatectl set-timezone Europe/Berlin
----
.. Edit the file `/etc/hostname` with `sudo` such that its content is only your SERVER_NAME.
.. Edit the file `/etc/hosts` with `sudo` such that the first two lines are:
+
[source,bash]
----
127.0.0.1 localhost
127.0.1.1 SERVER_NAME SERVER_NAME_WITHOUT_DOMAIN
----
.. Run the server setup script:
+
[source,bash]
----
python3 advlabdb/scripts/setup/server_setup.py
----
.. The setup script will cause the server to reboot at the end. After the reboot ssh again:
+
[source,bash]
----
ssh admin@SERVER_NAME
----
.. Change working directory to the repository:
+
[source,bash]
----
cd ~/advlabdb
----
.. Run database initialization script:
+
[source,bash]
----
poetry run python3 manage.py setup init-db
----
.. *Done!* Now go to your SERVER_NAME using a browser to verify that everything is working.
== SSH configuration
IMPORTANT: This section is important for security!
=== SSH key
For the authentication using SSH, generate a SSH key pair on your _own machine_ (not on the server) and upload the public key to the server using the command `ssh-copy-id`:
[source,bash]
----
ssh-copy-id -i KEY.pub admin@SERVER_NAME
----
=== SSH configuration file
On the server, open the file `/etc/ssh/sshd_config` with in an editor like `nano` or `vim` with `sudo`, then do the following:
. Disable login to root
+
Change
+
----
PermitRootLogin yes
----
+
to
+
----
PermitRootLogin no
----
. Disable login with password
+
WARNING: Make sure that you did upload your public key to the server for the SSH authentication! Otherwise, you will not be able to login to the server after this change.
+
Change
+
----
#PasswordAuthentication yes
----
+
to
+
----
PasswordAuthentication no
----
. Disable X11Forwarding
+
Change
+
----
X11Forwarding yes
----
+
to
+
----
X11Forwarding no
----

View file

@ -1,282 +0,0 @@
#!/usr/bin/env python3
import subprocess # nosec 404
import sys
from argparse import ArgumentParser
from pathlib import Path
# Variables
# You might want to change some.
# Volumes
VOLUMES_DIR = Path.home() / "volumes"
# AdvLabDB
ADVLABDB_REPO_LINK = "https://codeberg.org/Mo8it/AdvLabDB.git"
ADVLABDB_VOLUMES_DIR = VOLUMES_DIR / "advlabdb"
ADVLABDB_REPO_DIR = ADVLABDB_VOLUMES_DIR / "repo"
ADVLABDB_LOGS_DIR = ADVLABDB_VOLUMES_DIR / "logs"
ADVLABDB_DATA_DIR = ADVLABDB_VOLUMES_DIR / "data"
# Nginx
NGINX_CONF_D_DIR = ADVLABDB_VOLUMES_DIR / "nginx/conf.d"
# Traefik
TRAEFIK_VOLUMES_DIR = VOLUMES_DIR / "traefik"
TRAEFIK_ETC_DIR = TRAEFIK_VOLUMES_DIR / "etc"
TRAEFIK_LOGS_DIR = TRAEFIK_VOLUMES_DIR / "logs"
TRAEFIK_CERTS_DIR = TRAEFIK_VOLUMES_DIR / "certs"
# Systemd
SYSTEMD_USER_DIR = Path.home() / ".config/systemd/user"
# Parse script arguments
parser = ArgumentParser(
description="Build the AdvLabDB image and deploy related containers.",
)
parser.add_argument(
"--skip-traefik",
action="store_true",
help="Do not deploy the Traefik container.",
)
parser.add_argument(
"-n",
"--network",
default="traefik",
help="Traefik's network. Default: traefik.",
)
parser.add_argument(
"-v",
"--verbose",
action="store_true",
help="Show more information while running.",
)
args = parser.parse_args()
# Functions
def run(command: str, **kwargs):
print("\n\nRunning command:")
print(f"\t{command}\n")
return subprocess.run(command, shell=True, **kwargs) # nosec B602
# Needed for create_container
if args.verbose:
print(f"Making sure that the systemd directory for user services {SYSTEMD_USER_DIR} exists.")
SYSTEMD_USER_DIR.mkdir(parents=True, exist_ok=True)
def create_container(container_name: str, podman_args: str):
"""
Create a container with a systemd service.
"""
print(f"Creating container: {container_name}.")
run(
f"""podman create \
--name {container_name} \
--tz local \
{podman_args}""",
check=True,
)
print(f"Generating a systemd service then enabling and starting it for the container {container_name}.")
print(f"The service is a user service named container-{container_name}.")
print("You can check its status with the following command:")
print(f"\tsystemctl --user status container-{container_name}")
run(
f"podman generate systemd --new --files --name {container_name}",
cwd=SYSTEMD_USER_DIR,
check=True,
)
run(
f"systemctl --user enable --now container-{container_name}",
check=True,
)
def pull_or_clone_repo():
if ADVLABDB_REPO_DIR.is_dir():
print("Pulling AdvLabDB repository.")
run(
"git pull --rebase origin main",
cwd=ADVLABDB_REPO_DIR,
check=True,
)
else:
if args.verbose:
print(f"Making sure that the volumes directory {ADVLABDB_VOLUMES_DIR} exists.")
ADVLABDB_VOLUMES_DIR.mkdir(parents=True, exist_ok=True)
print("Cloning AdvLabDB repository")
print(f"From:\t{ADVLABDB_REPO_LINK}")
print(f"Into:\t{ADVLABDB_REPO_DIR}")
run(
f"git clone {ADVLABDB_REPO_LINK} {ADVLABDB_REPO_DIR}",
check=True,
)
def check_requirements():
settings_file = ADVLABDB_DATA_DIR / "settings.ini"
if not settings_file.is_file():
sys.exit(f"{settings_file} missing!")
if not NGINX_CONF_D_DIR.is_dir():
sys.exit(f"{NGINX_CONF_D_DIR} missing!")
if not args.skip_traefik:
if not TRAEFIK_ETC_DIR.is_dir():
sys.exit(f"{TRAEFIK_ETC_DIR} missing!")
if run(f"podman network exists {args.network}").returncode != 0:
if args.skip_traefik:
sys.exit(f"Skipped Traefik's deployment although Traefik's network {args.network} does not exist!")
else:
print(f"Creating network {args.network}.")
run(
f"podman network create {args.network}",
# Commented out because old buildah versions do not support "network exists"
# check=True,
)
def create_nginx_container():
create_container(
"advlabdb-nginx",
f"""--network {args.network} \
-v {NGINX_CONF_D_DIR}:/etc/nginx/conf.d:Z,ro \
--label "io.containers.autoupdate=registry" \
docker.io/library/nginx:alpine""",
)
def create_traefik_container():
if args.verbose:
print(f"Making sure that the logs directory {TRAEFIK_LOGS_DIR} exists.")
TRAEFIK_LOGS_DIR.mkdir(parents=True, exist_ok=True)
if args.verbose:
print(f"Making sure that the certificates directory {TRAEFIK_CERTS_DIR} exists.")
TRAEFIK_CERTS_DIR.mkdir(parents=True, exist_ok=True)
create_container(
"traefik",
f"""--network {args.network} \
-p 80:80 \
-p 443:443 \
-v {TRAEFIK_ETC_DIR}:/etc/traefik:Z,ro \
-v {TRAEFIK_LOGS_DIR}:/volumes/logs:Z \
-v {TRAEFIK_CERTS_DIR}:/volumes/certs:Z \
--label "io.containers.autoupdate=registry" \
docker.io/library/traefik:latest""",
)
# Needed for main and create_advlabdb_container
advlabdb_container_args = f"""--network {args.network} \
-e ADVLABDB_DATA_DIR=/volumes/data \
-v {ADVLABDB_REPO_DIR}:/volumes/repo:Z \
-v {ADVLABDB_DATA_DIR}:/volumes/data:Z \
-v {ADVLABDB_LOGS_DIR}:/volumes/logs:Z"""
def create_advlabdb_container():
create_container(
"advlabdb",
f"{advlabdb_container_args} localhost/advlabdb:latest",
)
def main():
pull_or_clone_repo()
# Checking requirements
check_requirements()
# Create/update the AdvLabDB image and container
# Make sure that the builder container does not exist.
run(
"buildah rm builder",
stderr=subprocess.DEVNULL,
)
requirements_file = ADVLABDB_REPO_DIR / "requirements.txt"
container_cmd = (
"\"gunicorn --bind 0.0.0.0:80 --workers 5 --log-file /volumes/logs/gunicorn.log 'run:create_app()'\""
)
print("Creating AdvLabDB image.")
commands = (
# Start building from a base image
"buildah from --pull --name builder docker.io/library/python:3.10-slim",
# Install Python requirements in the container
f"buildah copy builder {requirements_file} /root/requirements.txt",
"buildah run builder -- pip3 install -r /root/requirements.txt",
"buildah run builder -- rm /root/requirements.txt",
# Set the working directory of the container
"buildah config --workingdir /volumes/repo builder",
# Set the command that will run after starting the container
f"buildah config --cmd {container_cmd} builder",
)
for command in commands:
run(command, check=True)
if run("systemctl --user is-enabled container-advlabdb").returncode == 0:
print("Disabling and deleting existing container advlabdb.")
run(
"systemctl --user disable --now container-advlabdb",
check=True,
)
if run("podman image exists localhost/advlabdb:latest").returncode == 0:
print("Deleting existing image advlabdb.")
run(
"podman rmi localhost/advlabdb:latest",
check=True,
)
# Save new image
run(
"buildah commit --rm builder advlabdb",
check=True,
)
if args.verbose:
print(f"Making sure that the logs directory {ADVLABDB_LOGS_DIR} exists.")
ADVLABDB_LOGS_DIR.mkdir(parents=True, exist_ok=True)
# Running setup commands (if needed)
run_manage = f"podman run -it --rm {advlabdb_container_args} localhost/advlabdb:latest python3 manage.py"
commands = (
# Generate secret keys if secrets.ini does not exist yet
f"{run_manage} setup generate-secrets",
# Initialize a database if none exists
f"{run_manage} setup init-db",
)
for command in commands:
run(command, check=True)
create_advlabdb_container()
# Create Traefik container if needed
if not args.skip_traefik and run("systemctl --user is-enabled container-traefik").returncode != 0:
create_traefik_container()
# Create Nginx container if needed
if run("systemctl --user is-enabled container-advlabdb-nginx").returncode != 0:
create_nginx_container()
else:
run("systemctl --user restart container-advlabdb-nginx")
print("\nDone!\n")
if __name__ == "__main__":
main()

View file

@ -1,13 +0,0 @@
server {
listen 80;
# Uncomment following line and replace SERVER_NAME!
# server_name SERVER_NAME;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://advlabdb;
}
}

106
poetry.lock generated
View file

@ -142,7 +142,7 @@ Werkzeug = ">=1.0.1"
[[package]]
name = "flask-migrate"
version = "3.1.0"
version = "4.0.0"
description = "SQLAlchemy database migrations for Flask applications using Alembic."
category = "main"
optional = false
@ -309,7 +309,7 @@ python-versions = ">=3.7"
[[package]]
name = "mako"
version = "1.2.3"
version = "1.2.4"
description = "A super-fast templating language that borrows the best ideas from the existing templating languages."
category = "main"
optional = false
@ -420,7 +420,7 @@ six = ">=1.5"
[[package]]
name = "setuptools"
version = "65.5.1"
version = "65.6.0"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
category = "main"
optional = false
@ -459,7 +459,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
[[package]]
name = "sqlalchemy"
version = "1.4.43"
version = "1.4.44"
description = "Database Abstraction Library"
category = "main"
optional = false
@ -535,8 +535,8 @@ email = ["email-validator"]
[metadata]
lock-version = "1.1"
python-versions = "^3.10"
content-hash = "557e589053eab97e7bc9276d5eefcf12fb2178b71455d38e7d2190a786d27fad"
python-versions = "^3.11"
content-hash = "6fa824b8aac5ae426b3fbfcb6dc69e740171867dbf1d9dde4636df4235558ee9"
[metadata.files]
alembic = [
@ -650,8 +650,8 @@ flask-login = [
{file = "Flask_Login-0.6.2-py3-none-any.whl", hash = "sha256:1ef79843f5eddd0f143c2cd994c1b05ac83c0401dc6234c143495af9a939613f"},
]
flask-migrate = [
{file = "Flask-Migrate-3.1.0.tar.gz", hash = "sha256:57d6060839e3a7f150eaab6fe4e726d9e3e7cffe2150fb223d73f92421c6d1d9"},
{file = "Flask_Migrate-3.1.0-py3-none-any.whl", hash = "sha256:a6498706241aba6be7a251078de9cf166d74307bca41a4ca3e403c9d39e2f897"},
{file = "Flask-Migrate-4.0.0.tar.gz", hash = "sha256:2a301c3040af6844f29d9149abe428a0f08ebc8fa149e72113bbb36fa341920a"},
{file = "Flask_Migrate-4.0.0-py3-none-any.whl", hash = "sha256:e75a46b657e3062296b9f6e92f31e19662f76cfee8abd6ae94640cbcb79fe016"},
]
flask-principal = [
{file = "Flask-Principal-0.4.0.tar.gz", hash = "sha256:f5d6134b5caebfdbb86f32d56d18ee44b080876a27269560a96ea35f75c99453"},
@ -818,8 +818,8 @@ kiwisolver = [
{file = "kiwisolver-1.4.4.tar.gz", hash = "sha256:d41997519fcba4a1e46eb4a2fe31bc12f0ff957b2b81bac28db24744f333e955"},
]
mako = [
{file = "Mako-1.2.3-py3-none-any.whl", hash = "sha256:c413a086e38cd885088d5e165305ee8eed04e8b3f8f62df343480da0a385735f"},
{file = "Mako-1.2.3.tar.gz", hash = "sha256:7fde96466fcfeedb0eed94f187f20b23d85e4cb41444be0e542e2c8c65c396cd"},
{file = "Mako-1.2.4-py3-none-any.whl", hash = "sha256:c97c79c018b9165ac9922ae4f32da095ffd3c4e6872b45eded42926deea46818"},
{file = "Mako-1.2.4.tar.gz", hash = "sha256:d60a3903dc3bb01a18ad6a89cdbe2e4eadc69c0bc8ef1e3773ba53d44c3f7a34"},
]
markupsafe = [
{file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"},
@ -1014,8 +1014,8 @@ python-dateutil = [
{file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
]
setuptools = [
{file = "setuptools-65.5.1-py3-none-any.whl", hash = "sha256:d0b9a8433464d5800cbe05094acf5c6d52a91bfac9b52bcfc4d41382be5d5d31"},
{file = "setuptools-65.5.1.tar.gz", hash = "sha256:e197a19aa8ec9722928f2206f8de752def0e4c9fc6953527360d1c36d94ddb2f"},
{file = "setuptools-65.6.0-py3-none-any.whl", hash = "sha256:6211d2f5eddad8757bd0484923ca7c0a6302ebc4ab32ea5e94357176e0ca0840"},
{file = "setuptools-65.6.0.tar.gz", hash = "sha256:d1eebf881c6114e51df1664bc2c9133d022f78d12d5f4f665b9191f084e2862d"},
]
setuptools-scm = [
{file = "setuptools_scm-7.0.5-py3-none-any.whl", hash = "sha256:7930f720905e03ccd1e1d821db521bff7ec2ac9cf0ceb6552dd73d24a45d3b02"},
@ -1026,47 +1026,47 @@ six = [
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
]
sqlalchemy = [
{file = "SQLAlchemy-1.4.43-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:491d94879f9ec0dea7e1cb053cd9cc65a28d2467960cf99f7b3c286590406060"},
{file = "SQLAlchemy-1.4.43-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:eeb55a555eef1a9607c1635bbdddd0b8a2bb9713bcb5bc8da1e8fae8ee46d1d8"},
{file = "SQLAlchemy-1.4.43-cp27-cp27m-win32.whl", hash = "sha256:7d6293010aa0af8bd3b0c9993259f8979db2422d6abf85a31d70ec69cb2ee4dc"},
{file = "SQLAlchemy-1.4.43-cp27-cp27m-win_amd64.whl", hash = "sha256:27479b5a1e110e64c56b18ffbf8cf99e101572a3d1a43943ea02158f1304108e"},
{file = "SQLAlchemy-1.4.43-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:13ce4f3a068ec4ef7598d2a77f42adc3d90c76981f5a7c198756b25c4f4a22ea"},
{file = "SQLAlchemy-1.4.43-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:aa12e27cb465b4b006ffb777624fc6023363e01cfed2d3f89d33fb6da80f6de2"},
{file = "SQLAlchemy-1.4.43-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d16aca30fad4753aeb4ebde564bbd4a248b9673e4f879b940f4e806a17be87f"},
{file = "SQLAlchemy-1.4.43-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cde363fb5412ab178f1cc1e596e9cfc396464da8a4fe8e733cc6d6b4e2c23aa9"},
{file = "SQLAlchemy-1.4.43-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4abda3e693d24169221ffc7aa0444ccef3dc43dfeab6ad8665d3836751cd6af7"},
{file = "SQLAlchemy-1.4.43-cp310-cp310-win32.whl", hash = "sha256:fa46d86a17cccd48c6762df1a60aecf5aaa2e0c0973efacf146c637694b62ffd"},
{file = "SQLAlchemy-1.4.43-cp310-cp310-win_amd64.whl", hash = "sha256:962c7c80c54a42836c47cb0d8a53016986c8584e8d98e90e2ea723a4ed0ba85b"},
{file = "SQLAlchemy-1.4.43-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f6e036714a586f757a3e12ff0798ce9a90aa04a60cff392d8bcacc5ecf79c95e"},
{file = "SQLAlchemy-1.4.43-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d05d7365c2d1df03a69d90157a3e9b3e7b62088cca8ee6686aed2598659a6e14"},
{file = "SQLAlchemy-1.4.43-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59bd0ae166253f7fed8c3f4f6265d2637f25d2f6614d00df34d7ee0d95d29c91"},
{file = "SQLAlchemy-1.4.43-cp311-cp311-win32.whl", hash = "sha256:0c8a174f23bc021aac97bcb27fbe2ae3d4652d3d23e5768bc2ec3d44e386c7eb"},
{file = "SQLAlchemy-1.4.43-cp311-cp311-win_amd64.whl", hash = "sha256:5d5937e1bf7921e4d1acdfad72dd98d9e7f9ea5c52aeb12b3b05b534b527692d"},
{file = "SQLAlchemy-1.4.43-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:ed1c950aba723b7a5b702b88f05d883607c587de918d7d8c2014fe7f55cf67e0"},
{file = "SQLAlchemy-1.4.43-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f5438f6c768b7e928f0463777b545965648ba0d55877afd14a4e96d2a99702e7"},
{file = "SQLAlchemy-1.4.43-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:41df873cdae1d56fde97a1b4f6ffa118f40e4b2d6a6aa8c25c50eea31ecbeb08"},
{file = "SQLAlchemy-1.4.43-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a22f46440e61d90100e0f378faac40335fb5bbf278472df0d83dc15b653b9896"},
{file = "SQLAlchemy-1.4.43-cp36-cp36m-win32.whl", hash = "sha256:529e2cc8af75811114e5ab2eb116fd71b6e252c6bdb32adbfcd5e0c5f6d5ab06"},
{file = "SQLAlchemy-1.4.43-cp36-cp36m-win_amd64.whl", hash = "sha256:c1ced2fae7a1177a36cf94d0a5567452d195d3b4d7d932dd61f123fb15ddf87b"},
{file = "SQLAlchemy-1.4.43-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:736d4e706adb3c95a0a7e660073a5213dfae78ff2df6addf8ff2918c83fbeebe"},
{file = "SQLAlchemy-1.4.43-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23a4569d3db1ce44370d05c5ad79be4f37915fcc97387aef9da232b95db7b695"},
{file = "SQLAlchemy-1.4.43-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:42bff29eaecbb284f614f4bb265bb0c268625f5b93ce6268f8017811e0afbdde"},
{file = "SQLAlchemy-1.4.43-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee9613b0460dce970414cfc990ca40afe518bc139e697243fcdf890285fb30ac"},
{file = "SQLAlchemy-1.4.43-cp37-cp37m-win32.whl", hash = "sha256:dc1e005d490c101d27657481a05765851ab795cc8aedeb8d9425595088b20736"},
{file = "SQLAlchemy-1.4.43-cp37-cp37m-win_amd64.whl", hash = "sha256:c9a6e878e63286392b262d86d21fe16e6eec12b95ccb0a92c392f2b1e0acca03"},
{file = "SQLAlchemy-1.4.43-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:c6de20de7c19b965c007c9da240268dde1451865099ca10f0f593c347041b845"},
{file = "SQLAlchemy-1.4.43-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2fef01240d32ada9007387afd8e0b2230f99efdc4b57ca6f1d1192fca4fcf6a5"},
{file = "SQLAlchemy-1.4.43-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b6fd58e25e6cdd2a131d7e97f9713f8f2142360cd40c75af8aa5b83d535f811c"},
{file = "SQLAlchemy-1.4.43-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35dc0a5e934c41e282e019c889069b01ff4cd356b2ea452c9985e1542734cfb1"},
{file = "SQLAlchemy-1.4.43-cp38-cp38-win32.whl", hash = "sha256:fb9a44e7124f72b79023ab04e1c8fcd8f392939ef0d7a75beae8634e15605d30"},
{file = "SQLAlchemy-1.4.43-cp38-cp38-win_amd64.whl", hash = "sha256:4a791e7a1e5ac33f70a3598f8f34fdd3b60c68593bbb038baf58bc50e02d7468"},
{file = "SQLAlchemy-1.4.43-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:c9b59863e2b1f1e1ebf9ee517f86cdfa82d7049c8d81ad71ab58d442b137bbe9"},
{file = "SQLAlchemy-1.4.43-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd80300d81d92661e2488a4bf4383f0c5dc6e7b05fa46d2823e231af4e30539a"},
{file = "SQLAlchemy-1.4.43-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c3dde668edea70dc8d55a74d933d5446e5a97786cdd1c67c8e4971c73bd087ad"},
{file = "SQLAlchemy-1.4.43-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b462c070769f0ef06ea5fe65206b970bcf2b59cb3fda2bec2f4729e1be89c13"},
{file = "SQLAlchemy-1.4.43-cp39-cp39-win32.whl", hash = "sha256:c1f5bfffc3227d05d90c557b10604962f655b4a83c9f3ad507a81ac8d6847679"},
{file = "SQLAlchemy-1.4.43-cp39-cp39-win_amd64.whl", hash = "sha256:a7fa3e57a7b0476fbcba72b231150503d53dbcbdd23f4a86be5152912a923b6e"},
{file = "SQLAlchemy-1.4.43.tar.gz", hash = "sha256:c628697aad7a141da8fc3fd81b4874a711cc84af172e1b1e7bbfadf760446496"},
{file = "SQLAlchemy-1.4.44-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:da60b98b0f6f0df9fbf8b72d67d13b73aa8091923a48af79a951d4088530a239"},
{file = "SQLAlchemy-1.4.44-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:95f4f8d62589755b507218f2e3189475a4c1f5cc9db2aec772071a7dc6cd5726"},
{file = "SQLAlchemy-1.4.44-cp27-cp27m-win32.whl", hash = "sha256:afd1ac99179d1864a68c06b31263a08ea25a49df94e272712eb2824ef151e294"},
{file = "SQLAlchemy-1.4.44-cp27-cp27m-win_amd64.whl", hash = "sha256:f8e5443295b218b08bef8eb85d31b214d184b3690d99a33b7bd8e5591e2b0aa1"},
{file = "SQLAlchemy-1.4.44-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:53f90a2374f60e703c94118d21533765412da8225ba98659de7dd7998641ab17"},
{file = "SQLAlchemy-1.4.44-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:65a0ad931944fcb0be12a8e0ac322dbd3ecf17c53f088bc10b6da8f0caac287b"},
{file = "SQLAlchemy-1.4.44-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:595b185041a4dc5c685283ea98c2f67bbfa47bb28e4a4f5b27ebf40684e7a9f8"},
{file = "SQLAlchemy-1.4.44-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:80ead36fb1d676cc019586ffdc21c7e906ce4bf243fe4021e4973dae332b6038"},
{file = "SQLAlchemy-1.4.44-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68e0cd5d32a32c4395168d42f2fefbb03b817ead3a8f3704b8bd5697c0b26c24"},
{file = "SQLAlchemy-1.4.44-cp310-cp310-win32.whl", hash = "sha256:ae1ed1ebc407d2f66c6f0ec44ef7d56e3f455859df5494680e2cf89dad8e3ae0"},
{file = "SQLAlchemy-1.4.44-cp310-cp310-win_amd64.whl", hash = "sha256:6f0ea4d7348feb5e5d0bf317aace92e28398fa9a6e38b7be9ec1f31aad4a8039"},
{file = "SQLAlchemy-1.4.44-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f5e8ed9cde48b76318ab989deeddc48f833d2a6a7b7c393c49b704f67dedf01d"},
{file = "SQLAlchemy-1.4.44-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c857676d810ca196be73c98eb839125d6fa849bfa3589be06201a6517f9961c"},
{file = "SQLAlchemy-1.4.44-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c56e6899fa6e767e4be5d106941804a4201c5cb9620a409c0b80448ec70b656"},
{file = "SQLAlchemy-1.4.44-cp311-cp311-win32.whl", hash = "sha256:c46322354c58d4dc039a2c982d28284330f8919f31206894281f4b595b9d8dbe"},
{file = "SQLAlchemy-1.4.44-cp311-cp311-win_amd64.whl", hash = "sha256:7313e4acebb9ae88dbde14a8a177467a7625b7449306c03a3f9f309b30e163d0"},
{file = "SQLAlchemy-1.4.44-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:17aee7bfcef7bf0dea92f10e5dfdd67418dcf6fe0759f520e168b605855c003e"},
{file = "SQLAlchemy-1.4.44-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9470633395e5f24d6741b4c8a6e905bce405a28cf417bba4ccbaadf3dab0111d"},
{file = "SQLAlchemy-1.4.44-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:393f51a09778e8984d735b59a810731394308b4038acdb1635397c2865dae2b6"},
{file = "SQLAlchemy-1.4.44-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c7e3b9e01fdbe1ce3a165cc7e1ff52b24813ee79c6df6dee0d1e13888a97817e"},
{file = "SQLAlchemy-1.4.44-cp36-cp36m-win32.whl", hash = "sha256:6a06c2506c41926d2769f7968759995f2505e31c5b5a0821e43ca5a3ddb0e8ae"},
{file = "SQLAlchemy-1.4.44-cp36-cp36m-win_amd64.whl", hash = "sha256:3ca21b35b714ce36f4b8d1ee8d15f149db8eb43a472cf71600bf18dae32286e7"},
{file = "SQLAlchemy-1.4.44-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:3cbdbed8cdcae0f83640a9c44fa02b45a6c61e149c58d45a63c9581aba62850f"},
{file = "SQLAlchemy-1.4.44-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a22208c1982f1fe2ae82e5e4c3d4a6f2445a7a0d65fb7983a3d7cbbe3983f5a4"},
{file = "SQLAlchemy-1.4.44-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d3b9ac11f36ab9a726097fba7c7f6384f0129aedb017f1d4d1d4fce9052a1320"},
{file = "SQLAlchemy-1.4.44-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d654870a66027af3a26df1372cf7f002e161c6768ebe4c9c6fdc0da331cb5173"},
{file = "SQLAlchemy-1.4.44-cp37-cp37m-win32.whl", hash = "sha256:0be9b479c5806cece01f1581726573a8d6515f8404e082c375b922c45cfc2a7b"},
{file = "SQLAlchemy-1.4.44-cp37-cp37m-win_amd64.whl", hash = "sha256:3eba07f740488c3a125f17c092a81eeae24a6c7ec32ac9dbc52bf7afaf0c4f16"},
{file = "SQLAlchemy-1.4.44-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:ad5f966623905ee33694680dda1b735544c99c7638f216045d21546d3d8c6f5b"},
{file = "SQLAlchemy-1.4.44-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f68eab46649504eb95be36ca529aea16cd199f080726c28cbdbcbf23d20b2a2"},
{file = "SQLAlchemy-1.4.44-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:21f3df74a0ab39e1255e94613556e33c1dc3b454059fe0b365ec3bbb9ed82e4a"},
{file = "SQLAlchemy-1.4.44-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8080bc51a775627865e0f1dbfc0040ff4ace685f187f6036837e1727ba2ed10"},
{file = "SQLAlchemy-1.4.44-cp38-cp38-win32.whl", hash = "sha256:b6a337a2643a41476fb6262059b8740f4b9a2ec29bf00ffb18c18c080f6e0aed"},
{file = "SQLAlchemy-1.4.44-cp38-cp38-win_amd64.whl", hash = "sha256:b737fbeb2f78926d1f59964feb287bbbd050e7904766f87c8ce5cfb86e6d840c"},
{file = "SQLAlchemy-1.4.44-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:c9aa372b295a36771cffc226b6517df3011a7d146ac22d19fa6a75f1cdf9d7e6"},
{file = "SQLAlchemy-1.4.44-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:237067ba0ef45a518b64606e1807f7229969ad568288b110ed5f0ca714a3ed3a"},
{file = "SQLAlchemy-1.4.44-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6d7e1b28342b45f19e3dea7873a9479e4a57e15095a575afca902e517fb89652"},
{file = "SQLAlchemy-1.4.44-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94c0093678001f5d79f2dcbf3104c54d6c89e41ab50d619494c503a4d3f1aef2"},
{file = "SQLAlchemy-1.4.44-cp39-cp39-win32.whl", hash = "sha256:7cf7c7adbf4417e3f46fc5a2dbf8395a5a69698217337086888f79700a12e93a"},
{file = "SQLAlchemy-1.4.44-cp39-cp39-win_amd64.whl", hash = "sha256:d3b6d4588994da73567bb00af9d7224a16c8027865a8aab53ae9be83f9b7cbd1"},
{file = "SQLAlchemy-1.4.44.tar.gz", hash = "sha256:2dda5f96719ae89b3ec0f1b79698d86eb9aecb1d54e990abb3fdd92c04b46a90"},
]
tomli = [
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},

View file

@ -1,19 +1,19 @@
[tool.poetry]
name = "advlabdb"
version = "0.7.0"
version = "0.8.0"
description = "Database with a web interface for labs."
authors = ["Mo Bitar <mo8it@proton.me>"]
readme = "README.adoc"
[tool.poetry.dependencies]
# TODO: Use ^ instead of >=
python = "^3.10"
python = "^3.11"
click = ">=8.1.3"
email-validator = ">=1.3.0"
flask = ">=2.2.2"
flask-admin = ">=1.6.0"
flask-login = ">=0.6.2"
flask-migrate = ">=3.1.0"
flask-migrate = ">=4.0.0"
flask-security-Too = ">=5.0.2"
flask-sqlalchemy = ">=3.0.2"
flask-wtf = ">=1.0.1"

View file

@ -1,199 +1,190 @@
alembic==1.8.1 ; python_version >= "3.10" and python_version < "4.0" \
alembic==1.8.1 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:0a024d7f2de88d738d7395ff866997314c837be6104e90c5724350313dee4da4 \
--hash=sha256:cd0b5e45b14b706426b833f06369b9a6d5ee03f826ec3238723ce8caaf6e5ffa
blinker==1.5 ; python_version >= "3.10" and python_version < "4.0" \
blinker==1.5 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:1eb563df6fdbc39eeddc177d953203f99f097e9bf0e2b8f9f3cf18b6ca425e36 \
--hash=sha256:923e5e2f69c155f2cc42dafbbd70e16e3fde24d2d4aa2ab72fbe386238892462
click==8.1.3 ; python_version >= "3.10" and python_version < "4.0" \
click==8.1.3 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e \
--hash=sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48
colorama==0.4.6 ; python_version >= "3.10" and python_version < "4.0" and platform_system == "Windows" \
colorama==0.4.6 ; python_version >= "3.11" and python_version < "4.0" and platform_system == "Windows" \
--hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \
--hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6
contourpy==1.0.5 ; python_version >= "3.10" and python_version < "4.0" \
--hash=sha256:0389349875424aa8c5e61f757e894687916bc4e9616cc6afcbd8051aa2428952 \
--hash=sha256:0395ae71164bfeb2dedd136e03c71a2718a5aa9873a46f518f4133be0d63e1d2 \
--hash=sha256:057114f698ffb9e54657e8fda6802e2f5c8fad609845cf6afaf31590ef6a33c0 \
--hash=sha256:061e1f066c419ffe25b615a1df031b4832ea1d7f2676937e69e8e00e24512005 \
--hash=sha256:06c4d1dde5ee4f909a8a95ba1eb04040c6c26946b4f3b5beaf10d45f14e940ee \
--hash=sha256:09ed9b63f4df8a7591b7a4a26c1ad066dcaafda1f846250fdcb534074a411692 \
--hash=sha256:0f7672148f8fca48e4efc16aba24a7455b40c22d4f8abe42475dec6a12b0bb9a \
--hash=sha256:0f89f0608a5aa8142ed0e53957916623791a88c7f5e5f07ae530c328beeb888f \
--hash=sha256:128bd7acf569f8443ad5b2227f30ac909e4f5399ed221727eeacf0c6476187e6 \
--hash=sha256:19ea64fa0cf389d2ebc10974616acfa1fdecbd73d1fd9c72215b782f3c40f561 \
--hash=sha256:1fb782982c42cee667b892a0b0c52a9f6c7ecf1da5c5f4345845f04eaa862f93 \
--hash=sha256:218722a29c5c26677d37c44f5f8a372daf6f07870aad793a97d47eb6ad6b3290 \
--hash=sha256:2b5e334330d82866923015b455260173cb3b9e3b4e297052d758abd262031289 \
--hash=sha256:2bf5c846c257578b03d498b20f54f53551616a507d8e5463511c58bb58e9a9cf \
--hash=sha256:2d0ad9a85f208473b1f3613c45756c7aa6fcc288266a8c7b873f896aaf741b6b \
--hash=sha256:2f54dcc9bb9390fd0636301ead134d46d5229fe86da0db4d974c0fda349f560e \
--hash=sha256:3109fa601d2a448cec4643abd3a31f972bf05b7c2f2e83df9d3429878f8c10ae \
--hash=sha256:3210d93ad2af742b6a96cf39792f7181822edbb8fe11c3ef29d1583fe637a8d8 \
--hash=sha256:3b3082ade8849130203d461b98c2a061b382c46074b43b4edd5cefd81af92b8a \
--hash=sha256:3c3f2f6b898a40207843ae01970e57e33d22a26b22f23c6a5e07b4716751085f \
--hash=sha256:3ca40d7844b391d90b864c6a6d1bb6b88b09035fb4d866d64d43c4d26fb0ab64 \
--hash=sha256:3cfc067ddde78b76dcbc9684d82688b7d3c5158fa2254a085f9bcb9586c1e2d8 \
--hash=sha256:434942fa2f9019b9ae525fb752dc523800c49a1a28fbd6d9240b0fa959573dcc \
--hash=sha256:46b8e24813e2fb5a3e598c1f8b9ae403e1438cb846a80cc2b33cddf19dddd7f2 \
--hash=sha256:59c827e536bb5e3ef58e06da0faba61fd89a14f30b68bcfeca41f43ca83a1942 \
--hash=sha256:60f37acd4e4227c5a29f737d9a85ca3145c529a8dd4bf70af7f0637c61b49222 \
--hash=sha256:689d7d2a840619915d0abd1ecc6e399fee202f8ad315acda2807f4ca420d0802 \
--hash=sha256:6c02e22cf09996194bcb3a4784099975cf527d5c29caf759abadf29ebdb2fe27 \
--hash=sha256:79908b9d02b1d6c1c71ff3b7ad127f3f82e14a8e091ab44b3c7e34b649fea733 \
--hash=sha256:7c9e99aac7b430f6a9f15eebf058c742097cea3369f23a2bfc5e64d374b67e3a \
--hash=sha256:813c2944e940ef8dccea71305bacc942d4b193a021140874b3e58933ec44f5b6 \
--hash=sha256:87121b9428ac568fb84fae4af5e7852fc34f02eadc4e3e91f6c8989327692186 \
--hash=sha256:896631cd40222aef3697e4e51177d14c3709fda49d30983269d584f034acc8a4 \
--hash=sha256:970a4be7ec84ccda7c27cb4ae74930bbbd477bc8d849ed55ea798084dd5fca8c \
--hash=sha256:9939796abcadb2810a63dfb26ff8ca4595fe7dd70a3ceae7f607a2639b714307 \
--hash=sha256:99a8071e351b50827ad976b92ed91845fb614ac67a3c41109b24f3d8bd3afada \
--hash=sha256:9c16fa267740d67883899e054cccb4279e002f3f4872873b752c1ba15045ff49 \
--hash=sha256:a30e95274f5c0e007ccc759ec258aa5708c534ec058f153ee25ac700a2f1438b \
--hash=sha256:a74afd8d560eaafe0d9e3e1db8c06081282a05ca4de00ee416195085a79d7d3d \
--hash=sha256:b46a04588ceb7cf132568e0e564a854627ef87a1ed3bf536234540a79ced44b0 \
--hash=sha256:b4963cf08f4320d98ae72ec7694291b8ab85cb7da3b0cd824bc32701bc992edf \
--hash=sha256:b50e481a4317a8efcfffcfddcd4c9b36eacba440440e70cbe0256aeb6fd6abae \
--hash=sha256:b85553699862c09937a7a5ea14ee6229087971a7d51ae97d5f4b407f571a2c17 \
--hash=sha256:bcc98d397c3dea45d5b262029564b29cb8e945f2607a38bee6163694c0a8b4ef \
--hash=sha256:bed3a2a823a041e8d249b1a7ec132933e1505299329b5cfe1b2b5ec689ec7675 \
--hash=sha256:bf6b4c0c723664f65c2a47c8cb6ebbf660b0b2e2d936adf2e8503d4e93359465 \
--hash=sha256:bfd634cb9685161b2a51f73a7fc4736fd0d67a56632d52319317afaa27f08243 \
--hash=sha256:c0d5ee865b5fd16bf62d72122aadcc90aab296c30c1adb0a32b4b66bd843163e \
--hash=sha256:c2b4eab7c12f9cb460509bc34a3b086f9802f0dba27c89a63df4123819ad64af \
--hash=sha256:c51568e94f7f232296de30002f2a50f77a7bd346673da3e4f2aaf9d2b833f2e5 \
--hash=sha256:c5158616ab39d34b76c50f40c81552ee180598f7825dc7a66fd187d29958820f \
--hash=sha256:cdacddb18d55ffec42d1907079cdc04ec4fa8a990cdf5b9d9fe67d281fc0d12e \
--hash=sha256:ce763369e646e59e4ca2c09735cd1bdd3048d909ad5f2bc116e83166a9352f3c \
--hash=sha256:d45822b0a2a452327ab4f95efe368d234d5294bbf89a99968be27c7938a21108 \
--hash=sha256:d8150579bf30cdf896906baf256aa200cd50dbe6e565c17d6fd3d678e21ff5de \
--hash=sha256:d88814befbd1433152c5f6dd536905149ba028d795a22555b149ae0a36024d9e \
--hash=sha256:dca5be83a6dfaf933a46e3bc2b9f2685e5ec61b22f6a38ad740aac9c16e9a0ff \
--hash=sha256:dd084459ecdb224e617e4ab3f1d5ebe4d1c48facb41f24952b76aa6ba9712bb0 \
--hash=sha256:def9a01b73c9e27d70ea03b381fb3e7aadfac1f398dbd63751313c3a46747ef5 \
--hash=sha256:df65f4b2b4e74977f0336bef12a88051ab24e6a16873cd9249f34d67cb3e345d \
--hash=sha256:dfe924e5a63861c82332a12adeeab955dc8c8009ddbbd80cc2fcca049ff89a49 \
--hash=sha256:e67dcaa34dcd908fcccbf49194211d847c731b6ebaac661c1c889f1bf6af1e44 \
--hash=sha256:eba62b7c21a33e72dd8adab2b92dd5610d8527f0b2ac28a8e0770e71b21a13f9 \
--hash=sha256:ed9c91bf4ce614efed5388c3f989a7cfe08728ab871d995a486ea74ff88993db \
--hash=sha256:f05d311c937da03b0cd26ac3e14cb991f6ff8fc94f98b3df9713537817539795 \
--hash=sha256:f1cc623fd6855b25da52b3275e0c9e51711b86a9dccc75f8c9ab4432fd8e42c7 \
--hash=sha256:f670686d99c867d0f24b28ce8c6f02429c6eef5e2674aab287850d0ee2d20437 \
--hash=sha256:f856652f9b533c6cd2b9ad6836a7fc0e43917d7ff15be46c5baf1350f8cdc5d9 \
--hash=sha256:fb0458d74726937ead9e2effc91144aea5a58ecee9754242f8539a782bed685a
cycler==0.11.0 ; python_version >= "3.10" and python_version < "4.0" \
contourpy==1.0.6 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:0236875c5a0784215b49d00ebbe80c5b6b5d5244b3655a36dda88105334dea17 \
--hash=sha256:03d1b9c6b44a9e30d554654c72be89af94fab7510b4b9f62356c64c81cec8b7d \
--hash=sha256:0537cc1195245bbe24f2913d1f9211b8f04eb203de9044630abd3664c6cc339c \
--hash=sha256:06ca79e1efbbe2df795822df2fa173d1a2b38b6e0f047a0ec7903fbca1d1847e \
--hash=sha256:08e8d09d96219ace6cb596506fb9b64ea5f270b2fb9121158b976d88871fcfd1 \
--hash=sha256:0b1e66346acfb17694d46175a0cea7d9036f12ed0c31dfe86f0f405eedde2bdd \
--hash=sha256:0b97454ed5b1368b66ed414c754cba15b9750ce69938fc6153679787402e4cdf \
--hash=sha256:0e4854cc02006ad6684ce092bdadab6f0912d131f91c2450ce6dbdea78ee3c0b \
--hash=sha256:12a7dc8439544ed05c6553bf026d5e8fa7fad48d63958a95d61698df0e00092b \
--hash=sha256:1b1ee48a130da4dd0eb8055bbab34abf3f6262957832fd575e0cab4979a15a41 \
--hash=sha256:1c0e1308307a75e07d1f1b5f0f56b5af84538a5e9027109a7bcf6cb47c434e72 \
--hash=sha256:1dedf4c64185a216c35eb488e6f433297c660321275734401760dafaeb0ad5c2 \
--hash=sha256:208bc904889c910d95aafcf7be9e677726df9ef71e216780170dbb7e37d118fa \
--hash=sha256:211dfe2bd43bf5791d23afbe23a7952e8ac8b67591d24be3638cabb648b3a6eb \
--hash=sha256:341330ed19074f956cb20877ad8d2ae50e458884bfa6a6df3ae28487cc76c768 \
--hash=sha256:344cb3badf6fc7316ad51835f56ac387bdf86c8e1b670904f18f437d70da4183 \
--hash=sha256:358f6364e4873f4d73360b35da30066f40387dd3c427a3e5432c6b28dd24a8fa \
--hash=sha256:371f6570a81dfdddbb837ba432293a63b4babb942a9eb7aaa699997adfb53278 \
--hash=sha256:375d81366afd547b8558c4720337218345148bc2fcffa3a9870cab82b29667f2 \
--hash=sha256:3a1917d3941dd58732c449c810fa7ce46cc305ce9325a11261d740118b85e6f3 \
--hash=sha256:4081918147fc4c29fad328d5066cfc751da100a1098398742f9f364be63803fc \
--hash=sha256:444fb776f58f4906d8d354eb6f6ce59d0a60f7b6a720da6c1ccb839db7c80eb9 \
--hash=sha256:46deb310a276cc5c1fd27958e358cce68b1e8a515fa5a574c670a504c3a3fe30 \
--hash=sha256:494efed2c761f0f37262815f9e3c4bb9917c5c69806abdee1d1cb6611a7174a0 \
--hash=sha256:50627bf76abb6ba291ad08db583161939c2c5fab38c38181b7833423ab9c7de3 \
--hash=sha256:5641927cc5ae66155d0c80195dc35726eae060e7defc18b7ab27600f39dd1fe7 \
--hash=sha256:5b117d29433fc8393b18a696d794961464e37afb34a6eeb8b2c37b5f4128a83e \
--hash=sha256:613c665529899b5d9fade7e5d1760111a0b011231277a0d36c49f0d3d6914bd6 \
--hash=sha256:6e459ebb8bb5ee4c22c19cc000174f8059981971a33ce11e17dddf6aca97a142 \
--hash=sha256:6f56515e7c6fae4529b731f6c117752247bef9cdad2b12fc5ddf8ca6a50965a5 \
--hash=sha256:730c27978a0003b47b359935478b7d63fd8386dbb2dcd36c1e8de88cbfc1e9de \
--hash=sha256:75a2e638042118118ab39d337da4c7908c1af74a8464cad59f19fbc5bbafec9b \
--hash=sha256:78ced51807ccb2f45d4ea73aca339756d75d021069604c2fccd05390dc3c28eb \
--hash=sha256:7ee394502026d68652c2824348a40bf50f31351a668977b51437131a90d777ea \
--hash=sha256:8468b40528fa1e15181cccec4198623b55dcd58306f8815a793803f51f6c474a \
--hash=sha256:84c593aeff7a0171f639da92cb86d24954bbb61f8a1b530f74eb750a14685832 \
--hash=sha256:913bac9d064cff033cf3719e855d4f1db9f1c179e0ecf3ba9fdef21c21c6a16a \
--hash=sha256:9447c45df407d3ecb717d837af3b70cfef432138530712263730783b3d016512 \
--hash=sha256:9b0e7fe7f949fb719b206548e5cde2518ffb29936afa4303d8a1c4db43dcb675 \
--hash=sha256:9bc407a6af672da20da74823443707e38ece8b93a04009dca25856c2d9adadb1 \
--hash=sha256:9e8e686a6db92a46111a1ee0ee6f7fbfae4048f0019de207149f43ac1812cf95 \
--hash=sha256:9fc4e7973ed0e1fe689435842a6e6b330eb7ccc696080dda9a97b1a1b78e41db \
--hash=sha256:a457ee72d9032e86730f62c5eeddf402e732fdf5ca8b13b41772aa8ae13a4563 \
--hash=sha256:a628bba09ba72e472bf7b31018b6281fd4cc903f0888049a3724afba13b6e0b8 \
--hash=sha256:a79d239fc22c3b8d9d3de492aa0c245533f4f4c7608e5749af866949c0f1b1b9 \
--hash=sha256:aa4674cf3fa2bd9c322982644967f01eed0c91bb890f624e0e0daf7a5c3383e9 \
--hash=sha256:acd2bd02f1a7adff3a1f33e431eb96ab6d7987b039d2946a9b39fe6fb16a1036 \
--hash=sha256:b3b1bd7577c530eaf9d2bc52d1a93fef50ac516a8b1062c3d1b9bcec9ebe329b \
--hash=sha256:b48d94386f1994db7c70c76b5808c12e23ed7a4ee13693c2fc5ab109d60243c0 \
--hash=sha256:b64f747e92af7da3b85631a55d68c45a2d728b4036b03cdaba4bd94bcc85bd6f \
--hash=sha256:b98c820608e2dca6442e786817f646d11057c09a23b68d2b3737e6dcb6e4a49b \
--hash=sha256:c1baa49ab9fedbf19d40d93163b7d3e735d9cd8d5efe4cce9907902a6dad391f \
--hash=sha256:c38c6536c2d71ca2f7e418acaf5bca30a3af7f2a2fa106083c7d738337848dbe \
--hash=sha256:c78bfbc1a7bff053baf7e508449d2765964d67735c909b583204e3240a2aca45 \
--hash=sha256:cd2bc0c8f2e8de7dd89a7f1c10b8844e291bca17d359373203ef2e6100819edd \
--hash=sha256:d2eff2af97ea0b61381828b1ad6cd249bbd41d280e53aea5cccd7b2b31b8225c \
--hash=sha256:d8834c14b8c3dd849005e06703469db9bf96ba2d66a3f88ecc539c9a8982e0ee \
--hash=sha256:d912f0154a20a80ea449daada904a7eb6941c83281a9fab95de50529bfc3a1da \
--hash=sha256:da1ef35fd79be2926ba80fbb36327463e3656c02526e9b5b4c2b366588b74d9a \
--hash=sha256:dbe6fe7a1166b1ddd7b6d887ea6fa8389d3f28b5ed3f73a8f40ece1fc5a3d340 \
--hash=sha256:dcd556c8fc37a342dd636d7eef150b1399f823a4462f8c968e11e1ebeabee769 \
--hash=sha256:e13b31d1b4b68db60b3b29f8e337908f328c7f05b9add4b1b5c74e0691180109 \
--hash=sha256:e1739496c2f0108013629aa095cc32a8c6363444361960c07493818d0dea2da4 \
--hash=sha256:e43255a83835a129ef98f75d13d643844d8c646b258bebd11e4a0975203e018f \
--hash=sha256:e626cefff8491bce356221c22af5a3ea528b0b41fbabc719c00ae233819ea0bf \
--hash=sha256:eadad75bf91897f922e0fb3dca1b322a58b1726a953f98c2e5f0606bd8408621 \
--hash=sha256:f33da6b5d19ad1bb5e7ad38bb8ba5c426d2178928bc2b2c44e8823ea0ecb6ff3 \
--hash=sha256:f4052a8a4926d4468416fc7d4b2a7b2a3e35f25b39f4061a7e2a3a2748c4fc48 \
--hash=sha256:f6ca38dd8d988eca8f07305125dec6f54ac1c518f1aaddcc14d08c01aebb6efc
cycler==0.11.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:3a27e95f763a428a739d2add979fa7494c912a32c17c4c38c4d5f082cad165a3 \
--hash=sha256:9c87405839a19696e837b3b818fed3f5f69f16f1eec1a1ad77e043dcea9c772f
dnspython==2.2.1 ; python_version >= "3.10" and python_version < "4.0" \
dnspython==2.2.1 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:0f7569a4a6ff151958b64304071d370daa3243d15941a7beedf0c9fe5105603e \
--hash=sha256:a851e51367fb93e9e1361732c1d60dab63eff98712e503ea7d92e6eccb109b4f
email-validator==1.3.0 ; python_version >= "3.10" and python_version < "4.0" \
email-validator==1.3.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:553a66f8be2ec2dea641ae1d3f29017ab89e9d603d4a25cdaac39eefa283d769 \
--hash=sha256:816073f2a7cffef786b29928f58ec16cdac42710a53bb18aa94317e3e145ec5c
flask-admin==1.6.0 ; python_version >= "3.10" and python_version < "4.0" \
flask-admin==1.6.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:424ffc79b7b0dfff051555686ea12e86e48dffacac14beaa319fb4502ac40988
flask-login==0.6.2 ; python_version >= "3.10" and python_version < "4.0" \
flask-login==0.6.2 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:1ef79843f5eddd0f143c2cd994c1b05ac83c0401dc6234c143495af9a939613f \
--hash=sha256:c0a7baa9fdc448cdd3dd6f0939df72eec5177b2f7abe6cb82fc934d29caac9c3
flask-migrate==3.1.0 ; python_version >= "3.10" and python_version < "4.0" \
--hash=sha256:57d6060839e3a7f150eaab6fe4e726d9e3e7cffe2150fb223d73f92421c6d1d9 \
--hash=sha256:a6498706241aba6be7a251078de9cf166d74307bca41a4ca3e403c9d39e2f897
flask-principal==0.4.0 ; python_version >= "3.10" and python_version < "4.0" \
flask-migrate==4.0.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:2a301c3040af6844f29d9149abe428a0f08ebc8fa149e72113bbb36fa341920a \
--hash=sha256:e75a46b657e3062296b9f6e92f31e19662f76cfee8abd6ae94640cbcb79fe016
flask-principal==0.4.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:f5d6134b5caebfdbb86f32d56d18ee44b080876a27269560a96ea35f75c99453
flask-security-too==5.0.2 ; python_version >= "3.10" and python_version < "4.0" \
flask-security-too==5.0.2 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:36fee0da5d1b3d211caf274553b7753478c208997c624abb84ebba4261de65c2 \
--hash=sha256:5f81e220c63f8f319bcd04327267328fd4b58ca05aa6f3ffc458756dfa78d579
flask-sqlalchemy==3.0.2 ; python_version >= "3.10" and python_version < "4.0" \
flask-sqlalchemy==3.0.2 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:16199f5b3ddfb69e0df2f52ae4c76aedbfec823462349dabb21a1b2e0a2b65e9 \
--hash=sha256:7d0cd9cf73e64a996bb881a1ebd01633fc5a6d11c36ea27f7b5e251dc45476e7
flask-wtf==1.0.1 ; python_version >= "3.10" and python_version < "4.0" \
flask-wtf==1.0.1 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:34fe5c6fee0f69b50e30f81a3b7ea16aa1492a771fe9ad0974d164610c09a6c9 \
--hash=sha256:9d733658c80be551ce7d5bc13c7a7ac0d80df509be1e23827c847d9520f4359a
flask==2.2.2 ; python_version >= "3.10" and python_version < "4.0" \
flask==2.2.2 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:642c450d19c4ad482f96729bd2a8f6d32554aa1e231f4f6b4e7e5264b16cca2b \
--hash=sha256:b9c46cc36662a7949f34b52d8ec7bb59c0d74ba08ba6cb9ce9adc1d8676d9526
fonttools==4.38.0 ; python_version >= "3.10" and python_version < "4.0" \
fonttools==4.38.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:2bb244009f9bf3fa100fc3ead6aeb99febe5985fa20afbfbaa2f8946c2fbdaf1 \
--hash=sha256:820466f43c8be8c3009aef8b87e785014133508f0de64ec469e4efb643ae54fb
greenlet==1.1.3.post0 ; python_version >= "3.10" and (platform_machine == "aarch64" or platform_machine == "ppc64le" or platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "win32" or platform_machine == "WIN32") and python_version < "4.0" \
--hash=sha256:0120a879aa2b1ac5118bce959ea2492ba18783f65ea15821680a256dfad04754 \
--hash=sha256:025b8de2273d2809f027d347aa2541651d2e15d593bbce0d5f502ca438c54136 \
--hash=sha256:05ae7383f968bba4211b1fbfc90158f8e3da86804878442b4fb6c16ccbcaa519 \
--hash=sha256:0914f02fcaa8f84f13b2df4a81645d9e82de21ed95633765dd5cc4d3af9d7403 \
--hash=sha256:0971d37ae0eaf42344e8610d340aa0ad3d06cd2eee381891a10fe771879791f9 \
--hash=sha256:0a954002064ee919b444b19c1185e8cce307a1f20600f47d6f4b6d336972c809 \
--hash=sha256:0aa1845944e62f358d63fcc911ad3b415f585612946b8edc824825929b40e59e \
--hash=sha256:104f29dd822be678ef6b16bf0035dcd43206a8a48668a6cae4d2fe9c7a7abdeb \
--hash=sha256:11fc7692d95cc7a6a8447bb160d98671ab291e0a8ea90572d582d57361360f05 \
--hash=sha256:17a69967561269b691747e7f436d75a4def47e5efcbc3c573180fc828e176d80 \
--hash=sha256:2794eef1b04b5ba8948c72cc606aab62ac4b0c538b14806d9c0d88afd0576d6b \
--hash=sha256:2c6e942ca9835c0b97814d14f78da453241837419e0d26f7403058e8db3e38f8 \
--hash=sha256:2ccdc818cc106cc238ff7eba0d71b9c77be868fdca31d6c3b1347a54c9b187b2 \
--hash=sha256:325f272eb997916b4a3fc1fea7313a8adb760934c2140ce13a2117e1b0a8095d \
--hash=sha256:39464518a2abe9c505a727af7c0b4efff2cf242aa168be5f0daa47649f4d7ca8 \
--hash=sha256:3a24f3213579dc8459e485e333330a921f579543a5214dbc935bc0763474ece3 \
--hash=sha256:3aeac044c324c1a4027dca0cde550bd83a0c0fbff7ef2c98df9e718a5086c194 \
--hash=sha256:3c22998bfef3fcc1b15694818fc9b1b87c6cc8398198b96b6d355a7bcb8c934e \
--hash=sha256:467b73ce5dcd89e381292fb4314aede9b12906c18fab903f995b86034d96d5c8 \
--hash=sha256:4a8b58232f5b72973350c2b917ea3df0bebd07c3c82a0a0e34775fc2c1f857e9 \
--hash=sha256:4f74aa0092602da2069df0bc6553919a15169d77bcdab52a21f8c5242898f519 \
--hash=sha256:5662492df0588a51d5690f6578f3bbbd803e7f8d99a99f3bf6128a401be9c269 \
--hash=sha256:5c2d21c2b768d8c86ad935e404cc78c30d53dea009609c3ef3a9d49970c864b5 \
--hash=sha256:5edf75e7fcfa9725064ae0d8407c849456553a181ebefedb7606bac19aa1478b \
--hash=sha256:60839ab4ea7de6139a3be35b77e22e0398c270020050458b3d25db4c7c394df5 \
--hash=sha256:62723e7eb85fa52e536e516ee2ac91433c7bb60d51099293671815ff49ed1c21 \
--hash=sha256:64e10f303ea354500c927da5b59c3802196a07468332d292aef9ddaca08d03dd \
--hash=sha256:66aa4e9a726b70bcbfcc446b7ba89c8cec40f405e51422c39f42dfa206a96a05 \
--hash=sha256:695d0d8b5ae42c800f1763c9fce9d7b94ae3b878919379150ee5ba458a460d57 \
--hash=sha256:70048d7b2c07c5eadf8393e6398595591df5f59a2f26abc2f81abca09610492f \
--hash=sha256:7afa706510ab079fd6d039cc6e369d4535a48e202d042c32e2097f030a16450f \
--hash=sha256:7cf37343e43404699d58808e51f347f57efd3010cc7cee134cdb9141bd1ad9ea \
--hash=sha256:8149a6865b14c33be7ae760bcdb73548bb01e8e47ae15e013bf7ef9290ca309a \
--hash=sha256:814f26b864ed2230d3a7efe0336f5766ad012f94aad6ba43a7c54ca88dd77cba \
--hash=sha256:82a38d7d2077128a017094aff334e67e26194f46bd709f9dcdacbf3835d47ef5 \
--hash=sha256:83a7a6560df073ec9de2b7cb685b199dfd12519bc0020c62db9d1bb522f989fa \
--hash=sha256:8415239c68b2ec9de10a5adf1130ee9cb0ebd3e19573c55ba160ff0ca809e012 \
--hash=sha256:88720794390002b0c8fa29e9602b395093a9a766b229a847e8d88349e418b28a \
--hash=sha256:890f633dc8cb307761ec566bc0b4e350a93ddd77dc172839be122be12bae3e10 \
--hash=sha256:8926a78192b8b73c936f3e87929931455a6a6c6c385448a07b9f7d1072c19ff3 \
--hash=sha256:8c0581077cf2734569f3e500fab09c0ff6a2ab99b1afcacbad09b3c2843ae743 \
--hash=sha256:8fda1139d87ce5f7bd80e80e54f9f2c6fe2f47983f1a6f128c47bf310197deb6 \
--hash=sha256:91a84faf718e6f8b888ca63d0b2d6d185c8e2a198d2a7322d75c303e7097c8b7 \
--hash=sha256:924df1e7e5db27d19b1359dc7d052a917529c95ba5b8b62f4af611176da7c8ad \
--hash=sha256:949c9061b8c6d3e6e439466a9be1e787208dec6246f4ec5fffe9677b4c19fcc3 \
--hash=sha256:9649891ab4153f217f319914455ccf0b86986b55fc0573ce803eb998ad7d6854 \
--hash=sha256:96656c5f7c95fc02c36d4f6ef32f4e94bb0b6b36e6a002c21c39785a4eec5f5d \
--hash=sha256:a812df7282a8fc717eafd487fccc5ba40ea83bb5b13eb3c90c446d88dbdfd2be \
--hash=sha256:a8d24eb5cb67996fb84633fdc96dbc04f2d8b12bfcb20ab3222d6be271616b67 \
--hash=sha256:bef49c07fcb411c942da6ee7d7ea37430f830c482bf6e4b72d92fd506dd3a427 \
--hash=sha256:bffba15cff4802ff493d6edcf20d7f94ab1c2aee7cfc1e1c7627c05f1102eee8 \
--hash=sha256:c0643250dd0756f4960633f5359884f609a234d4066686754e834073d84e9b51 \
--hash=sha256:c6f90234e4438062d6d09f7d667f79edcc7c5e354ba3a145ff98176f974b8132 \
--hash=sha256:c8c9301e3274276d3d20ab6335aa7c5d9e5da2009cccb01127bddb5c951f8870 \
--hash=sha256:c8ece5d1a99a2adcb38f69af2f07d96fb615415d32820108cd340361f590d128 \
--hash=sha256:cb863057bed786f6622982fb8b2c122c68e6e9eddccaa9fa98fd937e45ee6c4f \
--hash=sha256:ccbe7129a282ec5797df0451ca1802f11578be018a32979131065565da89b392 \
--hash=sha256:d25cdedd72aa2271b984af54294e9527306966ec18963fd032cc851a725ddc1b \
--hash=sha256:d75afcbb214d429dacdf75e03a1d6d6c5bd1fa9c35e360df8ea5b6270fb2211c \
--hash=sha256:d7815e1519a8361c5ea2a7a5864945906f8e386fa1bc26797b4d443ab11a4589 \
--hash=sha256:eb6ac495dccb1520667cfea50d89e26f9ffb49fa28496dea2b95720d8b45eb54 \
--hash=sha256:ec615d2912b9ad807afd3be80bf32711c0ff9c2b00aa004a45fd5d5dde7853d9 \
--hash=sha256:f5e09dc5c6e1796969fd4b775ea1417d70e49a5df29aaa8e5d10675d9e11872c \
--hash=sha256:f6661b58412879a2aa099abb26d3c93e91dedaba55a6394d1fb1512a77e85de9 \
--hash=sha256:f7d20c3267385236b4ce54575cc8e9f43e7673fc761b069c820097092e318e3b \
--hash=sha256:fe7c51f8a2ab616cb34bc33d810c887e89117771028e1e3d3b77ca25ddeace04
gunicorn==20.1.0 ; python_version >= "3.10" and python_version < "4.0" \
greenlet==2.0.1 ; python_version >= "3.11" and (platform_machine == "aarch64" or platform_machine == "ppc64le" or platform_machine == "x86_64" or platform_machine == "amd64" or platform_machine == "AMD64" or platform_machine == "win32" or platform_machine == "WIN32") and python_version < "4.0" \
--hash=sha256:0109af1138afbfb8ae647e31a2b1ab030f58b21dd8528c27beaeb0093b7938a9 \
--hash=sha256:04957dc96669be041e0c260964cfef4c77287f07c40452e61abe19d647505581 \
--hash=sha256:0722c9be0797f544a3ed212569ca3fe3d9d1a1b13942d10dd6f0e8601e484d26 \
--hash=sha256:097e3dae69321e9100202fc62977f687454cd0ea147d0fd5a766e57450c569fd \
--hash=sha256:0b493db84d124805865adc587532ebad30efa68f79ad68f11b336e0a51ec86c2 \
--hash=sha256:13ba6e8e326e2116c954074c994da14954982ba2795aebb881c07ac5d093a58a \
--hash=sha256:13ebf93c343dd8bd010cd98e617cb4c1c1f352a0cf2524c82d3814154116aa82 \
--hash=sha256:1407fe45246632d0ffb7a3f4a520ba4e6051fc2cbd61ba1f806900c27f47706a \
--hash=sha256:1bf633a50cc93ed17e494015897361010fc08700d92676c87931d3ea464123ce \
--hash=sha256:2d0bac0385d2b43a7bd1d651621a4e0f1380abc63d6fb1012213a401cbd5bf8f \
--hash=sha256:3001d00eba6bbf084ae60ec7f4bb8ed375748f53aeaefaf2a37d9f0370558524 \
--hash=sha256:356e4519d4dfa766d50ecc498544b44c0249b6de66426041d7f8b751de4d6b48 \
--hash=sha256:38255a3f1e8942573b067510f9611fc9e38196077b0c8eb7a8c795e105f9ce77 \
--hash=sha256:3d75b8d013086b08e801fbbb896f7d5c9e6ccd44f13a9241d2bf7c0df9eda928 \
--hash=sha256:41b825d65f31e394b523c84db84f9383a2f7eefc13d987f308f4663794d2687e \
--hash=sha256:42e602564460da0e8ee67cb6d7236363ee5e131aa15943b6670e44e5c2ed0f67 \
--hash=sha256:4aeaebcd91d9fee9aa768c1b39cb12214b30bf36d2b7370505a9f2165fedd8d9 \
--hash=sha256:4c8b1c43e75c42a6cafcc71defa9e01ead39ae80bd733a2608b297412beede68 \
--hash=sha256:4d37990425b4687ade27810e3b1a1c37825d242ebc275066cfee8cb6b8829ccd \
--hash=sha256:4f09b0010e55bec3239278f642a8a506b91034f03a4fb28289a7d448a67f1515 \
--hash=sha256:505138d4fa69462447a562a7c2ef723c6025ba12ac04478bc1ce2fcc279a2db5 \
--hash=sha256:5067920de254f1a2dee8d3d9d7e4e03718e8fd2d2d9db962c8c9fa781ae82a39 \
--hash=sha256:56961cfca7da2fdd178f95ca407fa330c64f33289e1804b592a77d5593d9bd94 \
--hash=sha256:5a8e05057fab2a365c81abc696cb753da7549d20266e8511eb6c9d9f72fe3e92 \
--hash=sha256:659f167f419a4609bc0516fb18ea69ed39dbb25594934bd2dd4d0401660e8a1e \
--hash=sha256:6f61d71bbc9b4a3de768371b210d906726535d6ca43506737682caa754b956cd \
--hash=sha256:72b00a8e7c25dcea5946692a2485b1a0c0661ed93ecfedfa9b6687bd89a24ef5 \
--hash=sha256:811e1d37d60b47cb8126e0a929b58c046251f28117cb16fcd371eed61f66b764 \
--hash=sha256:81b0ea3715bf6a848d6f7149d25bf018fd24554a4be01fcbbe3fdc78e890b955 \
--hash=sha256:88c8d517e78acdf7df8a2134a3c4b964415b575d2840a2746ddb1cc6175f8608 \
--hash=sha256:8dca09dedf1bd8684767bc736cc20c97c29bc0c04c413e3276e0962cd7aeb148 \
--hash=sha256:974a39bdb8c90a85982cdb78a103a32e0b1be986d411303064b28a80611f6e51 \
--hash=sha256:9e112e03d37987d7b90c1e98ba5e1b59e1645226d78d73282f45b326f7bddcb9 \
--hash=sha256:9e9744c657d896c7b580455e739899e492a4a452e2dd4d2b3e459f6b244a638d \
--hash=sha256:9ed358312e63bf683b9ef22c8e442ef6c5c02973f0c2a939ec1d7b50c974015c \
--hash=sha256:9f2c221eecb7ead00b8e3ddb913c67f75cba078fd1d326053225a3f59d850d72 \
--hash=sha256:a20d33124935d27b80e6fdacbd34205732660e0a1d35d8b10b3328179a2b51a1 \
--hash=sha256:a4c0757db9bd08470ff8277791795e70d0bf035a011a528ee9a5ce9454b6cba2 \
--hash=sha256:afe07421c969e259e9403c3bb658968702bc3b78ec0b6fde3ae1e73440529c23 \
--hash=sha256:b1992ba9d4780d9af9726bbcef6a1db12d9ab1ccc35e5773685a24b7fb2758eb \
--hash=sha256:b23d2a46d53210b498e5b701a1913697671988f4bf8e10f935433f6e7c332fb6 \
--hash=sha256:b5e83e4de81dcc9425598d9469a624826a0b1211380ac444c7c791d4a2137c19 \
--hash=sha256:be35822f35f99dcc48152c9839d0171a06186f2d71ef76dc57fa556cc9bf6b45 \
--hash=sha256:be9e0fb2ada7e5124f5282d6381903183ecc73ea019568d6d63d33f25b2a9000 \
--hash=sha256:c140e7eb5ce47249668056edf3b7e9900c6a2e22fb0eaf0513f18a1b2c14e1da \
--hash=sha256:c6a08799e9e88052221adca55741bf106ec7ea0710bca635c208b751f0d5b617 \
--hash=sha256:cb242fc2cda5a307a7698c93173d3627a2a90d00507bccf5bc228851e8304963 \
--hash=sha256:cce1e90dd302f45716a7715517c6aa0468af0bf38e814ad4eab58e88fc09f7f7 \
--hash=sha256:cd4ccc364cf75d1422e66e247e52a93da6a9b73cefa8cad696f3cbbb75af179d \
--hash=sha256:d21681f09e297a5adaa73060737e3aa1279a13ecdcfcc6ef66c292cb25125b2d \
--hash=sha256:d566b82e92ff2e09dd6342df7e0eb4ff6275a3f08db284888dcd98134dbd4243 \
--hash=sha256:d5b0ff9878333823226d270417f24f4d06f235cb3e54d1103b71ea537a6a86ce \
--hash=sha256:d6ee1aa7ab36475035eb48c01efae87d37936a8173fc4d7b10bb02c2d75dd8f6 \
--hash=sha256:db38f80540083ea33bdab614a9d28bcec4b54daa5aff1668d7827a9fc769ae0a \
--hash=sha256:ea688d11707d30e212e0110a1aac7f7f3f542a259235d396f88be68b649e47d1 \
--hash=sha256:f6327b6907b4cb72f650a5b7b1be23a2aab395017aa6f1adb13069d66360eb3f \
--hash=sha256:fb412b7db83fe56847df9c47b6fe3f13911b06339c2aa02dcc09dce8bbf582cd
gunicorn==20.1.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e \
--hash=sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8
idna==3.4 ; python_version >= "3.10" and python_version < "4.0" \
idna==3.4 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \
--hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2
itsdangerous==2.1.2 ; python_version >= "3.10" and python_version < "4.0" \
itsdangerous==2.1.2 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44 \
--hash=sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a
jinja2==3.1.2 ; python_version >= "3.10" and python_version < "4.0" \
jinja2==3.1.2 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \
--hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61
kiwisolver==1.4.4 ; python_version >= "3.10" and python_version < "4.0" \
kiwisolver==1.4.4 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:02f79693ec433cb4b5f51694e8477ae83b3205768a6fb48ffba60549080e295b \
--hash=sha256:03baab2d6b4a54ddbb43bba1a3a2d1627e82d205c5cf8f4c924dc49284b87166 \
--hash=sha256:1041feb4cda8708ce73bb4dcb9ce1ccf49d553bf87c3954bdfa46f0c3f77252c \
@ -262,10 +253,10 @@ kiwisolver==1.4.4 ; python_version >= "3.10" and python_version < "4.0" \
--hash=sha256:f6cb459eea32a4e2cf18ba5fcece2dbdf496384413bc1bae15583f19e567f3b2 \
--hash=sha256:f8ad8285b01b0d4695102546b342b493b3ccc6781fc28c8c6a1bb63e95d22f09 \
--hash=sha256:f9f39e2f049db33a908319cf46624a569b36983c7c78318e9726a4cb8923b26c
mako==1.2.3 ; python_version >= "3.10" and python_version < "4.0" \
--hash=sha256:7fde96466fcfeedb0eed94f187f20b23d85e4cb41444be0e542e2c8c65c396cd \
--hash=sha256:c413a086e38cd885088d5e165305ee8eed04e8b3f8f62df343480da0a385735f
markupsafe==2.1.1 ; python_version >= "3.10" and python_version < "4.0" \
mako==1.2.4 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:c97c79c018b9165ac9922ae4f32da095ffd3c4e6872b45eded42926deea46818 \
--hash=sha256:d60a3903dc3bb01a18ad6a89cdbe2e4eadc69c0bc8ef1e3773ba53d44c3f7a34
markupsafe==2.1.1 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003 \
--hash=sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88 \
--hash=sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5 \
@ -306,49 +297,49 @@ markupsafe==2.1.1 ; python_version >= "3.10" and python_version < "4.0" \
--hash=sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933 \
--hash=sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a \
--hash=sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7
matplotlib==3.6.1 ; python_version >= "3.10" and python_version < "4.0" \
--hash=sha256:02561141c434154f7bae8e5449909d152367cb40aa57bfb2a27f2748b9c5f95f \
--hash=sha256:05e86446562063d6186ff6d700118c0dbd5dccc403a6187351ee526c48878f10 \
--hash=sha256:0bab7564aafd5902128d54b68dca04f5755413fb6b502100bb0235a545882c48 \
--hash=sha256:12ab21d0cad122f5b23688d453a0280676e7c42f634f0dbd093d15d42d142b1f \
--hash=sha256:183bf3ac6a6023ee590aa4b677f391ceed65ec0d6b930901a8483c267bd12995 \
--hash=sha256:1e2c75d5d1ff6b7ef9870360bfa23bea076b8dc0945a60d19453d7619ed9ea8f \
--hash=sha256:220314c2d6b9ca11570d7cd4b841c9f3137546f188336003b9fb8def4dcb804d \
--hash=sha256:2469f57e4c5cc0e85eddc7b30995ea9c404a78c0b1856da75d1a5887156ca350 \
--hash=sha256:27337bcb38d5db7430c14f350924542d75416ec1546d5d9d9f39b362b71db3fb \
--hash=sha256:2cc5d726d4d42865f909c5208a7841109d76584950dd0587b01a77cc279d4ab7 \
--hash=sha256:3c53486278a0629fd892783271dc994b962fba8dfe207445d039e14f1928ea46 \
--hash=sha256:4648f0d79a87bf50ee740058305c91091ee5e1fbb71a7d2f5fe6707bfe328d1c \
--hash=sha256:47cb088bbce82ae9fc2edf3c25e56a5c6142ce2553fea2b781679f960a70c207 \
--hash=sha256:4a3d903588b519b38ed085d0ae762a1dcd4b70164617292175cfd91b90d6c415 \
--hash=sha256:4d3b0e0a4611bd22065bbf47e9b2f689ac9e575bcb850a9f0ae2bbed75cab956 \
--hash=sha256:52935b7d4ccbf0dbc9cf454dbb10ca99c11cbe8da9467596b96e5e21fd4dfc5c \
--hash=sha256:563896ba269324872ace436a57775dcc8322678a9496b28a8c25cdafa5ec2b92 \
--hash=sha256:565f514dec81a41cbed10eb6011501879695087fc2787fb89423a466508abbbd \
--hash=sha256:5f97141e05baf160c3ec125f06ceb2a44c9bb62f42fcb8ee1c05313c73e99432 \
--hash=sha256:6f5788168da2661b42f7468063b725cc73fdbeeb80f2704cb2d8c415e9a57c50 \
--hash=sha256:71eced071825005011cdc64efbae2e2c76b8209c18aa487dedf69796fe4b1e40 \
--hash=sha256:7730e60e751cfcfe7fcb223cf03c0b979e9a064c239783ad37929d340a364cef \
--hash=sha256:8245e85fd793f58edf29b8a9e3be47e8ecf76ea1a1e8240545f2746181ca5787 \
--hash=sha256:85948b303534b69fd771126764cf883fde2af9b003eb5778cb60f3b46f93d3f6 \
--hash=sha256:87027ff7b2edeb14476900261ef04d4beae949e1dfa0a3eb3ad6a6efbf9d0e1d \
--hash=sha256:87bdbd37d0a41e025879863fe9b17bab15c0421313bc33e77e5e1aa54215c9c5 \
--hash=sha256:8dc25473319afabe49150267e54648ac559c33b0fc2a80c8caecfbbc2948a820 \
--hash=sha256:8ddd58324dc9a77e2e56d7b7aea7dbd0575b6f7cd1333c3ca9d388ac70978344 \
--hash=sha256:9403764017d20ff570f7ce973a8b9637f08a6109118f4e0ce6c7493d8849a0d3 \
--hash=sha256:9dd40505ccc526acaf9a5db1b3029e237c64b58f1249983b28a291c2d6a1d0fa \
--hash=sha256:a4de03085afb3b80fab341afaf8e60dfe06ce439b6dfed55d657cf34a7bc3c40 \
--hash=sha256:a68b91ac7e6bb26100a540a033f54c95fe06d9c0aa51312c2a52d07d1bde78f4 \
--hash=sha256:b53387d4e59432ff221540a4ffb5ee9669c69417805e4faf0148a00d701c61f9 \
--hash=sha256:c1effccef0cea2d4da9feeed22079adf6786f92c800a7d0d2ef2104318a1c66c \
--hash=sha256:c9756a8e69f6e1f76d47eb42132175b6814da1fbeae0545304c6d0fc2aae252a \
--hash=sha256:d0161ebf87518ecfe0980c942d5f0d5df0e080c1746ebaab2027a969967014b7 \
--hash=sha256:e2d1b7225666f7e1bcc94c0bc9c587a82e3e8691da4757e357e5c2515222ee37 \
--hash=sha256:e3c116e779fbbf421a9e4d3060db259a9bb486d98f4e3c5a0877c599bd173582 \
--hash=sha256:e4c8b5a243dd29d50289d694e931bd6cb6ae0b5bd654d12c647543d63862540c \
--hash=sha256:e632f66218811d4cf8b7a2a649e25ec15406c3c498f72d19e2bcf8377f38445d \
--hash=sha256:fad858519bd6d52dbfeebdbe04d00dd8e932ed436f1c535e61bcc970a96c11e4
numpy==1.23.4 ; python_version >= "3.10" and python_version < "4.0" \
matplotlib==3.6.2 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:0844523dfaaff566e39dbfa74e6f6dc42e92f7a365ce80929c5030b84caa563a \
--hash=sha256:0eda9d1b43f265da91fb9ae10d6922b5a986e2234470a524e6b18f14095b20d2 \
--hash=sha256:168093410b99f647ba61361b208f7b0d64dde1172b5b1796d765cd243cadb501 \
--hash=sha256:1836f366272b1557a613f8265db220eb8dd883202bbbabe01bad5a4eadfd0c95 \
--hash=sha256:19d61ee6414c44a04addbe33005ab1f87539d9f395e25afcbe9a3c50ce77c65c \
--hash=sha256:252957e208c23db72ca9918cb33e160c7833faebf295aaedb43f5b083832a267 \
--hash=sha256:32d29c8c26362169c80c5718ce367e8c64f4dd068a424e7110df1dd2ed7bd428 \
--hash=sha256:380d48c15ec41102a2b70858ab1dedfa33eb77b2c0982cb65a200ae67a48e9cb \
--hash=sha256:3964934731fd7a289a91d315919cf757f293969a4244941ab10513d2351b4e83 \
--hash=sha256:3cef89888a466228fc4e4b2954e740ce8e9afde7c4315fdd18caa1b8de58ca17 \
--hash=sha256:4426c74761790bff46e3d906c14c7aab727543293eed5a924300a952e1a3a3c1 \
--hash=sha256:5024b8ed83d7f8809982d095d8ab0b179bebc07616a9713f86d30cf4944acb73 \
--hash=sha256:52c2bdd7cd0bf9d5ccdf9c1816568fd4ccd51a4d82419cc5480f548981b47dd0 \
--hash=sha256:54fa9fe27f5466b86126ff38123261188bed568c1019e4716af01f97a12fe812 \
--hash=sha256:5ba73aa3aca35d2981e0b31230d58abb7b5d7ca104e543ae49709208d8ce706a \
--hash=sha256:5e16dcaecffd55b955aa5e2b8a804379789c15987e8ebd2f32f01398a81e975b \
--hash=sha256:5ecfc6559132116dedfc482d0ad9df8a89dc5909eebffd22f3deb684132d002f \
--hash=sha256:74153008bd24366cf099d1f1e83808d179d618c4e32edb0d489d526523a94d9f \
--hash=sha256:78ec3c3412cf277e6252764ee4acbdbec6920cc87ad65862272aaa0e24381eee \
--hash=sha256:795ad83940732b45d39b82571f87af0081c120feff2b12e748d96bb191169e33 \
--hash=sha256:7f716b6af94dc1b6b97c46401774472f0867e44595990fe80a8ba390f7a0a028 \
--hash=sha256:83dc89c5fd728fdb03b76f122f43b4dcee8c61f1489e232d9ad0f58020523e1c \
--hash=sha256:8a0ae37576ed444fe853709bdceb2be4c7df6f7acae17b8378765bd28e61b3ae \
--hash=sha256:8a8dbe2cb7f33ff54b16bb5c500673502a35f18ac1ed48625e997d40c922f9cc \
--hash=sha256:8a9d899953c722b9afd7e88dbefd8fb276c686c3116a43c577cfabf636180558 \
--hash=sha256:8d0068e40837c1d0df6e3abf1cdc9a34a6d2611d90e29610fa1d2455aeb4e2e5 \
--hash=sha256:9347cc6822f38db2b1d1ce992f375289670e595a2d1c15961aacbe0977407dfc \
--hash=sha256:9f335e5625feb90e323d7e3868ec337f7b9ad88b5d633f876e3b778813021dab \
--hash=sha256:b03fd10a1709d0101c054883b550f7c4c5e974f751e2680318759af005964990 \
--hash=sha256:b0ca2c60d3966dfd6608f5f8c49b8a0fcf76de6654f2eda55fc6ef038d5a6f27 \
--hash=sha256:b2604c6450f9dd2c42e223b1f5dca9643a23cfecc9fde4a94bb38e0d2693b136 \
--hash=sha256:ca0e7a658fbafcddcaefaa07ba8dae9384be2343468a8e011061791588d839fa \
--hash=sha256:d0e9ac04065a814d4cf2c6791a2ad563f739ae3ae830d716d54245c2b96fead6 \
--hash=sha256:d50e8c1e571ee39b5dfbc295c11ad65988879f68009dd281a6e1edbc2ff6c18c \
--hash=sha256:d840adcad7354be6f2ec28d0706528b0026e4c3934cc6566b84eac18633eab1b \
--hash=sha256:e0bbee6c2a5bf2a0017a9b5e397babb88f230e6f07c3cdff4a4c4bc75ed7c617 \
--hash=sha256:e5afe0a7ea0e3a7a257907060bee6724a6002b7eec55d0db16fd32409795f3e1 \
--hash=sha256:e68be81cd8c22b029924b6d0ee814c337c0e706b8d88495a617319e5dd5441c3 \
--hash=sha256:ec9be0f4826cdb3a3a517509dcc5f87f370251b76362051ab59e42b6b765f8c4 \
--hash=sha256:f04f97797df35e442ed09f529ad1235d1f1c0f30878e2fe09a2676b71a8801e0 \
--hash=sha256:f41e57ad63d336fe50d3a67bb8eaa26c09f6dda6a59f76777a99b8ccd8e26aec
numpy==1.23.4 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:0fe563fc8ed9dc4474cbf70742673fc4391d70f4363f917599a7fa99f042d5a8 \
--hash=sha256:12ac457b63ec8ded85d85c1e17d85efd3c2b0967ca39560b307a35a6703a4735 \
--hash=sha256:2341f4ab6dba0834b685cce16dad5f9b6606ea8a00e6da154f5dbded70fdc4dd \
@ -377,13 +368,13 @@ numpy==1.23.4 ; python_version >= "3.10" and python_version < "4.0" \
--hash=sha256:f260da502d7441a45695199b4e7fd8ca87db659ba1c78f2bbf31f934fe76ae0e \
--hash=sha256:f2f390aa4da44454db40a1f0201401f9036e8d578a25f01a6e237cea238337ef \
--hash=sha256:f76025acc8e2114bb664294a07ede0727aa75d63a06d2fae96bf29a81747e4a7
packaging==21.3 ; python_version >= "3.10" and python_version < "4.0" \
packaging==21.3 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb \
--hash=sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522
passlib==1.7.4 ; python_version >= "3.10" and python_version < "4.0" \
passlib==1.7.4 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1 \
--hash=sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04
pillow==9.3.0 ; python_version >= "3.10" and python_version < "4.0" \
pillow==9.3.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:03150abd92771742d4a8cd6f2fa6246d847dcd2e332a18d0c15cc75bf6703040 \
--hash=sha256:073adb2ae23431d3b9bcbcff3fe698b62ed47211d0716b067385538a1b0f28b8 \
--hash=sha256:0b07fffc13f474264c336298d1b4ce01d9c5a011415b79d4ee5527bb69ae6f65 \
@ -443,32 +434,72 @@ pillow==9.3.0 ; python_version >= "3.10" and python_version < "4.0" \
--hash=sha256:dbb8e7f2abee51cef77673be97760abff1674ed32847ce04b4af90f610144c7b \
--hash=sha256:ebf2029c1f464c59b8bdbe5143c79fa2045a581ac53679733d3a91d400ff9efb \
--hash=sha256:f1ff2ee69f10f13a9596480335f406dd1f70c3650349e2be67ca3139280cade0
pyparsing==3.0.9 ; python_version >= "3.10" and python_version < "4.0" \
pyparsing==3.0.9 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb \
--hash=sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc
python-dateutil==2.8.2 ; python_version >= "3.10" and python_version < "4.0" \
python-dateutil==2.8.2 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \
--hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9
setuptools-scm==7.0.5 ; python_version >= "3.10" and python_version < "4.0" \
setuptools-scm==7.0.5 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:031e13af771d6f892b941adb6ea04545bbf91ebc5ce68c78aaf3fff6e1fb4844 \
--hash=sha256:7930f720905e03ccd1e1d821db521bff7ec2ac9cf0ceb6552dd73d24a45d3b02
setuptools==65.5.0 ; python_version >= "3.10" and python_version < "4.0" \
--hash=sha256:512e5536220e38146176efb833d4a62aa726b7bbff82cfbc8ba9eaa3996e0b17 \
--hash=sha256:f62ea9da9ed6289bfe868cd6845968a2c854d1427f8548d52cae02a42b4f0356
six==1.16.0 ; python_version >= "3.10" and python_version < "4.0" \
setuptools==65.6.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:6211d2f5eddad8757bd0484923ca7c0a6302ebc4ab32ea5e94357176e0ca0840 \
--hash=sha256:d1eebf881c6114e51df1664bc2c9133d022f78d12d5f4f665b9191f084e2862d
six==1.16.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \
--hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254
sqlalchemy==1.4.42 ; python_version >= "3.10" and python_version < "4.0" \
--hash=sha256:177e41914c476ed1e1b77fd05966ea88c094053e17a85303c4ce007f88eff363
tomli==2.0.1 ; python_version >= "3.10" and python_version < "4.0" \
sqlalchemy==1.4.44 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:0be9b479c5806cece01f1581726573a8d6515f8404e082c375b922c45cfc2a7b \
--hash=sha256:17aee7bfcef7bf0dea92f10e5dfdd67418dcf6fe0759f520e168b605855c003e \
--hash=sha256:21f3df74a0ab39e1255e94613556e33c1dc3b454059fe0b365ec3bbb9ed82e4a \
--hash=sha256:237067ba0ef45a518b64606e1807f7229969ad568288b110ed5f0ca714a3ed3a \
--hash=sha256:2dda5f96719ae89b3ec0f1b79698d86eb9aecb1d54e990abb3fdd92c04b46a90 \
--hash=sha256:393f51a09778e8984d735b59a810731394308b4038acdb1635397c2865dae2b6 \
--hash=sha256:3ca21b35b714ce36f4b8d1ee8d15f149db8eb43a472cf71600bf18dae32286e7 \
--hash=sha256:3cbdbed8cdcae0f83640a9c44fa02b45a6c61e149c58d45a63c9581aba62850f \
--hash=sha256:3eba07f740488c3a125f17c092a81eeae24a6c7ec32ac9dbc52bf7afaf0c4f16 \
--hash=sha256:3f68eab46649504eb95be36ca529aea16cd199f080726c28cbdbcbf23d20b2a2 \
--hash=sha256:4c56e6899fa6e767e4be5d106941804a4201c5cb9620a409c0b80448ec70b656 \
--hash=sha256:53f90a2374f60e703c94118d21533765412da8225ba98659de7dd7998641ab17 \
--hash=sha256:595b185041a4dc5c685283ea98c2f67bbfa47bb28e4a4f5b27ebf40684e7a9f8 \
--hash=sha256:65a0ad931944fcb0be12a8e0ac322dbd3ecf17c53f088bc10b6da8f0caac287b \
--hash=sha256:68e0cd5d32a32c4395168d42f2fefbb03b817ead3a8f3704b8bd5697c0b26c24 \
--hash=sha256:6a06c2506c41926d2769f7968759995f2505e31c5b5a0821e43ca5a3ddb0e8ae \
--hash=sha256:6d7e1b28342b45f19e3dea7873a9479e4a57e15095a575afca902e517fb89652 \
--hash=sha256:6f0ea4d7348feb5e5d0bf317aace92e28398fa9a6e38b7be9ec1f31aad4a8039 \
--hash=sha256:7313e4acebb9ae88dbde14a8a177467a7625b7449306c03a3f9f309b30e163d0 \
--hash=sha256:7cf7c7adbf4417e3f46fc5a2dbf8395a5a69698217337086888f79700a12e93a \
--hash=sha256:80ead36fb1d676cc019586ffdc21c7e906ce4bf243fe4021e4973dae332b6038 \
--hash=sha256:9470633395e5f24d6741b4c8a6e905bce405a28cf417bba4ccbaadf3dab0111d \
--hash=sha256:94c0093678001f5d79f2dcbf3104c54d6c89e41ab50d619494c503a4d3f1aef2 \
--hash=sha256:95f4f8d62589755b507218f2e3189475a4c1f5cc9db2aec772071a7dc6cd5726 \
--hash=sha256:9c857676d810ca196be73c98eb839125d6fa849bfa3589be06201a6517f9961c \
--hash=sha256:a22208c1982f1fe2ae82e5e4c3d4a6f2445a7a0d65fb7983a3d7cbbe3983f5a4 \
--hash=sha256:ad5f966623905ee33694680dda1b735544c99c7638f216045d21546d3d8c6f5b \
--hash=sha256:ae1ed1ebc407d2f66c6f0ec44ef7d56e3f455859df5494680e2cf89dad8e3ae0 \
--hash=sha256:afd1ac99179d1864a68c06b31263a08ea25a49df94e272712eb2824ef151e294 \
--hash=sha256:b6a337a2643a41476fb6262059b8740f4b9a2ec29bf00ffb18c18c080f6e0aed \
--hash=sha256:b737fbeb2f78926d1f59964feb287bbbd050e7904766f87c8ce5cfb86e6d840c \
--hash=sha256:c46322354c58d4dc039a2c982d28284330f8919f31206894281f4b595b9d8dbe \
--hash=sha256:c7e3b9e01fdbe1ce3a165cc7e1ff52b24813ee79c6df6dee0d1e13888a97817e \
--hash=sha256:c9aa372b295a36771cffc226b6517df3011a7d146ac22d19fa6a75f1cdf9d7e6 \
--hash=sha256:d3b6d4588994da73567bb00af9d7224a16c8027865a8aab53ae9be83f9b7cbd1 \
--hash=sha256:d3b9ac11f36ab9a726097fba7c7f6384f0129aedb017f1d4d1d4fce9052a1320 \
--hash=sha256:d654870a66027af3a26df1372cf7f002e161c6768ebe4c9c6fdc0da331cb5173 \
--hash=sha256:d8080bc51a775627865e0f1dbfc0040ff4ace685f187f6036837e1727ba2ed10 \
--hash=sha256:da60b98b0f6f0df9fbf8b72d67d13b73aa8091923a48af79a951d4088530a239 \
--hash=sha256:f5e8ed9cde48b76318ab989deeddc48f833d2a6a7b7c393c49b704f67dedf01d \
--hash=sha256:f8e5443295b218b08bef8eb85d31b214d184b3690d99a33b7bd8e5591e2b0aa1
tomli==2.0.1 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \
--hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f
typing-extensions==4.4.0 ; python_version >= "3.10" and python_version < "4.0" \
typing-extensions==4.4.0 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa \
--hash=sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e
werkzeug==2.2.2 ; python_version >= "3.10" and python_version < "4.0" \
werkzeug==2.2.2 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:7ea2d48322cc7c0f8b3a215ed73eabd7b5d75d0b50e31ab006286ccff9e00b8f \
--hash=sha256:f979ab81f58d7318e064e99c4506445d60135ac5cd2e177a2de0089bfd4c9bd5
wtforms==3.0.1 ; python_version >= "3.10" and python_version < "4.0" \
wtforms==3.0.1 ; python_version >= "3.11" and python_version < "4.0" \
--hash=sha256:6b351bbb12dd58af57ffef05bc78425d08d1914e0fd68ee14143b7ade023c5bc \
--hash=sha256:837f2f0e0ca79481b92884962b914eba4e72b7a2daaf1f939c890ed0124b834b