Compare commits

...

4 Commits

Author SHA1 Message Date
Phin Wolkwitz
ec87f1ca49 Update model index migrations (Meta.index_together removed in Django 5.2) 2026-02-05 15:33:29 +01:00
Phin Wolkwitz
8a428538b8 Fix migration monkeypatching 2026-02-05 14:42:16 +01:00
Phin Wolkwitz
64101c502f Update pytest filterwarnings, sort imports 2026-02-05 14:42:16 +01:00
Phin Wolkwitz
b820567cd2 Update django to 5.2, initial fixes 2026-02-05 14:42:16 +01:00
13 changed files with 86 additions and 68 deletions

View File

@@ -22,7 +22,7 @@ classifiers = [
"Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.11",
"Framework :: Django :: 4.2", "Framework :: Django :: 5.2",
] ]
dependencies = [ dependencies = [
@@ -36,7 +36,7 @@ dependencies = [
"css-inline==0.19.*", "css-inline==0.19.*",
"defusedcsv>=1.1.0", "defusedcsv>=1.1.0",
"dnspython==2.*", "dnspython==2.*",
"Django[argon2]==4.2.*,>=4.2.26", "Django[argon2]==5.2.*",
"django-bootstrap3==26.1", "django-bootstrap3==26.1",
"django-compressor==4.6.0", "django-compressor==4.6.0",
"django-countries==8.2.*", "django-countries==8.2.*",

View File

@@ -36,8 +36,9 @@ from django.core.management.commands.makemigrations import Command as Parent
from ._migrations import monkeypatch_migrations from ._migrations import monkeypatch_migrations
monkeypatch_migrations()
class Command(Parent): class Command(Parent):
pass
def handle(self, *args, **kwargs):
monkeypatch_migrations()
return super().handle(*args, **kwargs)

View File

@@ -41,16 +41,20 @@ class Migration(migrations.Migration):
name='datetime', name='datetime',
field=models.DateTimeField(), field=models.DateTimeField(),
), ),
migrations.AlterIndexTogether( migrations.AddIndex(
name='logentry', 'logentry',
index_together={('datetime', 'id')}, models.Index(fields=('datetime', 'id'), name="pretixbase__datetim_b1fe5a_idx"),
), ),
migrations.AlterIndexTogether( migrations.AddIndex(
name='order', 'order',
index_together={('datetime', 'id'), ('last_modified', 'id')}, models.Index(fields=["datetime", "id"], name="pretixbase__datetim_66aff0_idx"),
), ),
migrations.AlterIndexTogether( migrations.AddIndex(
name='transaction', 'order',
index_together={('datetime', 'id')}, models.Index(fields=["last_modified", "id"], name="pretixbase__last_mo_4ebf8b_idx"),
),
migrations.AddIndex(
'transaction',
models.Index(fields=('datetime', 'id'), name="pretixbase__datetim_b20405_idx"),
), ),
] ]

View File

@@ -61,7 +61,10 @@ class Migration(migrations.Migration):
options={ options={
'ordering': ('identifier', 'type', 'organizer'), 'ordering': ('identifier', 'type', 'organizer'),
'unique_together': {('identifier', 'type', 'organizer')}, 'unique_together': {('identifier', 'type', 'organizer')},
'index_together': {('identifier', 'type', 'organizer'), ('updated', 'id')}, 'indexes': [
models.Index(fields=('identifier', 'type', 'organizer'), name='reusable_medium_organizer_index'),
models.Index(fields=('updated', 'id'), name="pretixbase__updated_093277_idx")
],
}, },
bases=(models.Model, pretix.base.models.base.LoggingMixin), bases=(models.Model, pretix.base.models.base.LoggingMixin),
), ),

View File

