8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-12-23 15:33:45 +00:00

Merge branch 'docker-prod' into 'dev'

docker de prod

See merge request re2o/re2o!641
This commit is contained in:
chapeau 2024-03-10 11:06:29 +00:00
commit 1014839328
15 changed files with 189 additions and 16 deletions

View file

@ -21,9 +21,7 @@ build:
ENV: dev ENV: dev
script: script:
# - docker build -t re2o . --target=postgres # - docker build -t re2o . --target=postgres
- cp -n cotisations/templates/cotisations/invoice.html templates/default_invoice.html - docker compose -f docker-compose-dev.yml run --env RUN_TESTS=yes re2o
- cp -n cotisations/templates/cotisations/voucher.html templates/default_voucher.html
- docker compose run --build re2o poetry run python manage.py test
lint: lint:
image: python:3 image: python:3

View file

@ -305,6 +305,9 @@ gitdb==4.0.11 ; python_version >= "3.8" and python_version < "4.0" \
gitpython==3.1.42 ; python_version >= "3.8" and python_version < "4.0" \ gitpython==3.1.42 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:1bf9cd7c9e7255f77778ea54359e54ac22a72a5b51288c457c881057b7bb9ecd \ --hash=sha256:1bf9cd7c9e7255f77778ea54359e54ac22a72a5b51288c457c881057b7bb9ecd \
--hash=sha256:2d99869e0fef71a73cbd242528105af1d6c1b108c60dfabd994bf292f76c3ceb --hash=sha256:2d99869e0fef71a73cbd242528105af1d6c1b108c60dfabd994bf292f76c3ceb
gunicorn==21.2.0 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:3213aa5e8c24949e792bcacfc176fef362e7aac80b76c56f6b5122bf350722f0 \
--hash=sha256:88ec8bff1d634f98e61b9f65bc4bf3cd918a90806c6f5c48bc5603849ec81033
html5lib==1.1 ; python_version >= "3.8" and python_version < "4.0" \ html5lib==1.1 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d \ --hash=sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d \
--hash=sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f --hash=sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f

36
docker-compose-dev.yml Normal file
View file

@ -0,0 +1,36 @@
version: "3"
volumes:
database_data:
driver: local
services:
db:
image: postgres:latest
volumes:
- database_data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=postgres
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
re2o:
build:
context: .
dockerfile: ./docker/Dockerfile-re2o
target: postgres-dev
depends_on:
- db
ports:
- "8000:8000"
volumes:
- .:/code
environment:
- POSTGRES_DB=postgres
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- SUPERUSER_LOGIN=admin
- SUPERUSER_PASS=admin
- SUPERUSER_EMAIL=admin@example.net
- ENV=dev
entrypoint: ./docker/docker-entrypoint-dev.sh

View file

@ -17,11 +17,8 @@ services:
re2o: re2o:
build: build:
context: . context: .
dockerfile: ./docker/Dockerfile-re2o
target: postgres target: postgres
volumes:
- .:/code
ports:
- "8000:8000"
depends_on: depends_on:
- db - db
environment: environment:
@ -31,4 +28,12 @@ services:
- SUPERUSER_LOGIN=admin - SUPERUSER_LOGIN=admin
- SUPERUSER_PASS=admin - SUPERUSER_PASS=admin
- SUPERUSER_EMAIL=admin@example.net - SUPERUSER_EMAIL=admin@example.net
- ENV=dev
nginx:
build:
context: .
dockerfile: ./docker/Dockerfile-nginx
volumes:
- ./media:/media
ports:
- "80:80"

13
docker/Dockerfile-nginx Normal file
View file

@ -0,0 +1,13 @@
FROM python:3.9-bullseye AS build
ENV PYTHONUNBUFFERED=1
RUN pip install poetry
WORKDIR /code
RUN apt-get update && apt-get install -y --no-install-recommends gettext-base gettext libpq-dev
COPY . /code/
RUN poetry install --extras "postgresql"
RUN ENV=dev DATABASE_URL='' poetry run python manage.py collectstatic --noinput
RUN poetry run python manage.py compilemessages
FROM nginx
COPY ./docker/nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=build /code/static_files /static

View file

