Features: Move from poetry to uv.

Fixes: Removed naive datetime warning

Extra: Correct import in elasticsearch submodule.
This commit is contained in:
Egor Pavlovich Gorbunov 2025-10-25 02:18:41 +03:00
parent ec8c1039f3
commit ae1d16edda
28 changed files with 3916 additions and 5517 deletions

View file

@ -26,6 +26,7 @@ cython_debug/
# Python environments # Python environments
.Python .Python
.python-version
env/ env/
env.bak/ env.bak/
venv/ venv/

1
.gitignore vendored
View file

@ -27,6 +27,7 @@ venv.bak/
ENV/ ENV/
.venv/ .venv/
__pypackages__/ __pypackages__/
.python-version
# Local Django settings and database # Local Django settings and database
local_settings.py local_settings.py

View file

@ -10,7 +10,7 @@ docker-compose.yml @@maintainer
.dockerignore @@maintainer .dockerignore @@maintainer
nginx @@maintainer nginx @@maintainer
pyproject.toml @fureunoir contact@fureunoir.com pyproject.toml @fureunoir contact@fureunoir.com
poetry.lock @fureunoir contact@fureunoir.com uv.lock @fureunoir contact@fureunoir.com
*.py @fureunoir contact@fureunoir.com *.py @fureunoir contact@fureunoir.com
*.bat @fureunoir contact@fureunoir.com *.bat @fureunoir contact@fureunoir.com

View file