@@ -9,31 +9,6 @@ class Migration(migrations.Migration):
] ]
operations = [ operations = [
migrations.RenameIndex(
model_name="logentry",
new_name="pretixbase__datetim_b1fe5a_idx",
old_fields=("datetime", "id"),
),
migrations.RenameIndex(
model_name="order",
new_name="pretixbase__datetim_66aff0_idx",
old_fields=("datetime", "id"),
),
migrations.RenameIndex(
model_name="order",
new_name="pretixbase__last_mo_4ebf8b_idx",
old_fields=("last_modified", "id"),
),
migrations.RenameIndex(
model_name="reusablemedium",
new_name="pretixbase__updated_093277_idx",
old_fields=("updated", "id"),
),
migrations.RenameIndex(
model_name="transaction",
new_name="pretixbase__datetim_b20405_idx",
old_fields=("datetime", "id"),
),
migrations.AlterField( migrations.AlterField(
model_name="attendeeprofile", model_name="attendeeprofile",
name="id", name="id",

View File

@@ -1,6 +1,6 @@
# Generated by Django 4.2.10 on 2024-04-02 15:16 # Generated by Django 4.2.10 on 2024-04-02 15:16
from django.db import migrations from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
@@ -10,8 +10,8 @@ class Migration(migrations.Migration):
] ]
operations = [ operations = [
migrations.AlterIndexTogether( migrations.RemoveIndex(
name="reusablemedium", "reusablemedium",
index_together=set(), 'reusable_medium_organizer_index',
), ),
] ]

View File

@@ -88,7 +88,7 @@ class LogEntry(models.Model):
class Meta: class Meta:
ordering = ('-datetime', '-id') ordering = ('-datetime', '-id')
indexes = [models.Index(fields=["datetime", "id"])] indexes = [models.Index(fields=["datetime", "id"], name="pretixbase__datetim_b1fe5a_idx")]
def display(self): def display(self):
from pretix.base.logentrytype_registry import log_entry_types from pretix.base.logentrytype_registry import log_entry_types

View File

@@ -122,7 +122,7 @@ class ReusableMedium(LoggedModel):
class Meta: class Meta:
unique_together = (("identifier", "type", "organizer"),) unique_together = (("identifier", "type", "organizer"),)
indexes = [ indexes = [
models.Index(fields=("updated", "id")), models.Index(fields=("updated", "id"), name="pretixbase__updated_093277_idx"),
] ]
ordering = "identifier", "type", "organizer" ordering = "identifier", "type", "organizer"

View File

@@ -337,8 +337,8 @@ class Order(LockModel, LoggedModel):
verbose_name_plural = _("Orders") verbose_name_plural = _("Orders")
ordering = ("-datetime", "-pk") ordering = ("-datetime", "-pk")
indexes = [ indexes = [
models.Index(fields=["datetime", "id"]), models.Index(fields=["datetime", "id"], name="pretixbase__datetim_66aff0_idx"),
models.Index(fields=["last_modified", "id"]), models.Index(fields=["last_modified", "id"], name="pretixbase__last_mo_4ebf8b_idx"),
] ]
constraints = [ constraints = [
models.UniqueConstraint(fields=["organizer", "code"], name="order_organizer_code_uniq"), models.UniqueConstraint(fields=["organizer", "code"], name="order_organizer_code_uniq"),
@@ -3102,7 +3102,7 @@ class Transaction(models.Model):
class Meta: class Meta:
ordering = 'datetime', 'pk' ordering = 'datetime', 'pk'
indexes = [ indexes = [
models.Index(fields=['datetime', 'id']) models.Index(fields=['datetime', 'id'], name="pretixbase__datetim_b20405_idx")
] ]
def save(self, *args, **kwargs): def save(self, *args, **kwargs):

View File

@@ -60,23 +60,25 @@ def _populate_app_cache():
def get_defining_app(o): def get_defining_app(o):
# If sentry packed this in a wrapper, unpack that # If sentry packed this in a wrapper, unpack that
if "sentry" in o.__module__: module = getattr(o, "__module__", None)
if module and "sentry" in module:
o = o.__wrapped__ o = o.__wrapped__
if hasattr(o, "__mocked_app"): if hasattr(o, "__mocked_app"):
return o.__mocked_app return o.__mocked_app
# Find the Django application this belongs to # Find the Django application this belongs to
searchpath = o.__module__ searchpath = module or getattr(o.__class__, "__module__", None) or ""
# Core modules are always active # Core modules are always active
if any(searchpath.startswith(cm) for cm in settings.CORE_MODULES): if searchpath and any(searchpath.startswith(cm) for cm in settings.CORE_MODULES):
return 'CORE' return 'CORE'
if not app_cache: if not app_cache:
_populate_app_cache() _populate_app_cache()
while True: app = None
while searchpath:
app = app_cache.get(searchpath) app = app_cache.get(searchpath)
if "." not in searchpath or app: if "." not in searchpath or app:
break break
@@ -157,7 +159,11 @@ class PluginSignal(Generic[T], django.dispatch.Signal):
if not app_cache: if not app_cache:
_populate_app_cache() _populate_app_cache()
for receiver in self._sorted_receivers(sender): for receiver in self._sorted_receivers(sender)[0]:
if self._is_receiver_active(sender, receiver):
response = receiver(signal=self, sender=sender, **named)
responses.append((receiver, response))
for receiver in self._sorted_receivers(sender)[1]:
if self._is_receiver_active(sender, receiver): if self._is_receiver_active(sender, receiver):
response = receiver(signal=self, sender=sender, **named) response = receiver(signal=self, sender=sender, **named)
responses.append((receiver, response)) responses.append((receiver, response))
@@ -179,7 +185,11 @@ class PluginSignal(Generic[T], django.dispatch.Signal):
if not app_cache: if not app_cache:
_populate_app_cache() _populate_app_cache()
for receiver in self._sorted_receivers(sender): for receiver in self._sorted_receivers(sender)[0]:
if self._is_receiver_active(sender, receiver):
named[chain_kwarg_name] = response
response = receiver(signal=self, sender=sender, **named)
for receiver in self._sorted_receivers(sender)[1]:
if self._is_receiver_active(sender, receiver): if self._is_receiver_active(sender, receiver):
named[chain_kwarg_name] = response named[chain_kwarg_name] = response
response = receiver(signal=self, sender=sender, **named) response = receiver(signal=self, sender=sender, **named)
@@ -204,7 +214,15 @@ class PluginSignal(Generic[T], django.dispatch.Signal):
if not app_cache: if not app_cache:
_populate_app_cache() _populate_app_cache()
for receiver in self._sorted_receivers(sender): for receiver in self._sorted_receivers(sender)[0]:
if self._is_receiver_active(sender, receiver):
try:
response = receiver(signal=self, sender=sender, **named)
except Exception as err:
responses.append((receiver, err))
else:
responses.append((receiver, response))
for receiver in self._sorted_receivers(sender)[1]:
if self._is_receiver_active(sender, receiver): if self._is_receiver_active(sender, receiver):
try: try:
response = receiver(signal=self, sender=sender, **named) response = receiver(signal=self, sender=sender, **named)
@@ -215,16 +233,33 @@ class PluginSignal(Generic[T], django.dispatch.Signal):
return responses return responses
def _sorted_receivers(self, sender): def _sorted_receivers(self, sender):
orig_list = self._live_receivers(sender) orig_list_sync = self._live_receivers(sender)[0]
sorted_list = sorted( # todo: _live_receivers changed return value from [] to [], []
orig_list, orig_list_async = self._live_receivers(sender)[1]
def _receiver_module(receiver):
return getattr(receiver, "__module__", receiver.__class__.__module__)
def _receiver_name(receiver):
return getattr(receiver, "__name__", receiver.__class__.__name__)
sorted_list_sync = sorted(
orig_list_sync,
key=lambda receiver: ( key=lambda receiver: (
0 if any(receiver.__module__.startswith(m) for m in settings.CORE_MODULES) else 1, 0 if any(_receiver_module(receiver).startswith(m) for m in settings.CORE_MODULES) else 1,
receiver.__module__, _receiver_module(receiver),
receiver.__name__, _receiver_name(receiver),
) )
) )
return sorted_list sorted_list_async = sorted(
orig_list_async,
key=lambda receiver: (
0 if any(_receiver_module(receiver).startswith(m) for m in settings.CORE_MODULES) else 1,
_receiver_module(receiver),
_receiver_name(receiver),
)
)
return sorted_list_sync, sorted_list_async
class EventPluginSignal(PluginSignal[Event]): class EventPluginSignal(PluginSignal[Event]):

View File

@@ -49,7 +49,7 @@ from django.views.decorators.cache import cache_page
from django.views.decorators.gzip import gzip_page from django.views.decorators.gzip import gzip_page
from django.views.decorators.http import condition from django.views.decorators.http import condition
from django.views.i18n import ( from django.views.i18n import (
JavaScriptCatalog, get_formats, js_catalog_template, JavaScriptCatalog, builtin_template_path, get_formats,
) )
from lxml import html from lxml import html
@@ -170,7 +170,8 @@ def generate_widget_js(version, lang):
'September', 'October', 'November', 'December' 'September', 'October', 'November', 'December'
) )
catalog = dict((k, v) for k, v in catalog.items() if k.startswith('widget\u0004') or k in str_wl) catalog = dict((k, v) for k, v in catalog.items() if k.startswith('widget\u0004') or k in str_wl)
template = Engine().from_string(js_catalog_template) with builtin_template_path("i18n_catalog.js").open(encoding="utf-8") as fh:
template = Engine().from_string(fh.read())
context = Context({ context = Context({
'catalog_str': indent(json.dumps( 'catalog_str': indent(json.dumps(
catalog, sort_keys=True, indent=2)) if catalog else None, catalog, sort_keys=True, indent=2)) if catalog else None,

View File

@@ -530,6 +530,7 @@ X_FRAME_OPTIONS = 'DENY'
# URL settings # URL settings
ROOT_URLCONF = 'pretix.multidomain.maindomain_urlconf' ROOT_URLCONF = 'pretix.multidomain.maindomain_urlconf'
FORMS_URLFIELD_ASSUME_HTTPS = True # transitional for django 6.0
WSGI_APPLICATION = 'pretix.wsgi.application' WSGI_APPLICATION = 'pretix.wsgi.application'

View File

@@ -23,9 +23,7 @@ filterwarnings =
error error
ignore:.*invalid escape sequence.*: ignore:.*invalid escape sequence.*:
ignore:The 'warn' method is deprecated:DeprecationWarning ignore:The 'warn' method is deprecated:DeprecationWarning
ignore::django.utils.deprecation.RemovedInDjango51Warning:django.core.files.storage ignore::django.utils.deprecation.RemovedInDjango60Warning:
ignore:.*index_together.*:django.utils.deprecation.RemovedInDjango51Warning:
ignore:.*get_storage_class.*:django.utils.deprecation.RemovedInDjango51Warning:compressor
ignore:.*This signal will soon be only available for plugins that declare to be organizer-level.*:DeprecationWarning: ignore:.*This signal will soon be only available for plugins that declare to be organizer-level.*:DeprecationWarning:
ignore::DeprecationWarning:mt940 ignore::DeprecationWarning:mt940
ignore::DeprecationWarning:cbor2 ignore::DeprecationWarning:cbor2