mirror of
https://github.com/boostorg/website-v2.git
synced 2026-01-19 04:42:17 +00:00
Upgrade django to 5.2, python to 3.13 (#1915)
This commit is contained in:
10
.github/workflows/actions-gcp.yaml
vendored
10
.github/workflows/actions-gcp.yaml
vendored
@@ -25,7 +25,7 @@ jobs:
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
postgres:
|
postgres:
|
||||||
image: postgres:12
|
image: postgres:16
|
||||||
env:
|
env:
|
||||||
POSTGRES_USER: postgres
|
POSTGRES_USER: postgres
|
||||||
POSTGRES_PASSWORD: postgres
|
POSTGRES_PASSWORD: postgres
|
||||||
@@ -44,10 +44,10 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up Python 3.11
|
- name: Set up Python 3.13
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: 3.11
|
python-version: 3.13
|
||||||
|
|
||||||
- uses: actions/cache@v4
|
- uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
@@ -133,10 +133,10 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
git fetch --depth=1 origin +refs/tags/*:refs/tags/* || true
|
git fetch --depth=1 origin +refs/tags/*:refs/tags/* || true
|
||||||
|
|
||||||
- name: Set up Python 3.11
|
- name: Set up Python 3.13
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: 3.11
|
python-version: 3.13
|
||||||
|
|
||||||
- name: Install Python dependencies
|
- name: Install Python dependencies
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
10
.github/workflows/actions.yml
vendored
10
.github/workflows/actions.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
postgres:
|
postgres:
|
||||||
image: postgres:12
|
image: postgres:16
|
||||||
env:
|
env:
|
||||||
POSTGRES_USER: postgres
|
POSTGRES_USER: postgres
|
||||||
POSTGRES_PASSWORD: postgres
|
POSTGRES_PASSWORD: postgres
|
||||||
@@ -34,10 +34,10 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up Python 3.11
|
- name: Set up Python 3.13
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: 3.11
|
python-version: 3.13
|
||||||
|
|
||||||
- uses: actions/cache@v4
|
- uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
@@ -85,10 +85,10 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
git fetch --depth=1 origin +refs/tags/*:refs/tags/* || true
|
git fetch --depth=1 origin +refs/tags/*:refs/tags/* || true
|
||||||
|
|
||||||
- name: Set up Python 3.11
|
- name: Set up Python 3.13
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: 3.11
|
python-version: 3.13
|
||||||
|
|
||||||
- name: Install Python dependencies
|
- name: Install Python dependencies
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
default_language_version:
|
default_language_version:
|
||||||
python: python3.11
|
python: python3.13
|
||||||
|
|
||||||
exclude: .*migrations\/.*|static\/img\/.*|static\/animations\/.*|static\/js\/boost-gecko\/.*|kube\/boost\/templates\/.*\.yaml
|
exclude: .*migrations\/.*|static\/img\/.*|static\/animations\/.*|static\/js\/boost-gecko\/.*|kube\/boost\/templates\/.*\.yaml
|
||||||
|
|
||||||
repos:
|
repos:
|
||||||
|
- repo: https://github.com/adamchainz/django-upgrade
|
||||||
|
rev: "1.27.0"
|
||||||
|
hooks:
|
||||||
|
- id: django-upgrade
|
||||||
|
args: [--target-version, "5.2"] # Replace with Django version
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v5.0.0
|
rev: v5.0.0
|
||||||
hooks:
|
hooks:
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ Links:
|
|||||||
|
|
||||||
## Local Development Setup
|
## Local Development Setup
|
||||||
|
|
||||||
This project will use Python 3.11, Docker, and Docker Compose.
|
This project will use Python 3.13, Docker, and Docker Compose.
|
||||||
|
|
||||||
Instructions to install those packages are included in [development_setup_notes.md](docs/development_setup_notes.md).
|
Instructions to install those packages are included in [development_setup_notes.md](docs/development_setup_notes.md).
|
||||||
|
|
||||||
|
|||||||
@@ -20,10 +20,8 @@ def get_calendar(min_time=None, single_events=True, order_by="startTime"):
|
|||||||
https://developers.google.com/calendar/api/v3/reference/events/list
|
https://developers.google.com/calendar/api/v3/reference/events/list
|
||||||
"""
|
"""
|
||||||
if not min_time:
|
if not min_time:
|
||||||
min_time = (
|
# 'Z' indicates UTC time
|
||||||
datetime.datetime.utcnow().isoformat() + "Z"
|
min_time = datetime.datetime.now(datetime.timezone.utc).isoformat() + "Z"
|
||||||
) # 'Z' indicates UTC time
|
|
||||||
|
|
||||||
url = f"https://www.googleapis.com/calendar/v3/calendars/{settings.BOOST_CALENDAR}/events?key={settings.CALENDAR_API_KEY}&timeMin={min_time}&singleEvents={single_events}&orderBy={order_by}"
|
url = f"https://www.googleapis.com/calendar/v3/calendars/{settings.BOOST_CALENDAR}/events?key={settings.CALENDAR_API_KEY}&timeMin={min_time}&singleEvents={single_events}&orderBy={order_by}"
|
||||||
|
|
||||||
headers = {"Accept": "application/json"}
|
headers = {"Accept": "application/json"}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddConstraint(
|
migrations.AddConstraint(
|
||||||
model_name="sitesettings",
|
model_name="sitesettings",
|
||||||
constraint=models.CheckConstraint(
|
constraint=models.CheckConstraint(
|
||||||
check=models.Q(("id", 1)), name="core_sitesettings_single_instance"
|
condition=models.Q(("id", 1)), name="core_sitesettings_single_instance"
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
migrations.AlterModelOptions(
|
migrations.AlterModelOptions(
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ class SiteSettings(models.Model):
|
|||||||
# check constraint to only allow id=1 to exist
|
# check constraint to only allow id=1 to exist
|
||||||
models.CheckConstraint(
|
models.CheckConstraint(
|
||||||
name="%(app_label)s_%(class)s_single_instance",
|
name="%(app_label)s_%(class)s_single_instance",
|
||||||
check=models.Q(id=1),
|
condition=models.Q(id=1),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
verbose_name_plural = "Site Settings"
|
verbose_name_plural = "Site Settings"
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
|
import requests
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from urllib.parse import urljoin
|
from urllib.parse import urljoin
|
||||||
@@ -16,11 +17,14 @@ from django.http import (
|
|||||||
HttpResponse,
|
HttpResponse,
|
||||||
HttpResponseNotFound,
|
HttpResponseNotFound,
|
||||||
HttpResponseRedirect,
|
HttpResponseRedirect,
|
||||||
|
HttpRequest,
|
||||||
)
|
)
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from django.utils.decorators import method_decorator
|
||||||
from django.views import View
|
from django.views import View
|
||||||
|
from django.views.decorators.cache import never_cache
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
|
|
||||||
from config.settings import ENABLE_DB_CACHE
|
from config.settings import ENABLE_DB_CACHE
|
||||||
@@ -942,3 +946,57 @@ class RedirectToLibrariesView(BaseRedirectView):
|
|||||||
if requested_version == "release":
|
if requested_version == "release":
|
||||||
new_path = "/libraries/"
|
new_path = "/libraries/"
|
||||||
return HttpResponseRedirect(new_path)
|
return HttpResponseRedirect(new_path)
|
||||||
|
|
||||||
|
|
||||||
|
@method_decorator(never_cache, name="dispatch")
|
||||||
|
class QRCodeView(View):
|
||||||
|
"""Handles QR code urls, sending them to Plausible, then redirecting to the desired url.
|
||||||
|
|
||||||
|
QR code urls are formatted /qrc/<campaign_identifier>/desired/path/to/content/, and will
|
||||||
|
result in a redirect to /desired/path/to/content/.
|
||||||
|
|
||||||
|
E.g. https://www.boost.org/qrc/pv-01/library/latest/beast/ will send this full url to Plausible,
|
||||||
|
then redirect to https://www.boost.org/library/latest/beast/
|
||||||
|
"""
|
||||||
|
|
||||||
|
def get(self, request: HttpRequest, campaign_identifier: str, main_path: str = ""):
|
||||||
|
absolute_url = request.build_absolute_uri(request.path)
|
||||||
|
referrer = request.headers.get("referer", "")
|
||||||
|
user_agent = request.headers.get("user-agent", "")
|
||||||
|
|
||||||
|
plausible_payload = {
|
||||||
|
"name": "pageview",
|
||||||
|
"domain": "qrc.boost.org",
|
||||||
|
"url": absolute_url,
|
||||||
|
"referrer": referrer,
|
||||||
|
}
|
||||||
|
|
||||||
|
headers = {"Content-Type": "application/json", "User-Agent": user_agent}
|
||||||
|
|
||||||
|
client_ip = request.headers.get("x-forwarded-for", "").split(",")[0].strip()
|
||||||
|
client_ip = client_ip or request.META.get("REMOTE_ADDR")
|
||||||
|
|
||||||
|
if client_ip:
|
||||||
|
headers["X-Forwarded-For"] = client_ip
|
||||||
|
|
||||||
|
try:
|
||||||
|
requests.post(
|
||||||
|
"https://plausible.io/api/event",
|
||||||
|
json=plausible_payload,
|
||||||
|
headers=headers,
|
||||||
|
timeout=2.0,
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
# Don’t interrupt the redirect - just log it
|
||||||
|
logger.error(f"Plausible event post failed: {e}")
|
||||||
|
|
||||||
|
# Now that we've sent the request url to plausible, we can redirect to the main_path
|
||||||
|
# Preserve the original querystring, if any.
|
||||||
|
# Example: /qrc/3/library/latest/algorithm/?x=1 -> /library/latest/algorithm/?x=1
|
||||||
|
# `main_path` is everything after qrc/<campaign>/ thanks to <path:main_path>.
|
||||||
|
redirect_path = "/" + main_path if main_path else "/"
|
||||||
|
qs = request.META.get("QUERY_STRING")
|
||||||
|
if qs:
|
||||||
|
redirect_path = f"{redirect_path}?{qs}"
|
||||||
|
|
||||||
|
return HttpResponseRedirect(redirect_path)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# syntax = docker/dockerfile:experimental
|
# syntax = docker/dockerfile:experimental
|
||||||
|
|
||||||
FROM python:3.11-slim AS builder-py
|
FROM python:3.13-slim AS builder-py
|
||||||
|
|
||||||
ARG LOCAL_DEVELOPMENT
|
ARG LOCAL_DEVELOPMENT
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ RUN yarn build
|
|||||||
|
|
||||||
|
|
||||||
# Final image.
|
# Final image.
|
||||||
FROM python:3.11-slim AS release
|
FROM python:3.13-slim AS release
|
||||||
|
|
||||||
RUN apt update && apt install -y git libpq-dev ruby ruby-dev && rm -rf /var/lib/apt/lists/*
|
RUN apt update && apt install -y git libpq-dev ruby ruby-dev && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
|||||||
@@ -7,3 +7,14 @@
|
|||||||
1. Run `just pip-compile`, which will add the dependency to `requirements.txt`
|
1. Run `just pip-compile`, which will add the dependency to `requirements.txt`
|
||||||
1. Run `just rebuild` to rebuild your Docker image to include the new dependencies
|
1. Run `just rebuild` to rebuild your Docker image to include the new dependencies
|
||||||
2. Run `just up` and continue with development
|
2. Run `just up` and continue with development
|
||||||
|
|
||||||
|
## Upgrading dependencies
|
||||||
|
|
||||||
|
To upgrade all dependencies to their latest versions, run:
|
||||||
|
|
||||||
|
1. `just pip-compile-upgrade`.
|
||||||
|
2. Get the django version from requirements.txt and set the `DJANGO_VERSION` value in /justfile
|
||||||
|
3. Update the `--target-version` args value for django-upgrade in .pre-commit-config.yaml to match
|
||||||
|
3. In a venv with installed packages run `just run-django-upgrade` to upgrade python code.
|
||||||
|
4. `just build` to create new docker images.
|
||||||
|
5. Tear down docker containers and restart with the newly built images, then test.
|
||||||
|
|||||||
5
justfile
5
justfile
@@ -1,6 +1,7 @@
|
|||||||
set dotenv-load := false
|
set dotenv-load := false
|
||||||
COMPOSE_FILE := "docker-compose.yml"
|
COMPOSE_FILE := "docker-compose.yml"
|
||||||
ENV_FILE := ".env"
|
ENV_FILE := ".env"
|
||||||
|
DJANGO_VERSION := "5.2"
|
||||||
|
|
||||||
@_default:
|
@_default:
|
||||||
just --list
|
just --list
|
||||||
@@ -122,6 +123,10 @@ alias shell := console
|
|||||||
fi
|
fi
|
||||||
@cd development-tofu; direnv allow && tofu destroy
|
@cd development-tofu; direnv allow && tofu destroy
|
||||||
|
|
||||||
|
@run-django-upgrade:
|
||||||
|
[ -n "${VIRTUAL_ENV-}" ] || { echo "❌ Activate your venv first."; exit 1; }
|
||||||
|
-git ls-files -z -- '*.py' | xargs -0r django-upgrade --target {{DJANGO_VERSION}}
|
||||||
|
|
||||||
# Dependency management
|
# Dependency management
|
||||||
@pip-compile ARGS='': ## rebuilds our pip requirements
|
@pip-compile ARGS='': ## rebuilds our pip requirements
|
||||||
docker compose run --rm web uv pip compile {{ ARGS }} ./requirements.in --no-strip-extras --output-file ./requirements.txt
|
docker compose run --rm web uv pip compile {{ ARGS }} ./requirements.in --no-strip-extras --output-file ./requirements.txt
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ class PlausibleRedirectView(View):
|
|||||||
|
|
||||||
def get(self, request: HttpRequest, campaign_identifier: str, main_path: str = ""):
|
def get(self, request: HttpRequest, campaign_identifier: str, main_path: str = ""):
|
||||||
absolute_url = request.build_absolute_uri(request.path)
|
absolute_url = request.build_absolute_uri(request.path)
|
||||||
referrer = request.META.get("HTTP_REFERER", "")
|
referrer = request.headers.get("referer", "")
|
||||||
user_agent = request.META.get("HTTP_USER_AGENT", "")
|
user_agent = request.headers.get("user-agent", "")
|
||||||
|
|
||||||
plausible_payload = {
|
plausible_payload = {
|
||||||
"name": "pageview",
|
"name": "pageview",
|
||||||
@@ -40,7 +40,7 @@ class PlausibleRedirectView(View):
|
|||||||
|
|
||||||
headers = {"Content-Type": "application/json", "User-Agent": user_agent}
|
headers = {"Content-Type": "application/json", "User-Agent": user_agent}
|
||||||
|
|
||||||
client_ip = request.META.get("HTTP_X_FORWARDED_FOR", "").split(",")[0].strip()
|
client_ip = request.headers.get("x-forwarded-for", "").split(",")[0].strip()
|
||||||
client_ip = client_ip or request.META.get("REMOTE_ADDR")
|
client_ip = client_ip or request.META.get("REMOTE_ADDR")
|
||||||
|
|
||||||
if client_ip:
|
if client_ip:
|
||||||
@@ -85,7 +85,7 @@ class WhitePaperView(SuccessMessageMixin, CreateView):
|
|||||||
if original_referrer := self.request.session.get("original_referrer", ""):
|
if original_referrer := self.request.session.get("original_referrer", ""):
|
||||||
self.referrer = original_referrer
|
self.referrer = original_referrer
|
||||||
else:
|
else:
|
||||||
self.referrer = self.request.META.get("HTTP_REFERER", "")
|
self.referrer = self.request.headers.get("referer", "")
|
||||||
return super().dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_template_names(self):
|
def get_template_names(self):
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime, timezone
|
||||||
from django.contrib.syndication.views import Feed
|
from django.contrib.syndication.views import Feed
|
||||||
from django.utils.feedgenerator import Atom1Feed
|
from django.utils.feedgenerator import Atom1Feed
|
||||||
from django.utils.timezone import make_aware, utc
|
from django.utils.timezone import make_aware
|
||||||
from django.utils.html import urlize, linebreaks
|
from django.utils.html import urlize, linebreaks
|
||||||
|
|
||||||
from .models import Entry
|
from .models import Entry
|
||||||
@@ -22,7 +22,7 @@ class RSSNewsFeed(Feed):
|
|||||||
publish_date = item.publish_at
|
publish_date = item.publish_at
|
||||||
if publish_date:
|
if publish_date:
|
||||||
datetime_obj = datetime.combine(publish_date, datetime.min.time())
|
datetime_obj = datetime.combine(publish_date, datetime.min.time())
|
||||||
aware_datetime_obj = make_aware(datetime_obj, timezone=utc)
|
aware_datetime_obj = make_aware(datetime_obj, timezone=timezone.utc)
|
||||||
return aware_datetime_obj
|
return aware_datetime_obj
|
||||||
|
|
||||||
def item_description(self, item):
|
def item_description(self, item):
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ def generate_magic_approval_link(entry_slug: str, moderator_id: int):
|
|||||||
def send_email_news_needs_moderation(request, entry):
|
def send_email_news_needs_moderation(request, entry):
|
||||||
recipient_list = [
|
recipient_list = [
|
||||||
u
|
u
|
||||||
for u in moderators().select_related("preferences").only("email")
|
for u in moderators().select_related("preferences").only("email", "preferences")
|
||||||
if entry.tag in u.preferences.allow_notification_others_news_needs_moderation
|
if entry.tag in u.preferences.allow_notification_others_news_needs_moderation
|
||||||
]
|
]
|
||||||
if not recipient_list:
|
if not recipient_list:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta, timezone
|
||||||
from django.utils.timezone import make_aware, now, utc
|
from django.utils.timezone import make_aware, now
|
||||||
from model_bakery import baker
|
from model_bakery import baker
|
||||||
from ..feeds import RSSNewsFeed, AtomNewsFeed
|
from ..feeds import RSSNewsFeed, AtomNewsFeed
|
||||||
|
|
||||||
@@ -22,7 +22,8 @@ def test_item_pubdate(make_entry):
|
|||||||
feed = RSSNewsFeed()
|
feed = RSSNewsFeed()
|
||||||
published_entry = make_entry(moderator=baker.make("users.User"), approved_at=now())
|
published_entry = make_entry(moderator=baker.make("users.User"), approved_at=now())
|
||||||
expected_datetime = make_aware(
|
expected_datetime = make_aware(
|
||||||
datetime.combine(published_entry.publish_at, datetime.min.time()), timezone=utc
|
datetime.combine(published_entry.publish_at, datetime.min.time()),
|
||||||
|
timezone=timezone.utc,
|
||||||
)
|
)
|
||||||
assert feed.item_pubdate(published_entry) == expected_datetime
|
assert feed.item_pubdate(published_entry) == expected_datetime
|
||||||
|
|
||||||
@@ -51,6 +52,7 @@ def test_item_pubdate_atom(make_entry):
|
|||||||
feed = AtomNewsFeed()
|
feed = AtomNewsFeed()
|
||||||
published_entry = make_entry(moderator=baker.make("users.User"), approved_at=now())
|
published_entry = make_entry(moderator=baker.make("users.User"), approved_at=now())
|
||||||
expected_datetime = make_aware(
|
expected_datetime = make_aware(
|
||||||
datetime.combine(published_entry.publish_at, datetime.min.time()), timezone=utc
|
datetime.combine(published_entry.publish_at, datetime.min.time()),
|
||||||
|
timezone=timezone.utc,
|
||||||
)
|
)
|
||||||
assert feed.item_pubdate(published_entry) == expected_datetime
|
assert feed.item_pubdate(published_entry) == expected_datetime
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ whitelist-regex = ["test_.*"]
|
|||||||
|
|
||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
line-length = 88
|
line-length = 88
|
||||||
target-version = "py311"
|
target-version = "py313"
|
||||||
|
|
||||||
[tool.black]
|
[tool.black]
|
||||||
line-length = 88
|
line-length = 88
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
-c requirements.txt
|
-c requirements.txt
|
||||||
django-debug-toolbar
|
django-debug-toolbar
|
||||||
pydevd-pycharm==243.26053.29 # pinned to appropriate version for current pycharm
|
pydevd-pycharm==252.26830.99 # pinned to appropriate version for current pycharm
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
# This file was autogenerated by uv via the following command:
|
# This file was autogenerated by uv via the following command:
|
||||||
# uv pip compile ./requirements-dev.in --no-strip-extras --output-file ./requirements-dev.txt
|
# uv pip compile ./requirements-dev.in --no-strip-extras --output-file ./requirements-dev.txt
|
||||||
asgiref==3.9.1
|
asgiref==3.10.0
|
||||||
# via
|
# via
|
||||||
# -c ./requirements.txt
|
# -c ./requirements.txt
|
||||||
# django
|
# django
|
||||||
django==4.2.24
|
django==5.2.7
|
||||||
# via
|
# via
|
||||||
# -c ./requirements.txt
|
# -c ./requirements.txt
|
||||||
# django-debug-toolbar
|
# django-debug-toolbar
|
||||||
django-debug-toolbar==6.0.0
|
django-debug-toolbar==6.0.0
|
||||||
# via -r ./requirements-dev.in
|
# via -r ./requirements-dev.in
|
||||||
pydevd-pycharm==243.26053.29
|
pydevd-pycharm==252.26830.99
|
||||||
# via -r ./requirements-dev.in
|
# via -r ./requirements-dev.in
|
||||||
sqlparse==0.5.3
|
sqlparse==0.5.3
|
||||||
# via
|
# via
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Django>=4.0, <5.0
|
Django>=5.0, <6.0
|
||||||
bumpversion
|
bumpversion
|
||||||
django-admin-env-notice
|
django-admin-env-notice
|
||||||
django-allauth
|
django-allauth
|
||||||
@@ -12,7 +12,7 @@ django-health-check
|
|||||||
django-imagekit
|
django-imagekit
|
||||||
django-oauth-toolkit
|
django-oauth-toolkit
|
||||||
django-redis
|
django-redis
|
||||||
django-rest-auth
|
django-upgrade
|
||||||
django-widget-tweaks
|
django-widget-tweaks
|
||||||
djangorestframework
|
djangorestframework
|
||||||
environs[django]
|
environs[django]
|
||||||
|
|||||||
150
requirements.txt
150
requirements.txt
@@ -2,17 +2,17 @@
|
|||||||
# uv pip compile ./requirements.in --no-strip-extras --output-file ./requirements.txt
|
# uv pip compile ./requirements.in --no-strip-extras --output-file ./requirements.txt
|
||||||
aiohappyeyeballs==2.6.1
|
aiohappyeyeballs==2.6.1
|
||||||
# via aiohttp
|
# via aiohttp
|
||||||
aiohttp==3.12.15
|
aiohttp==3.13.1
|
||||||
# via algoliasearch
|
# via algoliasearch
|
||||||
aiosignal==1.4.0
|
aiosignal==1.4.0
|
||||||
# via aiohttp
|
# via aiohttp
|
||||||
algoliasearch==4.27.0
|
algoliasearch==4.30.0
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
amqp==5.3.1
|
amqp==5.3.1
|
||||||
# via kombu
|
# via kombu
|
||||||
annotated-types==0.7.0
|
annotated-types==0.7.0
|
||||||
# via pydantic
|
# via pydantic
|
||||||
anyio==4.10.0
|
anyio==4.11.0
|
||||||
# via
|
# via
|
||||||
# httpx
|
# httpx
|
||||||
# openai
|
# openai
|
||||||
@@ -22,7 +22,7 @@ argon2-cffi==25.1.0
|
|||||||
# via minio
|
# via minio
|
||||||
argon2-cffi-bindings==25.1.0
|
argon2-cffi-bindings==25.1.0
|
||||||
# via argon2-cffi
|
# via argon2-cffi
|
||||||
asgiref==3.9.1
|
asgiref==3.10.0
|
||||||
# via
|
# via
|
||||||
# django
|
# django
|
||||||
# django-allauth
|
# django-allauth
|
||||||
@@ -32,21 +32,21 @@ asttokens==3.0.0
|
|||||||
# via stack-data
|
# via stack-data
|
||||||
async-timeout==5.0.1
|
async-timeout==5.0.1
|
||||||
# via algoliasearch
|
# via algoliasearch
|
||||||
attrs==25.3.0
|
attrs==25.4.0
|
||||||
# via
|
# via
|
||||||
# aiohttp
|
# aiohttp
|
||||||
# interrogate
|
# interrogate
|
||||||
beautifulsoup4==4.13.5
|
beautifulsoup4==4.14.2
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
billiard==4.2.1
|
billiard==4.2.2
|
||||||
# via celery
|
# via celery
|
||||||
black==25.1.0
|
black==25.9.0
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
boto3==1.40.24
|
boto3==1.40.56
|
||||||
# via
|
# via
|
||||||
# -r ./requirements.in
|
# -r ./requirements.in
|
||||||
# django-bakery
|
# django-bakery
|
||||||
botocore==1.40.24
|
botocore==1.40.56
|
||||||
# via
|
# via
|
||||||
# boto3
|
# boto3
|
||||||
# s3transfer
|
# s3transfer
|
||||||
@@ -56,14 +56,14 @@ bumpversion==0.6.0
|
|||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
celery==5.5.3
|
celery==5.5.3
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
certifi==2025.8.3
|
certifi==2025.10.5
|
||||||
# via
|
# via
|
||||||
# elasticsearch
|
# elasticsearch
|
||||||
# httpcore
|
# httpcore
|
||||||
# httpx
|
# httpx
|
||||||
# minio
|
# minio
|
||||||
# requests
|
# requests
|
||||||
cffi==1.17.1
|
cffi==2.0.0
|
||||||
# via
|
# via
|
||||||
# argon2-cffi-bindings
|
# argon2-cffi-bindings
|
||||||
# cryptography
|
# cryptography
|
||||||
@@ -71,9 +71,9 @@ cfgv==3.4.0
|
|||||||
# via pre-commit
|
# via pre-commit
|
||||||
chardet==5.2.0
|
chardet==5.2.0
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
charset-normalizer==3.4.3
|
charset-normalizer==3.4.4
|
||||||
# via requests
|
# via requests
|
||||||
click==8.2.1
|
click==8.3.0
|
||||||
# via
|
# via
|
||||||
# black
|
# black
|
||||||
# celery
|
# celery
|
||||||
@@ -92,9 +92,9 @@ colorama==0.4.6
|
|||||||
# via interrogate
|
# via interrogate
|
||||||
contourpy==1.3.3
|
contourpy==1.3.3
|
||||||
# via matplotlib
|
# via matplotlib
|
||||||
coverage[toml]==7.10.6
|
coverage[toml]==7.11.0
|
||||||
# via pytest-cov
|
# via pytest-cov
|
||||||
cryptography==45.0.7
|
cryptography==46.0.3
|
||||||
# via
|
# via
|
||||||
# -r ./requirements.in
|
# -r ./requirements.in
|
||||||
# jwcrypto
|
# jwcrypto
|
||||||
@@ -107,11 +107,11 @@ distlib==0.4.0
|
|||||||
# via virtualenv
|
# via virtualenv
|
||||||
distro==1.9.0
|
distro==1.9.0
|
||||||
# via openai
|
# via openai
|
||||||
dj-database-url==2.2.0
|
dj-database-url==3.0.1
|
||||||
# via environs
|
# via environs
|
||||||
dj-email-url==1.0.6
|
dj-email-url==1.0.6
|
||||||
# via environs
|
# via environs
|
||||||
django==4.2.24
|
django==5.2.7
|
||||||
# via
|
# via
|
||||||
# -r ./requirements.in
|
# -r ./requirements.in
|
||||||
# dj-database-url
|
# dj-database-url
|
||||||
@@ -126,13 +126,12 @@ django==4.2.24
|
|||||||
# django-js-asset
|
# django-js-asset
|
||||||
# django-oauth-toolkit
|
# django-oauth-toolkit
|
||||||
# django-redis
|
# django-redis
|
||||||
# django-rest-auth
|
|
||||||
# django-storages
|
# django-storages
|
||||||
# djangorestframework
|
# djangorestframework
|
||||||
# model-bakery
|
# model-bakery
|
||||||
django-admin-env-notice==1.0.1
|
django-admin-env-notice==1.0.1
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
django-allauth[socialaccount]==65.11.1
|
django-allauth[socialaccount]==65.12.1
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
django-anymail[mailgun]==13.1
|
django-anymail[mailgun]==13.1
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
@@ -144,7 +143,7 @@ django-cache-url==3.4.5
|
|||||||
# via environs
|
# via environs
|
||||||
django-click==2.4.1
|
django-click==2.4.1
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
django-cors-headers==4.7.0
|
django-cors-headers==4.9.0
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
django-countries==7.6.1
|
django-countries==7.6.1
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
@@ -156,53 +155,51 @@ django-haystack==3.3.0
|
|||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
django-health-check==3.20.0
|
django-health-check==3.20.0
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
django-imagekit==5.0.0
|
django-imagekit==6.0.0
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
django-js-asset==3.1.2
|
django-js-asset==3.1.2
|
||||||
# via django-mptt
|
# via django-mptt
|
||||||
django-mptt==0.14.0
|
django-mptt==0.14.0
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
django-oauth-toolkit==3.0.1
|
django-oauth-toolkit==3.1.0
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
django-redis==6.0.0
|
django-redis==6.0.0
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
django-rest-auth==0.9.5
|
|
||||||
# via -r ./requirements.in
|
|
||||||
django-storages==1.14.6
|
django-storages==1.14.6
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
django-test-plus==2.3.0
|
django-test-plus==2.3.0
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
django-tracer==0.9.3
|
django-tracer==0.9.3
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
|
django-upgrade==1.29.0
|
||||||
|
# via -r ./requirements.in
|
||||||
django-widget-tweaks==1.5.0
|
django-widget-tweaks==1.5.0
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
djangorestframework==3.16.1
|
djangorestframework==3.16.1
|
||||||
# via
|
# via -r ./requirements.in
|
||||||
# -r ./requirements.in
|
elasticsearch==7.9.1
|
||||||
# django-rest-auth
|
|
||||||
elasticsearch==7.17.12
|
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
environs[django]==14.3.0
|
environs[django]==14.3.0
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
executing==2.2.1
|
executing==2.2.1
|
||||||
# via stack-data
|
# via stack-data
|
||||||
faker==37.6.0
|
faker==37.11.0
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
fastcore==1.8.8
|
fastcore==1.8.13
|
||||||
# via ghapi
|
# via ghapi
|
||||||
filelock==3.19.1
|
filelock==3.20.0
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
fonttools==4.59.2
|
fonttools==4.60.1
|
||||||
# via matplotlib
|
# via matplotlib
|
||||||
frozenlist==1.7.0
|
frozenlist==1.8.0
|
||||||
# via
|
# via
|
||||||
# aiohttp
|
# aiohttp
|
||||||
# aiosignal
|
# aiosignal
|
||||||
fs==2.4.16
|
fs==2.4.16
|
||||||
# via django-bakery
|
# via django-bakery
|
||||||
gevent==25.8.2
|
gevent==25.9.1
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
ghapi==1.0.6
|
ghapi==1.0.8
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
greenlet==3.2.4
|
greenlet==3.2.4
|
||||||
# via
|
# via
|
||||||
@@ -216,19 +213,19 @@ httpcore==1.0.9
|
|||||||
# via httpx
|
# via httpx
|
||||||
httpx==0.28.1
|
httpx==0.28.1
|
||||||
# via openai
|
# via openai
|
||||||
identify==2.6.1
|
identify==2.6.15
|
||||||
# via pre-commit
|
# via pre-commit
|
||||||
idna==3.10
|
idna==3.11
|
||||||
# via
|
# via
|
||||||
# anyio
|
# anyio
|
||||||
# httpx
|
# httpx
|
||||||
# requests
|
# requests
|
||||||
# yarl
|
# yarl
|
||||||
iniconfig==2.1.0
|
iniconfig==2.3.0
|
||||||
# via pytest
|
# via pytest
|
||||||
interrogate==1.7.0
|
interrogate==1.7.0
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
ipython==9.5.0
|
ipython==9.6.0
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
ipython-pygments-lexers==1.1.1
|
ipython-pygments-lexers==1.1.1
|
||||||
# via ipython
|
# via ipython
|
||||||
@@ -236,7 +233,7 @@ itsdangerous==2.2.0
|
|||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
jedi==0.19.2
|
jedi==0.19.2
|
||||||
# via ipython
|
# via ipython
|
||||||
jiter==0.10.0
|
jiter==0.11.1
|
||||||
# via openai
|
# via openai
|
||||||
jmespath==1.0.1
|
jmespath==1.0.1
|
||||||
# via
|
# via
|
||||||
@@ -252,21 +249,21 @@ kiwisolver==1.4.9
|
|||||||
# via matplotlib
|
# via matplotlib
|
||||||
kombu==5.5.4
|
kombu==5.5.4
|
||||||
# via celery
|
# via celery
|
||||||
lxml==6.0.1
|
lxml==6.0.2
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
marshmallow==4.0.1
|
marshmallow==4.0.1
|
||||||
# via environs
|
# via environs
|
||||||
matplotlib==3.10.6
|
matplotlib==3.10.7
|
||||||
# via wordcloud
|
# via wordcloud
|
||||||
matplotlib-inline==0.1.7
|
matplotlib-inline==0.1.7
|
||||||
# via ipython
|
# via ipython
|
||||||
minio==7.2.16
|
minio==7.2.18
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
mistletoe==1.4.0
|
mistletoe==1.5.0
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
model-bakery==1.20.5
|
model-bakery==1.20.5
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
multidict==6.6.4
|
multidict==6.7.0
|
||||||
# via
|
# via
|
||||||
# aiohttp
|
# aiohttp
|
||||||
# yarl
|
# yarl
|
||||||
@@ -274,7 +271,7 @@ mypy-extensions==1.1.0
|
|||||||
# via black
|
# via black
|
||||||
nodeenv==1.9.1
|
nodeenv==1.9.1
|
||||||
# via pre-commit
|
# via pre-commit
|
||||||
numpy==2.3.2
|
numpy==2.3.4
|
||||||
# via
|
# via
|
||||||
# contourpy
|
# contourpy
|
||||||
# matplotlib
|
# matplotlib
|
||||||
@@ -283,9 +280,9 @@ oauthlib==3.3.1
|
|||||||
# via
|
# via
|
||||||
# django-allauth
|
# django-allauth
|
||||||
# django-oauth-toolkit
|
# django-oauth-toolkit
|
||||||
openai==1.102.0
|
openai==2.6.0
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
packaging==24.1
|
packaging==25.0
|
||||||
# via
|
# via
|
||||||
# black
|
# black
|
||||||
# django-haystack
|
# django-haystack
|
||||||
@@ -303,13 +300,13 @@ pexpect==4.9.0
|
|||||||
# via ipython
|
# via ipython
|
||||||
pilkit==3.0
|
pilkit==3.0
|
||||||
# via django-imagekit
|
# via django-imagekit
|
||||||
pillow==11.3.0
|
pillow==12.0.0
|
||||||
# via
|
# via
|
||||||
# -r ./requirements.in
|
# -r ./requirements.in
|
||||||
# matplotlib
|
# matplotlib
|
||||||
# pilkit
|
# pilkit
|
||||||
# wordcloud
|
# wordcloud
|
||||||
platformdirs==4.4.0
|
platformdirs==4.5.0
|
||||||
# via
|
# via
|
||||||
# black
|
# black
|
||||||
# virtualenv
|
# virtualenv
|
||||||
@@ -323,13 +320,13 @@ prompt-toolkit==3.0.52
|
|||||||
# via
|
# via
|
||||||
# click-repl
|
# click-repl
|
||||||
# ipython
|
# ipython
|
||||||
propcache==0.3.2
|
propcache==0.4.1
|
||||||
# via
|
# via
|
||||||
# aiohttp
|
# aiohttp
|
||||||
# yarl
|
# yarl
|
||||||
psycogreen==1.0.2
|
psycogreen==1.0.2
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
psycopg2-binary==2.9.10
|
psycopg2-binary==2.9.11
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
ptyprocess==0.7.0
|
ptyprocess==0.7.0
|
||||||
# via pexpect
|
# via pexpect
|
||||||
@@ -337,33 +334,33 @@ pure-eval==0.2.3
|
|||||||
# via stack-data
|
# via stack-data
|
||||||
py==1.11.0
|
py==1.11.0
|
||||||
# via interrogate
|
# via interrogate
|
||||||
pycparser==2.22
|
pycparser==2.23
|
||||||
# via cffi
|
# via cffi
|
||||||
pycryptodome==3.23.0
|
pycryptodome==3.23.0
|
||||||
# via minio
|
# via minio
|
||||||
pydantic==2.11.9
|
pydantic==2.12.3
|
||||||
# via
|
# via
|
||||||
# algoliasearch
|
# algoliasearch
|
||||||
# openai
|
# openai
|
||||||
pydantic-core==2.33.2
|
pydantic-core==2.41.4
|
||||||
# via pydantic
|
# via pydantic
|
||||||
pygments==2.19.2
|
pygments==2.19.2
|
||||||
# via
|
# via
|
||||||
# ipython
|
# ipython
|
||||||
# ipython-pygments-lexers
|
# ipython-pygments-lexers
|
||||||
# pytest
|
# pytest
|
||||||
pyjwt[crypto]==2.9.0
|
pyjwt[crypto]==2.10.1
|
||||||
# via
|
# via
|
||||||
# django-allauth
|
# django-allauth
|
||||||
# redis
|
# redis
|
||||||
pyparsing==3.2.0
|
pyparsing==3.2.5
|
||||||
# via matplotlib
|
# via matplotlib
|
||||||
pytest==8.4.2
|
pytest==8.4.2
|
||||||
# via
|
# via
|
||||||
# -r ./requirements.in
|
# -r ./requirements.in
|
||||||
# pytest-cov
|
# pytest-cov
|
||||||
# pytest-django
|
# pytest-django
|
||||||
pytest-cov==6.2.1
|
pytest-cov==7.0.0
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
pytest-django==4.11.1
|
pytest-django==4.11.1
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
@@ -378,9 +375,11 @@ python-dotenv==1.1.1
|
|||||||
# via environs
|
# via environs
|
||||||
python-frontmatter==1.1.0
|
python-frontmatter==1.1.0
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
python-json-logger==3.3.0
|
python-json-logger==4.0.0
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
pyyaml==6.0.2
|
pytokens==0.2.0
|
||||||
|
# via black
|
||||||
|
pyyaml==6.0.3
|
||||||
# via
|
# via
|
||||||
# pre-commit
|
# pre-commit
|
||||||
# python-frontmatter
|
# python-frontmatter
|
||||||
@@ -399,26 +398,24 @@ requests==2.32.5
|
|||||||
# responses
|
# responses
|
||||||
responses==0.25.8
|
responses==0.25.8
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
s3transfer==0.13.1
|
s3transfer==0.14.0
|
||||||
# via boto3
|
# via boto3
|
||||||
setuptools==80.9.0
|
setuptools==80.9.0
|
||||||
# via
|
# via
|
||||||
# fs
|
# fs
|
||||||
# zope-event
|
# zope-event
|
||||||
# zope-interface
|
|
||||||
six==1.17.0
|
six==1.17.0
|
||||||
# via
|
# via
|
||||||
# django-bakery
|
# django-bakery
|
||||||
# django-rest-auth
|
|
||||||
# fs
|
# fs
|
||||||
# python-dateutil
|
# python-dateutil
|
||||||
slack-sdk==3.36.0
|
slack-sdk==3.37.0
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
sniffio==1.3.1
|
sniffio==1.3.1
|
||||||
# via
|
# via
|
||||||
# anyio
|
# anyio
|
||||||
# openai
|
# openai
|
||||||
soupsieve==2.6
|
soupsieve==2.8
|
||||||
# via beautifulsoup4
|
# via beautifulsoup4
|
||||||
sqlparse==0.5.3
|
sqlparse==0.5.3
|
||||||
# via django
|
# via django
|
||||||
@@ -428,6 +425,8 @@ structlog==25.4.0
|
|||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
tabulate==0.9.0
|
tabulate==0.9.0
|
||||||
# via interrogate
|
# via interrogate
|
||||||
|
tokenize-rt==6.2.0
|
||||||
|
# via django-upgrade
|
||||||
tqdm==4.67.1
|
tqdm==4.67.1
|
||||||
# via openai
|
# via openai
|
||||||
traitlets==5.14.3
|
traitlets==5.14.3
|
||||||
@@ -439,7 +438,6 @@ typing-extensions==4.15.0
|
|||||||
# aiosignal
|
# aiosignal
|
||||||
# anyio
|
# anyio
|
||||||
# beautifulsoup4
|
# beautifulsoup4
|
||||||
# dj-database-url
|
|
||||||
# django-countries
|
# django-countries
|
||||||
# ipython
|
# ipython
|
||||||
# jwcrypto
|
# jwcrypto
|
||||||
@@ -448,7 +446,7 @@ typing-extensions==4.15.0
|
|||||||
# pydantic
|
# pydantic
|
||||||
# pydantic-core
|
# pydantic-core
|
||||||
# typing-inspection
|
# typing-inspection
|
||||||
typing-inspection==0.4.1
|
typing-inspection==0.4.2
|
||||||
# via pydantic
|
# via pydantic
|
||||||
tzdata==2025.2
|
tzdata==2025.2
|
||||||
# via
|
# via
|
||||||
@@ -456,7 +454,7 @@ tzdata==2025.2
|
|||||||
# kombu
|
# kombu
|
||||||
unidecode==1.4.0
|
unidecode==1.4.0
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
urllib3==1.26.20
|
urllib3==2.5.0
|
||||||
# via
|
# via
|
||||||
# algoliasearch
|
# algoliasearch
|
||||||
# botocore
|
# botocore
|
||||||
@@ -465,26 +463,26 @@ urllib3==1.26.20
|
|||||||
# minio
|
# minio
|
||||||
# requests
|
# requests
|
||||||
# responses
|
# responses
|
||||||
uv==0.8.15
|
uv==0.9.5
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
vine==5.1.0
|
vine==5.1.0
|
||||||
# via
|
# via
|
||||||
# amqp
|
# amqp
|
||||||
# celery
|
# celery
|
||||||
# kombu
|
# kombu
|
||||||
virtualenv==20.34.0
|
virtualenv==20.35.3
|
||||||
# via pre-commit
|
# via pre-commit
|
||||||
wcwidth==0.2.13
|
wcwidth==0.2.14
|
||||||
# via prompt-toolkit
|
# via prompt-toolkit
|
||||||
wheel==0.45.1
|
wheel==0.45.1
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
whitenoise==6.9.0
|
whitenoise==6.11.0
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
wordcloud==1.9.4
|
wordcloud==1.9.4
|
||||||
# via -r ./requirements.in
|
# via -r ./requirements.in
|
||||||
yarl==1.20.1
|
yarl==1.22.0
|
||||||
# via aiohttp
|
# via aiohttp
|
||||||
zope-event==5.1.1
|
zope-event==6.0
|
||||||
# via gevent
|
# via gevent
|
||||||
zope-interface==7.2
|
zope-interface==8.0.1
|
||||||
# via gevent
|
# via gevent
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddConstraint(
|
migrations.AddConstraint(
|
||||||
model_name="thread",
|
model_name="thread",
|
||||||
constraint=models.CheckConstraint(
|
constraint=models.CheckConstraint(
|
||||||
check=django.db.models.lookups.GreaterThanOrEqual(
|
condition=django.db.models.lookups.GreaterThanOrEqual(
|
||||||
django.db.models.functions.comparison.Cast(
|
django.db.models.functions.comparison.Cast(
|
||||||
"last_update_ts", output_field=models.FloatField()
|
"last_update_ts", output_field=models.FloatField()
|
||||||
),
|
),
|
||||||
@@ -172,7 +172,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddConstraint(
|
migrations.AddConstraint(
|
||||||
model_name="channelupdategap",
|
model_name="channelupdategap",
|
||||||
constraint=models.CheckConstraint(
|
constraint=models.CheckConstraint(
|
||||||
check=django.db.models.lookups.GreaterThan(
|
condition=django.db.models.lookups.GreaterThan(
|
||||||
django.db.models.functions.comparison.Cast(
|
django.db.models.functions.comparison.Cast(
|
||||||
"newest_message_ts", output_field=models.FloatField()
|
"newest_message_ts", output_field=models.FloatField()
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ class ChannelUpdateGap(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
constraints = [
|
constraints = [
|
||||||
models.CheckConstraint(
|
models.CheckConstraint(
|
||||||
check=models.lookups.GreaterThan(
|
condition=models.lookups.GreaterThan(
|
||||||
models.functions.Cast(
|
models.functions.Cast(
|
||||||
"newest_message_ts", output_field=models.FloatField()
|
"newest_message_ts", output_field=models.FloatField()
|
||||||
),
|
),
|
||||||
@@ -110,7 +110,7 @@ class Thread(models.Model):
|
|||||||
unique_together = [("channel", "thread_ts")]
|
unique_together = [("channel", "thread_ts")]
|
||||||
constraints = [
|
constraints = [
|
||||||
models.CheckConstraint(
|
models.CheckConstraint(
|
||||||
check=models.lookups.GreaterThanOrEqual(
|
condition=models.lookups.GreaterThanOrEqual(
|
||||||
models.functions.Cast(
|
models.functions.Cast(
|
||||||
"last_update_ts", output_field=models.FloatField()
|
"last_update_ts", output_field=models.FloatField()
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
from .models import User
|
from .models import User
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(User)
|
||||||
class EmailUserAdmin(UserAdmin):
|
class EmailUserAdmin(UserAdmin):
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
(None, {"fields": ("email", "password")}),
|
(None, {"fields": ("email", "password")}),
|
||||||
@@ -59,6 +60,3 @@ class EmailUserAdmin(UserAdmin):
|
|||||||
"claimed",
|
"claimed",
|
||||||
)
|
)
|
||||||
search_fields = ("email", "display_name__unaccent")
|
search_fields = ("email", "display_name__unaccent")
|
||||||
|
|
||||||
|
|
||||||
admin.site.register(User, EmailUserAdmin)
|
|
||||||
|
|||||||
@@ -330,7 +330,7 @@ class UserAvatar(TemplateView):
|
|||||||
):
|
):
|
||||||
# check if user is on pages that require CSRF but don't require login
|
# check if user is on pages that require CSRF but don't require login
|
||||||
# (auth pages where anonymous users submit forms)
|
# (auth pages where anonymous users submit forms)
|
||||||
referer = self.request.META.get("HTTP_REFERER", "")
|
referer = self.request.headers.get("referer", "")
|
||||||
current_path = self.request.path
|
current_path = self.request.path
|
||||||
|
|
||||||
# paths that anonymous users can access and have forms
|
# paths that anonymous users can access and have forms
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime, timezone
|
||||||
from django.contrib.syndication.views import Feed
|
from django.contrib.syndication.views import Feed
|
||||||
from django.utils.feedgenerator import Atom1Feed
|
from django.utils.feedgenerator import Atom1Feed
|
||||||
from django.utils.timezone import make_aware, utc
|
from django.utils.timezone import make_aware
|
||||||
|
|
||||||
from core.models import RenderedContent
|
from core.models import RenderedContent
|
||||||
from .models import Version
|
from .models import Version
|
||||||
@@ -24,7 +24,7 @@ class RSSVersionFeed(Feed):
|
|||||||
release_date = item.release_date
|
release_date = item.release_date
|
||||||
if release_date:
|
if release_date:
|
||||||
datetime_obj = datetime.combine(release_date, datetime.min.time())
|
datetime_obj = datetime.combine(release_date, datetime.min.time())
|
||||||
aware_datetime_obj = make_aware(datetime_obj, timezone=utc)
|
aware_datetime_obj = make_aware(datetime_obj, timezone=timezone.utc)
|
||||||
return aware_datetime_obj
|
return aware_datetime_obj
|
||||||
|
|
||||||
def item_description(self, item):
|
def item_description(self, item):
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime, timezone
|
||||||
from django.utils.timezone import make_aware, utc
|
from django.utils.timezone import make_aware
|
||||||
from ..feeds import RSSVersionFeed, AtomVersionFeed
|
from ..feeds import RSSVersionFeed, AtomVersionFeed
|
||||||
|
|
||||||
|
|
||||||
@@ -16,7 +16,8 @@ def test_items(version, old_version):
|
|||||||
def test_item_pubdate(version):
|
def test_item_pubdate(version):
|
||||||
feed = RSSVersionFeed()
|
feed = RSSVersionFeed()
|
||||||
expected_datetime = make_aware(
|
expected_datetime = make_aware(
|
||||||
datetime.combine(version.release_date, datetime.min.time()), timezone=utc
|
datetime.combine(version.release_date, datetime.min.time()),
|
||||||
|
timezone=timezone.utc,
|
||||||
)
|
)
|
||||||
assert feed.item_pubdate(version) == expected_datetime
|
assert feed.item_pubdate(version) == expected_datetime
|
||||||
|
|
||||||
@@ -51,6 +52,7 @@ def test_items_atom(version, old_version):
|
|||||||
def test_item_pubdate_atom(version):
|
def test_item_pubdate_atom(version):
|
||||||
feed = AtomVersionFeed()
|
feed = AtomVersionFeed()
|
||||||
expected_datetime = make_aware(
|
expected_datetime = make_aware(
|
||||||
datetime.combine(version.release_date, datetime.min.time()), timezone=utc
|
datetime.combine(version.release_date, datetime.min.time()),
|
||||||
|
timezone=timezone.utc,
|
||||||
)
|
)
|
||||||
assert feed.item_pubdate(version) == expected_datetime
|
assert feed.item_pubdate(version) == expected_datetime
|
||||||
|
|||||||
Reference in New Issue
Block a user