@ -1,5 +1,5 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
FROM python:3.12-bookworm FROM python:3.12-slim-bookworm
LABEL authors="fureunoir" LABEL authors="fureunoir"
ENV PYTHONDONTWRITEBYTECODE=1 \ ENV PYTHONDONTWRITEBYTECODE=1 \
@ -13,7 +13,7 @@ WORKDIR /app
RUN set -eux; \ RUN set -eux; \
sed -i 's|https://deb.debian.org/debian|https://ftp.uk.debian.org/debian|g' /etc/apt/sources.list.d/debian.sources; \ sed -i 's|https://deb.debian.org/debian|https://ftp.uk.debian.org/debian|g' /etc/apt/sources.list.d/debian.sources; \
apt-get update; \ apt-get update; \
apt-get install -y --no-install-recommends wget gnupg; \ apt-get install -y --no-install-recommends wget gnupg curl; \
wget -qO - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -; \ wget -qO - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -; \
echo "deb http://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" \ echo "deb http://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" \
> /etc/apt/sources.list.d/pgdg.list; \ > /etc/apt/sources.list.d/pgdg.list; \
@ -33,14 +33,21 @@ RUN set -eux; \
postgresql-client-17 \ postgresql-client-17 \
gdal-bin; \ gdal-bin; \
rm -rf /var/lib/apt/lists/*; \ rm -rf /var/lib/apt/lists/*; \
pip install --upgrade pip; \ pip install --upgrade pip
curl -sSL https://install.python-poetry.org | python3
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
ENV PATH="/root/.local/bin:/root/.cargo/bin:$PATH"
RUN uv venv /opt/evibes-python
ENV VIRTUAL_ENV=/opt/evibes-python
ENV UV_PROJECT_ENVIRONMENT=/opt/evibes-python
ENV PATH="/opt/evibes-python/bin:/root/.local/bin:/root/.cargo/bin:$PATH"
COPY pyproject.toml pyproject.toml COPY pyproject.toml pyproject.toml
COPY poetry.lock poetry.lock COPY uv.lock uv.lock
RUN poetry config virtualenvs.create false RUN set -eux; \
RUN poetry install --extras="graph worker openai testing" --no-interaction --no-ansi uv sync --extra graph --extra worker --extra openai --extra testing --locked
COPY ./scripts/Docker/app-entrypoint.sh /usr/local/bin/app-entrypoint.sh COPY ./scripts/Docker/app-entrypoint.sh /usr/local/bin/app-entrypoint.sh
RUN chmod +x /usr/local/bin/app-entrypoint.sh RUN chmod +x /usr/local/bin/app-entrypoint.sh

View file

@ -1,5 +1,5 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
FROM python:3.12-bookworm FROM python:3.12-slim-bookworm
LABEL authors="fureunoir" LABEL authors="fureunoir"
ENV PYTHONDONTWRITEBYTECODE=1 \ ENV PYTHONDONTWRITEBYTECODE=1 \
@ -13,7 +13,7 @@ WORKDIR /app
RUN set -eux; \ RUN set -eux; \
sed -i 's|https://deb.debian.org/debian|https://ftp.uk.debian.org/debian|g' /etc/apt/sources.list.d/debian.sources; \ sed -i 's|https://deb.debian.org/debian|https://ftp.uk.debian.org/debian|g' /etc/apt/sources.list.d/debian.sources; \
apt-get update; \ apt-get update; \
apt-get install -y --no-install-recommends wget gnupg; \ apt-get install -y --no-install-recommends wget gnupg curl; \
wget -qO - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -; \ wget -qO - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -; \
echo "deb http://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" \ echo "deb http://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" \
> /etc/apt/sources.list.d/pgdg.list; \ > /etc/apt/sources.list.d/pgdg.list; \
@ -33,14 +33,21 @@ RUN set -eux; \
postgresql-client-17 \ postgresql-client-17 \
gdal-bin; \ gdal-bin; \
rm -rf /var/lib/apt/lists/*; \ rm -rf /var/lib/apt/lists/*; \
pip install --upgrade pip; \ pip install --upgrade pip
curl -sSL https://install.python-poetry.org | python3
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
ENV PATH="/root/.local/bin:/root/.cargo/bin:$PATH"
ENV UV_PROJECT_ENVIRONMENT=/opt/evibes-python
ENV PATH="/opt/evibes-python/bin:/root/.local/bin:/root/.cargo/bin:$PATH"
RUN uv venv /opt/evibes-python
ENV VIRTUAL_ENV=/opt/evibes-python
COPY pyproject.toml pyproject.toml COPY pyproject.toml pyproject.toml
COPY poetry.lock poetry.lock COPY uv.lock uv.lock
RUN poetry config virtualenvs.create false RUN set -eux; \
RUN poetry install --extras="worker openai" --no-interaction --no-ansi uv sync --extra worker --extra openai --locked
COPY ./scripts/Docker/beat-entrypoint.sh /usr/local/bin/beat-entrypoint.sh COPY ./scripts/Docker/beat-entrypoint.sh /usr/local/bin/beat-entrypoint.sh
RUN chmod +x /usr/local/bin/beat-entrypoint.sh RUN chmod +x /usr/local/bin/beat-entrypoint.sh

View file

@ -1,5 +1,5 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
FROM python:3.12-bookworm FROM python:3.12-slim-bookworm
LABEL authors="fureunoir" LABEL authors="fureunoir"
ENV PYTHONDONTWRITEBYTECODE=1 \ ENV PYTHONDONTWRITEBYTECODE=1 \
@ -13,7 +13,7 @@ WORKDIR /app
RUN set -eux; \ RUN set -eux; \
sed -i 's|https://deb.debian.org/debian|https://ftp.uk.debian.org/debian|g' /etc/apt/sources.list.d/debian.sources; \ sed -i 's|https://deb.debian.org/debian|https://ftp.uk.debian.org/debian|g' /etc/apt/sources.list.d/debian.sources; \
apt-get update; \ apt-get update; \
apt-get install -y --no-install-recommends wget gnupg; \ apt-get install -y --no-install-recommends wget gnupg curl; \
wget -qO - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -; \ wget -qO - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -; \
echo "deb http://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" \ echo "deb http://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" \
> /etc/apt/sources.list.d/pgdg.list; \ > /etc/apt/sources.list.d/pgdg.list; \
@ -33,14 +33,21 @@ RUN set -eux; \
postgresql-client-17 \ postgresql-client-17 \
gdal-bin; \ gdal-bin; \
rm -rf /var/lib/apt/lists/*; \ rm -rf /var/lib/apt/lists/*; \
pip install --upgrade pip; \ pip install --upgrade pip
curl -sSL https://install.python-poetry.org | python3
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
ENV PATH="/root/.local/bin:/root/.cargo/bin:$PATH"
ENV UV_PROJECT_ENVIRONMENT=/opt/evibes-python
ENV PATH="/opt/evibes-python/bin:/root/.local/bin:/root/.cargo/bin:$PATH"
RUN uv venv /opt/evibes-python
ENV VIRTUAL_ENV=/opt/evibes-python
COPY pyproject.toml pyproject.toml COPY pyproject.toml pyproject.toml
COPY poetry.lock poetry.lock COPY uv.lock uv.lock
RUN poetry config virtualenvs.create false RUN set -eux; \
RUN poetry install --extras="worker openai" --no-interaction --no-ansi uv sync --extra worker --extra openai --locked
COPY ./scripts/Docker/stock-updater-entrypoint.sh /usr/local/bin/stock-updater-entrypoint.sh COPY ./scripts/Docker/stock-updater-entrypoint.sh /usr/local/bin/stock-updater-entrypoint.sh
RUN chmod +x /usr/local/bin/stock-updater-entrypoint.sh RUN chmod +x /usr/local/bin/stock-updater-entrypoint.sh

View file

@ -1,5 +1,5 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
FROM python:3.12-bookworm FROM python:3.12-slim-bookworm
LABEL authors="fureunoir" LABEL authors="fureunoir"
ENV PYTHONDONTWRITEBYTECODE=1 \ ENV PYTHONDONTWRITEBYTECODE=1 \
@ -13,7 +13,7 @@ WORKDIR /app
RUN set -eux; \ RUN set -eux; \
sed -i 's|https://deb.debian.org/debian|https://ftp.uk.debian.org/debian|g' /etc/apt/sources.list.d/debian.sources; \ sed -i 's|https://deb.debian.org/debian|https://ftp.uk.debian.org/debian|g' /etc/apt/sources.list.d/debian.sources; \
apt-get update; \ apt-get update; \
apt-get install -y --no-install-recommends wget gnupg; \ apt-get install -y --no-install-recommends wget gnupg curl; \
wget -qO - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -; \ wget -qO - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -; \
echo "deb http://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" \ echo "deb http://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" \
> /etc/apt/sources.list.d/pgdg.list; \ > /etc/apt/sources.list.d/pgdg.list; \
@ -33,14 +33,21 @@ RUN set -eux; \
postgresql-client-17 \ postgresql-client-17 \
gdal-bin; \ gdal-bin; \
rm -rf /var/lib/apt/lists/*; \ rm -rf /var/lib/apt/lists/*; \
pip install --upgrade pip; \ pip install --upgrade pip
curl -sSL https://install.python-poetry.org | python3
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
ENV PATH="/root/.local/bin:/root/.cargo/bin:$PATH"
RUN uv venv /opt/evibes-python
ENV VIRTUAL_ENV=/opt/evibes-python
ENV UV_PROJECT_ENVIRONMENT=/opt/evibes-python
ENV PATH="/opt/evibes-python/bin:/root/.local/bin:/root/.cargo/bin:$PATH"
COPY pyproject.toml pyproject.toml COPY pyproject.toml pyproject.toml
COPY poetry.lock poetry.lock COPY uv.lock uv.lock
RUN poetry config virtualenvs.create false RUN set -eux; \
RUN poetry install --extras="worker openai" --no-interaction --no-ansi uv sync --extra worker --extra openai --locked
COPY ./scripts/Docker/worker-entrypoint.sh /usr/local/bin/worker-entrypoint.sh COPY ./scripts/Docker/worker-entrypoint.sh /usr/local/bin/worker-entrypoint.sh
RUN chmod +x /usr/local/bin/worker-entrypoint.sh RUN chmod +x /usr/local/bin/worker-entrypoint.sh

View file

@ -1,7 +1,7 @@
import re import re
from typing import Any from typing import Any
from blib2to3.pgen2.parse import Callable from typing import Callable
from django.conf import settings from django.conf import settings
from django.db.models import QuerySet from django.db.models import QuerySet
from django.http import Http404 from django.http import Http404

View file

@ -0,0 +1,46 @@
# Generated by Django 5.2.7 on 2025-10-24 23:17
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("core", "0048_vendor_integration_path_alter_productimage_priority"),
]
operations = [
migrations.AlterUniqueTogether(
name="attribute",
unique_together={
("name", "group", "value_type"),
("name_ar_ar", "group", "value_type"),
("name_cs_cz", "group", "value_type"),
("name_da_dk", "group", "value_type"),
("name_de_de", "group", "value_type"),
("name_en_gb", "group", "value_type"),
("name_en_us", "group", "value_type"),
("name_es_es", "group", "value_type"),
("name_fa_ir", "group", "value_type"),
("name_fr_fr", "group", "value_type"),
("name_he_il", "group", "value_type"),
("name_hi_in", "group", "value_type"),
("name_hr_hr", "group", "value_type"),
("name_id_id", "group", "value_type"),
("name_it_it", "group", "value_type"),
("name_ja_jp", "group", "value_type"),
("name_kk_kz", "group", "value_type"),
("name_ko_kr", "group", "value_type"),
("name_nl_nl", "group", "value_type"),
("name_no_no", "group", "value_type"),
("name_pl_pl", "group", "value_type"),
("name_pt_br", "group", "value_type"),
("name_ro_ro", "group", "value_type"),
("name_ru_ru", "group", "value_type"),
("name_sv_se", "group", "value_type"),
("name_th_th", "group", "value_type"),
("name_tr_tr", "group", "value_type"),
("name_vi_vn", "group", "value_type"),
("name_zh_hans", "group", "value_type"),
},
),
]

View file

@ -195,12 +195,6 @@ services:
database: database:
condition: service_healthy condition: service_healthy
logging: *default-logging logging: *default-logging
healthcheck:
test: [ "CMD", "bash", "-c", "pgrep -f 'celery beat' >/dev/null" ]
interval: 30s
timeout: 10s
retries: 5
start_period: 15s
prometheus: prometheus:
container_name: prometheus container_name: prometheus

View file

@ -10,7 +10,7 @@ class GatewayQuerySet(QuerySet):
return self.annotate( return self.annotate(
daily_sum=Coalesce(Sum("transactions__amount", filter=Q(transactions__created__date=today)), Value(0.0)), daily_sum=Coalesce(Sum("transactions__amount", filter=Q(transactions__created__date=today)), Value(0.0)),
monthly_sum=Coalesce( monthly_sum=Coalesce(
Sum("transactions__amount", filter=Q(transactions__created__gte=current_month_start)), Value(0.0) Sum("transactions__amount", filter=Q(transactions__created__date__gte=current_month_start)), Value(0.0)
), ),
) )

View file

@ -0,0 +1,17 @@
# Generated by Django 5.2.7 on 2025-10-24 23:17
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("core", "0049_alter_attribute_unique_together"),
("payments", "0005_gateway_transaction_gateway"),
]
operations = [
migrations.AddIndex(
model_name="transaction",
index=models.Index(fields=["created"], name="payments_tr_created_95e595_idx"),
),
]

View file

@ -1,3 +1,4 @@
from datetime import datetime, time
from typing import Type from typing import Type
from constance import config from constance import config
@ -13,8 +14,9 @@ from django.db.models import (
PositiveIntegerField, PositiveIntegerField,
QuerySet, QuerySet,
Sum, Sum,
Index,
) )
from django.utils.timezone import now from django.utils import timezone
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from core.abstract import NiceModel from core.abstract import NiceModel
@ -64,6 +66,7 @@ class Transaction(NiceModel):
verbose_name_plural = _("transactions") verbose_name_plural = _("transactions")
indexes = [ indexes = [
GinIndex(fields=["process"]), GinIndex(fields=["process"]),
Index(fields=["created"]),
] ]
@ -143,18 +146,26 @@ class Gateway(NiceModel):
if not self.is_active: if not self.is_active:
return False return False
today = now().date() today = timezone.localdate()
current_month_start = today.replace(day=1)
tz = timezone.get_current_timezone()
month_start = timezone.make_aware(datetime.combine(today.replace(day=1), time.min), tz)
if today.month == 12:
next_month_date = today.replace(year=today.year + 1, month=1, day=1)
else:
next_month_date = today.replace(month=today.month + 1, day=1)
month_end = timezone.make_aware(datetime.combine(next_month_date, time.min), tz)
daily_sum = self.transactions.filter(created__date=today).aggregate(total=Sum("amount"))["total"] or 0 daily_sum = self.transactions.filter(created__date=today).aggregate(total=Sum("amount"))["total"] or 0
monthly_sum = ( monthly_sum = (
self.transactions.filter(created__gte=current_month_start).aggregate(total=Sum("amount"))["total"] or 0 self.transactions.filter(created__gte=month_start, created__lt=month_end).aggregate(total=Sum("amount"))[
"total"
]
or 0
) )
daily_ok = self.daily_limit == 0 or daily_sum < self.daily_limit daily_ok = self.daily_limit == 0 or daily_sum < self.daily_limit
monthly_ok = self.monthly_limit == 0 or monthly_sum < self.monthly_limit monthly_ok = self.monthly_limit == 0 or monthly_sum < self.monthly_limit
return daily_ok and monthly_ok return daily_ok and monthly_ok
@can_be_used.setter @can_be_used.setter

5343
poetry.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,106 +1,105 @@
[tool.poetry] [project]
name = "eVibes" name = "eVibes"
version = "3.1.0" version = "3.1.0"
description = "eVibes — your store without the extra baggage. Everything works out of the box: storefront, product catalog, cart, and orders. Minimal complexity, maximum flexibility — install, adjust to your needs, and start selling." description = "eVibes — your store without the extra baggage. Everything works out of the box: storefront, product catalog, cart, and orders. Minimal complexity, maximum flexibility — install, adjust to your needs, and start selling."
authors = ["fureunoir <contact@fureunoir.com>"] authors = [{ name = "fureunoir", email = "contact@fureunoir.com" }]
readme = "README.md" readme = "README.md"
package-mode = false requires-python = ">=3.12,<=3.13"
dependencies = [
"aiosmtpd==1.4.6",
"colorlog==6.10.1",
"click==8.3.0",
"cryptography==46.0.3",
"django==5.2.7",
"django-cacheops==7.2",
"django-constance==4.3.2",
"django-cors-headers==4.9.0",
"django-dbbackup==5.0.0",
"django-elasticsearch-dsl==8.2",
"django-extensions==4.1",
"django-filter==25.2",
"django-health-check==3.20.0",
"django-hosts==7.0.0",
"django-jazzmin==3.0.1",
"django-json-widget==2.1.0",
"django-mailbox==4.10.1",
"django-model-utils==5.0.0",
"django-modeltranslation==0.19.17",
"django-mptt==0.18.0",
"django-prometheus==2.4.1",
"django-redis==6.0.0",
"django-ratelimit==4.1.0",
"django-storages==1.14.6",
"django-stubs==5.2.7",
"django-summernote==0.8.20.0",
"django-widget-tweaks==1.5.0",
"django-md-field==0.1.0",
"djangorestframework==3.16.1",
"djangorestframework-camel-case==1.4.2",
"djangorestframework-recursive==0.1.2",
"djangorestframework-simplejwt[crypto]==5.5.1",
"djangorestframework-stubs==3.16.5",
"djangorestframework-xml==2.0.0",
"djangorestframework-yaml==2.0.0",
"docutils==0.22.2",
"drf-spectacular[sidecar]==0.28.0",
"elasticsearch-dsl==8.18.0",
"filelock==3.20.0",
"filetype==1.2.0",
"graphene-django==3.2.3",
"graphene-file-upload==1.3.0",
"gunicorn==23.0.0",
"httpx==0.28.1",
"paramiko==4.0.0",
"pillow==12.0.0",
"polib==1.2.0",
"PyJWT==2.10.1",
"python-slugify==8.0.4",
"psutil==7.1.1",
"psycopg2==2.9.11",
"pydantic==2.12.3",
"pymdown-extensions==10.16.1",
"redis==7.0.0",
"requests==2.32.5",
"sentry-sdk[django,celery,opentelemetry]==2.42.1",
"six==1.17.0",
"swapper==1.4.0",
"zeep==4.3.2",
"pip>=25.2",
"coverage>=7.11.0",
]
[tool.poetry.dependencies] [project.optional-dependencies]
aiosmtpd = "1.4.6" testing = ["pytest==8.4.2", "pytest-django==4.11.1", "coverage==7.11.0"]
celery = { version = "5.5.3", optional = true } graph = ["pygraphviz==1.14; sys_platform != 'win32'"]
celery-prometheus-exporter = { version = "1.7.0", optional = true } worker = [
colorlog = "6.9.0" "celery==5.5.3",
click = "8.2.1" "django-celery-beat==2.8.1",
cryptography = "45.0.4" "django-celery-results==2.6.0",
django = "5.2" "celery-prometheus-exporter==1.7.0",
django-cacheops = "7.2" ]
django-celery-beat = { version = "2.8.1", optional = true } openai = ["openai==2.6.1"]
django-celery-results = { version = "2.6.0", optional = true } jupyter = ["jupyter==1.1.1"]
django-constance = "4.3.2"
django-cors-headers = "4.7.0"
django-dbbackup = "4.3.0"
django-elasticsearch-dsl = "8.0"
django-elasticsearch-dsl-drf = "0.22.5"
django-extensions = "4.1"
django-filter = "25.1"
django-health-check = "3.20.0"
django-hosts = "6.0"
django-jazzmin = "3.0.1"
django-json-widget = "2.0.1"
django-mailbox = "4.10.1"
django-model-utils = "5.0.0"
django-modeltranslation = "0.19.15"
django-mptt = "0.17.0"
django-prometheus = "2.3.1"
django-redis = "6.0.0"
django-ratelimit = "4.1.0"
django-storages = "1.14.6"
django-stubs = "5.2.1"
django-summernote = "0.8.20.0"
django-widget-tweaks = "1.5.0"
django-md-field = "0.1.0"
djangorestframework = "3.16.0"
djangorestframework-camel-case = "1.4.2"
djangorestframework-recursive = "0.1.2"
djangorestframework-simplejwt = { extras = ["crypto"], version = "5.5.0" }
djangorestframework-stubs = "3.16.0"
djangorestframework-xml = "2.0.0"
djangorestframework-yaml = "2.0.0"
docutils = "0.21.2"
drf-spectacular = { extras = ["sidecar"], version = "0.28.0" }
elasticsearch = "8.18.1"
elasticsearch-dsl = "8.18.0"
filelock = "3.18.0"
filetype = "1.2.0"
graphene-django = "3.2.3"
graphene-file-upload = "1.3.0"
gunicorn = "23.0.0"
httpx = "0.28.1"
jupyter = { version = "1.1.1", optional = true }
mypy = "1.16.1"
openai = { version = "1.88.0", optional = true }
paramiko = "3.5.1"
pillow = "11.2.1"
polib = "1.2.0"
poetry-core = "2.1.3"
PyJWT = "2.9.0"
python = ">=3.12,<3.13"
python-slugify = "8.0.4"
psutil = "6.1.1"
psycopg2 = "2.9.10"
pydantic = "2.9.2"
pygraphviz = { version = "1.14", optional = true, markers = "sys_platform != 'win32'" }
pymdown-extensions = "10.15"
redis = "6.2.0"
requests = "2.32.4"
ruff = "0.12.0"
sentry-sdk = { extras = ["django", "celery", "opentelemetry", "redis"], version = "2.27.0" }
six = "1.17.0"
swapper = "1.4.0"
yapf = "0.43.0"
zeep = "4.3.1"
[tool.poetry.group.dev.dependencies]
black = "25.1.0"
celery-stubs = "0.1.3"
isort = "6.0.1"
flake8 = "7.2.0"
mypy-extensions = "1.1.0"
pytest = "8.4.1"
pytest-django = "4.11.1"
coverage = "7.9.1"
pre-commit = "4.2.0"
bandit = "1.8.5"
[tool.poetry.extras]
graph = ["pygraphviz"]
worker = ["celery", "django-celery-beat", "django-celery-results", "celery-prometheus-exporter"]
openai = ["openai"]
jupyter = ["jupyter"]
docs = ["sphinx", "sphinx-rtd-theme", "m2r2"] docs = ["sphinx", "sphinx-rtd-theme", "m2r2"]
testing = ["pytest", "pytest-django", "coverage"]
linting = ["black", "isort", "flake8", "bandit"] [dependency-groups]
testing = ["pytest==8.4.2", "pytest-django==4.11.1", "coverage==7.11.0"]
linting = [
"isort==7.0.0",
"bandit==1.8.6",
"pre-commit==4.3.0",
"mypy==1.18.2",
"mypy-extensions==1.1.0",
"ruff==0.14.2",
"celery-stubs==0.1.3",
]
dev = [{ include-group = "testing" }, { include-group = "linting" }]
[tool.uv]
package = false
[tool.uv.pip]
python-version = "3.12"
[tool.mypy] [tool.mypy]
strict = false strict = false
@ -122,4 +121,4 @@ ignore = ["RUF012", "A002", "A003"]
[tool.ruff.format] [tool.ruff.format]
quote-style = "double" quote-style = "double"
indent-style = "space" indent-style = "space"

View file

@ -2,11 +2,11 @@
set -e set -e
# wait for auxiliary services # wait for auxiliary services
poetry run python manage.py await_services uv run python manage.py await_services
# choose dev vs prod # choose dev vs prod
if [ "${DEBUG:-0}" = "1" ]; then if [ "${DEBUG:-0}" = "1" ]; then
exec poetry run gunicorn evibes.wsgi:application \ uv run gunicorn evibes.wsgi:application \
--bind 0.0.0.0:8000 \ --bind 0.0.0.0:8000 \
--workers 2 \ --workers 2 \
--reload \ --reload \
@ -14,7 +14,7 @@ if [ "${DEBUG:-0}" = "1" ]; then
--access-logfile - \ --access-logfile - \
--error-logfile - --error-logfile -
else else
exec poetry run gunicorn evibes.wsgi:application \ uv run gunicorn evibes.wsgi:application \
--bind 0.0.0.0:8000 \ --bind 0.0.0.0:8000 \
--workers 12 \ --workers 12 \
--timeout 120 --timeout 120

View file

@ -2,7 +2,7 @@
set -e set -e
# wait for auxiliary services # wait for auxiliary services
poetry run python manage.py await_services uv run python manage.py await_services
# run beat # run beat
poetry run celery -A evibes beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler uv run celery -A evibes beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler

View file

@ -2,7 +2,7 @@
set -e set -e
# wait for auxiliary services # wait for auxiliary services
poetry run python manage.py await_services uv run python manage.py await_services
# run stock_updater # run stock_updater
poetry run celery -A evibes worker --pool=prefork --concurrency=1 --queues=stock_updater --loglevel=info --max-tasks-per-child=1 uv run celery -A evibes worker --pool=prefork --concurrency=1 --queues=stock_updater --loglevel=info --max-tasks-per-child=1

View file

@ -2,7 +2,7 @@
set -e set -e
# wait for auxiliary services # wait for auxiliary services
poetry run python manage.py await_services uv run python manage.py await_services
# run worker and metrics exporter # run worker and metrics exporter
poetry run celery -A evibes worker --pool=prefork --concurrency=8 --loglevel=info -E --queues=default --prefetch-multiplier=1 --max-tasks-per-child=100 --max-memory-per-child=512000 --soft-time-limit=3600 --time-limit=7200 & /usr/local/bin/celery-prometheus-exporter uv run celery -A evibes worker --pool=prefork --concurrency=8 --loglevel=info -E --queues=default --prefetch-multiplier=1 --max-tasks-per-child=100 --max-memory-per-child=512000 --soft-time-limit=3600 --time-limit=7200 & /opt/evibes-python/bin/celery-prometheus-exporter

View file

@ -4,9 +4,9 @@ set -euo pipefail
source ./scripts/Unix/starter.sh source ./scripts/Unix/starter.sh
echo "Starting database backup process..." echo "Starting database backup process..."
docker compose exec app poetry run python manage.py dbbackup docker compose exec app uv run python manage.py dbbackup
echo "Database backup created under ./dbbackup" echo "Database backup created under ./dbbackup"
echo "Starting media backup process..." echo "Starting media backup process..."
docker compose exec app poetry run python manage.py mediabackup docker compose exec app uv run python manage.py mediabackup
echo "Media backup created under ./dbbackup" echo "Media backup created under ./dbbackup"

View file

@ -12,19 +12,19 @@ docker compose up -d --build --wait
echo "Services are up and healthy!" echo "Services are up and healthy!"
echo "Applying migrations..." echo "Applying migrations..."
docker compose exec app poetry run python manage.py migrate --no-input --verbosity 0 docker compose exec app uv run python manage.py migrate --no-input --verbosity 0
echo "Migrations applied successfully!" echo "Migrations applied successfully!"
echo "Collecting static files..." echo "Collecting static files..."
docker compose exec app poetry run python manage.py collectstatic --clear --no-input --verbosity 0 docker compose exec app uv run python manage.py collectstatic --clear --no-input --verbosity 0
echo "Static files collected successfully!" echo "Static files collected successfully!"
echo "Setting default caches..." echo "Setting default caches..."
docker compose exec app poetry run python manage.py set_default_caches docker compose exec app uv run python manage.py set_default_caches
echo "Default caches set successfully!" echo "Default caches set successfully!"
echo "Building search Index..." echo "Building search Index..."
docker compose exec app poetry run python manage.py search_index --rebuild -f docker compose exec app uv run python manage.py search_index --rebuild -f
echo "Search Index built successfully!" echo "Search Index built successfully!"
echo "Cleaning up unused Docker data..." echo "Cleaning up unused Docker data..."

View file

@ -18,15 +18,15 @@ docker compose up --no-build --detach --wait
echo "Services are up and healthy!" echo "Services are up and healthy!"
echo "Applying migrations…" echo "Applying migrations…"
docker compose exec app poetry run python manage.py migrate --no-input docker compose exec app uv run python manage.py migrate --no-input
echo "Migrations applied successfully!" echo "Migrations applied successfully!"
echo "Collecting static files…" echo "Collecting static files…"
docker compose exec app poetry run python manage.py collectstatic --clear --no-input docker compose exec app uv run python manage.py collectstatic --clear --no-input
echo "Static files collected successfully!" echo "Static files collected successfully!"
echo "Setting default caches…" echo "Setting default caches…"
docker compose exec app poetry run python manage.py set_default_caches docker compose exec app uv run python manage.py set_default_caches
echo "Default caches set successfully!" echo "Default caches set successfully!"
echo "Cleaning unused Docker data…" echo "Cleaning unused Docker data…"

View file

@ -8,14 +8,14 @@ if ($LASTEXITCODE -ne 0) {
} }
Write-Host "Starting database backup process..." -ForegroundColor Magenta Write-Host "Starting database backup process..." -ForegroundColor Magenta
docker compose exec app poetry run python manage.py dbbackup docker compose exec app uv run python manage.py dbbackup
if ($LASTEXITCODE -ne 0) { if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE exit $LASTEXITCODE
} }
Write-Host "Database backup created under ./dbbackup" -ForegroundColor Green Write-Host "Database backup created under ./dbbackup" -ForegroundColor Green
Write-Host "Starting media backup process..." -ForegroundColor Magenta Write-Host "Starting media backup process..." -ForegroundColor Magenta
docker compose exec app poetry run python manage.py mediabackup docker compose exec app uv run python manage.py mediabackup
if ($LASTEXITCODE -ne 0) { if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE exit $LASTEXITCODE
} }

View file

@ -13,14 +13,14 @@ if (-not (Test-Path '.env'))
} }
Write-Host "Checking placeholders in PO files..." -ForegroundColor Magenta Write-Host "Checking placeholders in PO files..." -ForegroundColor Magenta
docker compose exec app poetry run python manage.py check_translated -l ALL -a ALL docker compose exec app uv run python manage.py check_translated -l ALL -a ALL
if ($LASTEXITCODE -ne 0) { if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE exit $LASTEXITCODE
} }
Write-Host "PO files have no placeholder issues!" -ForegroundColor Green Write-Host "PO files have no placeholder issues!" -ForegroundColor Green
Write-Host "Compiling PO files into MO files..." -ForegroundColor Magenta Write-Host "Compiling PO files into MO files..." -ForegroundColor Magenta
docker compose exec app poetry run python manage.py compilemessages -l ar_AR -l cs_CZ -l da_DK -l de_DE -l en_GB -l en_US -l es_ES -l fa_IR -l fr_FR -l he_IL -l hi_IN -l hr_HR -l id_ID -l it_IT -l ja_JP -l kk_KZ -l ko_KR -l nl_NL -l no_NO -l pl_PL -l pt_BR -l ro_RO -l ru_RU -l sv_SE -l th_TH -l tr_TR -l vi_VN -l zh_Hans docker compose exec app uv run python manage.py compilemessages -l ar_AR -l cs_CZ -l da_DK -l de_DE -l en_GB -l en_US -l es_ES -l fa_IR -l fr_FR -l he_IL -l hi_IN -l hr_HR -l id_ID -l it_IT -l ja_JP -l kk_KZ -l ko_KR -l nl_NL -l no_NO -l pl_PL -l pt_BR -l ro_RO -l ru_RU -l sv_SE -l th_TH -l tr_TR -l vi_VN -l zh_Hans
if ($LASTEXITCODE -ne 0) { if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE exit $LASTEXITCODE
} }

View file

@ -13,28 +13,28 @@ if (-not (Test-Path '.env'))
} }
Write-Host "Remove old fuzzy entries..." -ForegroundColor Magenta Write-Host "Remove old fuzzy entries..." -ForegroundColor Magenta
docker compose exec app poetry run python manage.py fix_fuzzy docker compose exec app uv run python manage.py fix_fuzzy
if ($LASTEXITCODE -ne 0) { if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE exit $LASTEXITCODE
} }
Write-Host "Old fuzzy entries removed successfully!" -ForegroundColor Green Write-Host "Old fuzzy entries removed successfully!" -ForegroundColor Green
Write-Host "Updating PO files..." -ForegroundColor Magenta Write-Host "Updating PO files..." -ForegroundColor Magenta
docker compose exec app poetry run python manage.py makemessages -l ar_AR -l cs_CZ -l da_DK -l de_DE -l en_GB -l en_US -l es_ES -l fa_IR -l fr_FR -l he_IL -l hi_IN -l hr_HR -l id_ID -l it_IT -l ja_JP -l kk_KZ -l ko_KR -l nl_NL -l no_NO -l pl_PL -l pt_BR -l ro_RO -l ru_RU -l sv_SE -l th_TH -l tr_TR -l vi_VN -l zh_Hans docker compose exec app uv run python manage.py makemessages -l ar_AR -l cs_CZ -l da_DK -l de_DE -l en_GB -l en_US -l es_ES -l fa_IR -l fr_FR -l he_IL -l hi_IN -l hr_HR -l id_ID -l it_IT -l ja_JP -l kk_KZ -l ko_KR -l nl_NL -l no_NO -l pl_PL -l pt_BR -l ro_RO -l ru_RU -l sv_SE -l th_TH -l tr_TR -l vi_VN -l zh_Hans
if ($LASTEXITCODE -ne 0) { if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE exit $LASTEXITCODE
} }
Write-Host "PO files updated successfully!" -ForegroundColor Green Write-Host "PO files updated successfully!" -ForegroundColor Green
Write-Host "Fixing new fuzzy entries..." -ForegroundColor Magenta Write-Host "Fixing new fuzzy entries..." -ForegroundColor Magenta
docker compose exec app poetry run python manage.py fix_fuzzy docker compose exec app uv run python manage.py fix_fuzzy
if ($LASTEXITCODE -ne 0) { if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE exit $LASTEXITCODE
} }
Write-Host "New fuzzy entries fixed successfully!" -ForegroundColor Green Write-Host "New fuzzy entries fixed successfully!" -ForegroundColor Green
Write-Host "Translating with DeepL..." -ForegroundColor Magenta Write-Host "Translating with DeepL..." -ForegroundColor Magenta
docker compose exec app poetry run python manage.py deepl_translate -l ALL -a ALL docker compose exec app uv run python manage.py deepl_translate -l ALL -a ALL
if ($LASTEXITCODE -ne 0) { if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE exit $LASTEXITCODE
} }

View file

@ -22,28 +22,28 @@ if ($LASTEXITCODE -ne 0) {
Write-Host "Services are up and healthy!" -ForegroundColor Green Write-Host "Services are up and healthy!" -ForegroundColor Green
Write-Host "Applying migrations..." -ForegroundColor Magenta Write-Host "Applying migrations..." -ForegroundColor Magenta
docker compose exec app poetry run python manage.py migrate --no-input --verbosity 0 docker compose exec app uv run python manage.py migrate --no-input --verbosity 0
if ($LASTEXITCODE -ne 0) { if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE exit $LASTEXITCODE
} }
Write-Host "Migrations applied successfully!" -ForegroundColor Green Write-Host "Migrations applied successfully!" -ForegroundColor Green
Write-Host "Collecting static files..." -ForegroundColor Magenta Write-Host "Collecting static files..." -ForegroundColor Magenta
docker compose exec app poetry run python manage.py collectstatic --clear --no-input --verbosity 0 docker compose exec app uv run python manage.py collectstatic --clear --no-input --verbosity 0
if ($LASTEXITCODE -ne 0) { if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE exit $LASTEXITCODE
} }
Write-Host "Static files collected successfully!" -ForegroundColor Green Write-Host "Static files collected successfully!" -ForegroundColor Green
Write-Host "Setting default caches..." -ForegroundColor Magenta Write-Host "Setting default caches..." -ForegroundColor Magenta
docker compose exec app poetry run python manage.py set_default_caches docker compose exec app uv run python manage.py set_default_caches
if ($LASTEXITCODE -ne 0) { if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE exit $LASTEXITCODE
} }
Write-Host "Default caches set successfully!" -ForegroundColor Green Write-Host "Default caches set successfully!" -ForegroundColor Green
Write-Host "Building search Index..." -ForegroundColor Magenta Write-Host "Building search Index..." -ForegroundColor Magenta
docker compose exec app poetry run python manage.py search_index --rebuild -f docker compose exec app uv run python manage.py search_index --rebuild -f
if ($LASTEXITCODE -ne 0) { if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE exit $LASTEXITCODE
} }

View file

@ -38,21 +38,21 @@ if ($LASTEXITCODE -ne 0) {
Write-Host "Services are up and healthy!" -ForegroundColor Green Write-Host "Services are up and healthy!" -ForegroundColor Green
Write-Host "Applying migrations..." -ForegroundColor Magenta Write-Host "Applying migrations..." -ForegroundColor Magenta
docker compose exec app poetry run python manage.py migrate --no-input docker compose exec app uv run python manage.py migrate --no-input
if ($LASTEXITCODE -ne 0) { if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE exit $LASTEXITCODE
} }
Write-Host "Migrations applied successfully!" -ForegroundColor Green Write-Host "Migrations applied successfully!" -ForegroundColor Green
Write-Host "Collecting static files..." -ForegroundColor Magenta Write-Host "Collecting static files..." -ForegroundColor Magenta
docker compose exec app poetry run python manage.py collectstatic --clear --no-input docker compose exec app uv run python manage.py collectstatic --clear --no-input
if ($LASTEXITCODE -ne 0) { if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE exit $LASTEXITCODE
} }
Write-Host "Static files collected successfully!" -ForegroundColor Green Write-Host "Static files collected successfully!" -ForegroundColor Green
Write-Host "Setting default caches..." -ForegroundColor Magenta Write-Host "Setting default caches..." -ForegroundColor Magenta
docker compose exec app poetry run python manage.py set_default_caches docker compose exec app uv run python manage.py set_default_caches
if ($LASTEXITCODE -ne 0) { if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE exit $LASTEXITCODE
} }

3645
uv.lock Normal file

File diff suppressed because it is too large Load diff