@ -2,8 +2,7 @@ FROM python:3.9-bullseye AS base
ENV PYTHONUNBUFFERED=1 ENV PYTHONUNBUFFERED=1
RUN pip install poetry RUN pip install poetry
WORKDIR /code WORKDIR /code
RUN apt-get update && apt-get install -y --no-install-recommends gettext-base libpq-dev graphviz RUN apt-get update && apt-get install -y --no-install-recommends gettext-base gettext libpq-dev graphviz
COPY pyproject.toml poetry.lock /code/
COPY . /code/ COPY . /code/
CMD ./docker/docker-entrypoint.sh CMD ./docker/docker-entrypoint.sh
@ -12,13 +11,29 @@ ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get install -y --no-install-recommends libldap-dev slapd libsasl2-dev RUN apt-get install -y --no-install-recommends libldap-dev slapd libsasl2-dev
FROM base AS mysql FROM base AS mysql
RUN poetry install --with dev --extras "mysql" RUN poetry install --extras "mysql"
FROM base AS postgres FROM base AS postgres
RUN poetry install --with dev --extras "postgresql" RUN poetry install --extras "postgresql"
FROM ldap AS mysql-ldap FROM ldap AS mysql-ldap
RUN poetry install --with dev --extras "mysql ldap" RUN poetry install --extras "mysql ldap"
FROM ldap AS postgres-ldap FROM ldap AS postgres-ldap
RUN poetry install --extras "postgresql ldap"
FROM base AS mysql-dev
ENV RUN_TESTS=no
RUN poetry install --with dev --extras "mysql"
FROM base AS postgres-dev
ENV RUN_TESTS=no
RUN poetry install --with dev --extras "postgresql"
FROM ldap AS mysql-ldap-dev
ENV RUN_TESTS=no
RUN poetry install --with dev --extras "mysql ldap"
FROM ldap AS postgres-ldap-dev
ENV RUN_TESTS=no
RUN poetry install --with dev --extras "postgresql ldap" RUN poetry install --with dev --extras "postgresql ldap"

29
docker/docker-entrypoint-dev.sh Executable file
View file

@ -0,0 +1,29 @@
#!/usr/bin/env bash
set -euo pipefail
cp -n cotisations/templates/cotisations/invoice.html templates/default_invoice.html
cp -n cotisations/templates/cotisations/voucher.html templates/default_voucher.html
AUTOMIGRATE=${AUTOMIGRATE:-yes}
if [ "$AUTOMIGRATE" != "skip" ]; then
poetry run python manage.py migrate --noinput
fi
poetry run python manage.py collectstatic -c --noinput
poetry run python manage.py compilemessages
cat <<EOF | poetry run python manage.py shell
from django.contrib.auth import get_user_model
User = get_user_model()
User.objects.filter(pseudo='$SUPERUSER_LOGIN').exists() or \
User.objects.create_superuser(pseudo='$SUPERUSER_LOGIN', email='$SUPERUSER_EMAIL', password='$SUPERUSER_PASS', surname='$SUPERUSER_LOGIN')
EOF
if [ "$RUN_TESTS" != "no" ]; then
poetry run python manage.py test
else
poetry run python manage.py runserver 0.0.0.0:8000
fi

View file

@ -10,7 +10,6 @@ if [ "$AUTOMIGRATE" != "skip" ]; then
poetry run python manage.py migrate --noinput poetry run python manage.py migrate --noinput
fi fi
poetry run python manage.py collectstatic
poetry run python manage.py compilemessages poetry run python manage.py compilemessages
cat <<EOF | poetry run python manage.py shell cat <<EOF | poetry run python manage.py shell
@ -21,4 +20,4 @@ User = get_user_model()
User.objects.filter(pseudo='$SUPERUSER_LOGIN').exists() or \ User.objects.filter(pseudo='$SUPERUSER_LOGIN').exists() or \
User.objects.create_superuser(pseudo='$SUPERUSER_LOGIN', email='$SUPERUSER_EMAIL', password='$SUPERUSER_PASS', surname='$SUPERUSER_LOGIN') User.objects.create_superuser(pseudo='$SUPERUSER_LOGIN', email='$SUPERUSER_EMAIL', password='$SUPERUSER_PASS', surname='$SUPERUSER_LOGIN')
EOF EOF
poetry run python manage.py runserver 0.0.0.0:8000 poetry run gunicorn --workers=2 re2o.wsgi:application --bind 0.0.0.0:8000

30
docker/nginx.conf Normal file
View file

@ -0,0 +1,30 @@
server {
listen 80;
client_max_body_size 4G;
server_name localhost;
keepalive_timeout 5;
location /static {
alias /static;
}
location /media/ {
alias /media;
}
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://re2o:8000;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

View file

@ -238,6 +238,9 @@ gitdb==4.0.11 ; python_version >= "3.8" and python_version < "4.0" \
gitpython==3.1.42 ; python_version >= "3.8" and python_version < "4.0" \ gitpython==3.1.42 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:1bf9cd7c9e7255f77778ea54359e54ac22a72a5b51288c457c881057b7bb9ecd \ --hash=sha256:1bf9cd7c9e7255f77778ea54359e54ac22a72a5b51288c457c881057b7bb9ecd \
--hash=sha256:2d99869e0fef71a73cbd242528105af1d6c1b108c60dfabd994bf292f76c3ceb --hash=sha256:2d99869e0fef71a73cbd242528105af1d6c1b108c60dfabd994bf292f76c3ceb
gunicorn==21.2.0 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:3213aa5e8c24949e792bcacfc176fef362e7aac80b76c56f6b5122bf350722f0 \
--hash=sha256:88ec8bff1d634f98e61b9f65bc4bf3cd918a90806c6f5c48bc5603849ec81033
html5lib==1.1 ; python_version >= "3.8" and python_version < "4.0" \ html5lib==1.1 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d \ --hash=sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d \
--hash=sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f --hash=sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f
@ -329,6 +332,9 @@ netaddr==1.2.1 ; python_version >= "3.8" and python_version < "4.0" \
oscrypto==1.3.0 ; python_version >= "3.8" and python_version < "4.0" \ oscrypto==1.3.0 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:2b2f1d2d42ec152ca90ccb5682f3e051fb55986e1b170ebde472b133713e7085 \ --hash=sha256:2b2f1d2d42ec152ca90ccb5682f3e051fb55986e1b170ebde472b133713e7085 \
--hash=sha256:6f5fef59cb5b3708321db7cca56aed8ad7e662853351e7991fcf60ec606d47a4 --hash=sha256:6f5fef59cb5b3708321db7cca56aed8ad7e662853351e7991fcf60ec606d47a4
packaging==23.2 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5 \
--hash=sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7
pillow==8.4.0 ; python_version >= "3.8" and python_version < "4.0" \ pillow==8.4.0 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:066f3999cb3b070a95c3652712cffa1a748cd02d60ad7b4e485c3748a04d9d76 \ --hash=sha256:066f3999cb3b070a95c3652712cffa1a748cd02d60ad7b4e485c3748a04d9d76 \
--hash=sha256:0a0956fdc5defc34462bb1c765ee88d933239f9a94bc37d132004775241a7585 \ --hash=sha256:0a0956fdc5defc34462bb1c765ee88d933239f9a94bc37d132004775241a7585 \

View file

@ -235,6 +235,9 @@ gitdb==4.0.11 ; python_version >= "3.8" and python_version < "4.0" \
gitpython==3.1.42 ; python_version >= "3.8" and python_version < "4.0" \ gitpython==3.1.42 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:1bf9cd7c9e7255f77778ea54359e54ac22a72a5b51288c457c881057b7bb9ecd \ --hash=sha256:1bf9cd7c9e7255f77778ea54359e54ac22a72a5b51288c457c881057b7bb9ecd \
--hash=sha256:2d99869e0fef71a73cbd242528105af1d6c1b108c60dfabd994bf292f76c3ceb --hash=sha256:2d99869e0fef71a73cbd242528105af1d6c1b108c60dfabd994bf292f76c3ceb
gunicorn==21.2.0 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:3213aa5e8c24949e792bcacfc176fef362e7aac80b76c56f6b5122bf350722f0 \
--hash=sha256:88ec8bff1d634f98e61b9f65bc4bf3cd918a90806c6f5c48bc5603849ec81033
html5lib==1.1 ; python_version >= "3.8" and python_version < "4.0" \ html5lib==1.1 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d \ --hash=sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d \
--hash=sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f --hash=sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f
@ -336,6 +339,9 @@ netaddr==1.2.1 ; python_version >= "3.8" and python_version < "4.0" \
oscrypto==1.3.0 ; python_version >= "3.8" and python_version < "4.0" \ oscrypto==1.3.0 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:2b2f1d2d42ec152ca90ccb5682f3e051fb55986e1b170ebde472b133713e7085 \ --hash=sha256:2b2f1d2d42ec152ca90ccb5682f3e051fb55986e1b170ebde472b133713e7085 \
--hash=sha256:6f5fef59cb5b3708321db7cca56aed8ad7e662853351e7991fcf60ec606d47a4 --hash=sha256:6f5fef59cb5b3708321db7cca56aed8ad7e662853351e7991fcf60ec606d47a4
packaging==23.2 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5 \
--hash=sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7
pillow==8.4.0 ; python_version >= "3.8" and python_version < "4.0" \ pillow==8.4.0 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:066f3999cb3b070a95c3652712cffa1a748cd02d60ad7b4e485c3748a04d9d76 \ --hash=sha256:066f3999cb3b070a95c3652712cffa1a748cd02d60ad7b4e485c3748a04d9d76 \
--hash=sha256:0a0956fdc5defc34462bb1c765ee88d933239f9a94bc37d132004775241a7585 \ --hash=sha256:0a0956fdc5defc34462bb1c765ee88d933239f9a94bc37d132004775241a7585 \

22
poetry.lock generated
View file

@ -670,6 +670,26 @@ gitdb = ">=4.0.1,<5"
[package.extras] [package.extras]
test = ["black", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock", "mypy", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar"] test = ["black", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock", "mypy", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar"]
[[package]]
name = "gunicorn"
version = "21.2.0"
description = "WSGI HTTP Server for UNIX"
optional = false
python-versions = ">=3.5"
files = [
{file = "gunicorn-21.2.0-py3-none-any.whl", hash = "sha256:3213aa5e8c24949e792bcacfc176fef362e7aac80b76c56f6b5122bf350722f0"},
{file = "gunicorn-21.2.0.tar.gz", hash = "sha256:88ec8bff1d634f98e61b9f65bc4bf3cd918a90806c6f5c48bc5603849ec81033"},
]
[package.dependencies]
packaging = "*"
[package.extras]
eventlet = ["eventlet (>=0.24.1)"]
gevent = ["gevent (>=1.4.0)"]
setproctitle = ["setproctitle"]
tornado = ["tornado (>=0.2)"]
[[package]] [[package]]
name = "html5lib" name = "html5lib"
version = "1.1" version = "1.1"
@ -2165,4 +2185,4 @@ postgresql = ["psycopg2"]
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = ">=3.8,<4.0" python-versions = ">=3.8,<4.0"
content-hash = "35c7fcf4285d44bb7287cb8d9573f327beec53c61979faae77a8c077c2560930" content-hash = "f50b5e6d4c12f6c66b56d79a0999d353df86a887d003d3059a206b1373da5b7f"

View file

@ -235,6 +235,9 @@ gitdb==4.0.11 ; python_version >= "3.8" and python_version < "4.0" \
gitpython==3.1.42 ; python_version >= "3.8" and python_version < "4.0" \ gitpython==3.1.42 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:1bf9cd7c9e7255f77778ea54359e54ac22a72a5b51288c457c881057b7bb9ecd \ --hash=sha256:1bf9cd7c9e7255f77778ea54359e54ac22a72a5b51288c457c881057b7bb9ecd \
--hash=sha256:2d99869e0fef71a73cbd242528105af1d6c1b108c60dfabd994bf292f76c3ceb --hash=sha256:2d99869e0fef71a73cbd242528105af1d6c1b108c60dfabd994bf292f76c3ceb
gunicorn==21.2.0 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:3213aa5e8c24949e792bcacfc176fef362e7aac80b76c56f6b5122bf350722f0 \
--hash=sha256:88ec8bff1d634f98e61b9f65bc4bf3cd918a90806c6f5c48bc5603849ec81033
html5lib==1.1 ; python_version >= "3.8" and python_version < "4.0" \ html5lib==1.1 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d \ --hash=sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d \
--hash=sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f --hash=sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f
@ -326,6 +329,9 @@ netaddr==1.2.1 ; python_version >= "3.8" and python_version < "4.0" \
oscrypto==1.3.0 ; python_version >= "3.8" and python_version < "4.0" \ oscrypto==1.3.0 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:2b2f1d2d42ec152ca90ccb5682f3e051fb55986e1b170ebde472b133713e7085 \ --hash=sha256:2b2f1d2d42ec152ca90ccb5682f3e051fb55986e1b170ebde472b133713e7085 \
--hash=sha256:6f5fef59cb5b3708321db7cca56aed8ad7e662853351e7991fcf60ec606d47a4 --hash=sha256:6f5fef59cb5b3708321db7cca56aed8ad7e662853351e7991fcf60ec606d47a4
packaging==23.2 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5 \
--hash=sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7
pillow==8.4.0 ; python_version >= "3.8" and python_version < "4.0" \ pillow==8.4.0 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:066f3999cb3b070a95c3652712cffa1a748cd02d60ad7b4e485c3748a04d9d76 \ --hash=sha256:066f3999cb3b070a95c3652712cffa1a748cd02d60ad7b4e485c3748a04d9d76 \
--hash=sha256:0a0956fdc5defc34462bb1c765ee88d933239f9a94bc37d132004775241a7585 \ --hash=sha256:0a0956fdc5defc34462bb1c765ee88d933239f9a94bc37d132004775241a7585 \

View file

@ -62,6 +62,7 @@ xhtml2pdf = "^0.2.6"
pylint-django = {version = "^2.5.5", optional=true} pylint-django = {version = "^2.5.5", optional=true}
pylint = {version = "^3.1.0", optional=true} pylint = {version = "^3.1.0", optional=true}
python-decouple = "^3.8" python-decouple = "^3.8"
gunicorn = "^21.2.0"
[tool.poetry.extras] [tool.poetry.extras]
mysql = ["mysqlclient"] mysql = ["mysqlclient"]

View file

@ -235,6 +235,9 @@ gitdb==4.0.11 ; python_version >= "3.8" and python_version < "4.0" \
gitpython==3.1.42 ; python_version >= "3.8" and python_version < "4.0" \ gitpython==3.1.42 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:1bf9cd7c9e7255f77778ea54359e54ac22a72a5b51288c457c881057b7bb9ecd \ --hash=sha256:1bf9cd7c9e7255f77778ea54359e54ac22a72a5b51288c457c881057b7bb9ecd \
--hash=sha256:2d99869e0fef71a73cbd242528105af1d6c1b108c60dfabd994bf292f76c3ceb --hash=sha256:2d99869e0fef71a73cbd242528105af1d6c1b108c60dfabd994bf292f76c3ceb
gunicorn==21.2.0 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:3213aa5e8c24949e792bcacfc176fef362e7aac80b76c56f6b5122bf350722f0 \
--hash=sha256:88ec8bff1d634f98e61b9f65bc4bf3cd918a90806c6f5c48bc5603849ec81033
html5lib==1.1 ; python_version >= "3.8" and python_version < "4.0" \ html5lib==1.1 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d \ --hash=sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d \
--hash=sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f --hash=sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f
@ -326,6 +329,9 @@ netaddr==1.2.1 ; python_version >= "3.8" and python_version < "4.0" \
oscrypto==1.3.0 ; python_version >= "3.8" and python_version < "4.0" \ oscrypto==1.3.0 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:2b2f1d2d42ec152ca90ccb5682f3e051fb55986e1b170ebde472b133713e7085 \ --hash=sha256:2b2f1d2d42ec152ca90ccb5682f3e051fb55986e1b170ebde472b133713e7085 \
--hash=sha256:6f5fef59cb5b3708321db7cca56aed8ad7e662853351e7991fcf60ec606d47a4 --hash=sha256:6f5fef59cb5b3708321db7cca56aed8ad7e662853351e7991fcf60ec606d47a4
packaging==23.2 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5 \
--hash=sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7
pillow==8.4.0 ; python_version >= "3.8" and python_version < "4.0" \ pillow==8.4.0 ; python_version >= "3.8" and python_version < "4.0" \
--hash=sha256:066f3999cb3b070a95c3652712cffa1a748cd02d60ad7b4e485c3748a04d9d76 \ --hash=sha256:066f3999cb3b070a95c3652712cffa1a748cd02d60ad7b4e485c3748a04d9d76 \
--hash=sha256:0a0956fdc5defc34462bb1c765ee88d933239f9a94bc37d132004775241a7585 \ --hash=sha256:0a0956fdc5defc34462bb1c765ee88d933239f9a94bc37d132004775241a7585 \