diff --git a/pyproject.toml b/pyproject.toml index c45107d45e..725132adaa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,7 @@ classifiers = [ "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", - "Framework :: Django :: 4.2", + "Framework :: Django :: 5.2", ] dependencies = [ @@ -36,7 +36,7 @@ dependencies = [ "css-inline==0.20.*", "defusedcsv>=1.1.0", "dnspython==2.*", - "Django[argon2]==4.2.*,>=4.2.26", + "Django[argon2]==5.2.*", "django-bootstrap3==26.1", "django-compressor==4.6.0", "django-countries==8.2.*", diff --git a/src/pretix/base/signals.py b/src/pretix/base/signals.py index a5682576e4..fcaab61f86 100644 --- a/src/pretix/base/signals.py +++ b/src/pretix/base/signals.py @@ -60,23 +60,25 @@ def _populate_app_cache(): def get_defining_app(o): # 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__ if hasattr(o, "__mocked_app"): return o.__mocked_app # Find the Django application this belongs to - searchpath = o.__module__ + searchpath = module or getattr(o.__class__, "__module__", None) or "" # 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' if not app_cache: _populate_app_cache() - while True: + app = None + while searchpath: app = app_cache.get(searchpath) if "." not in searchpath or app: break @@ -157,7 +159,11 @@ class PluginSignal(Generic[T], django.dispatch.Signal): if not 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): response = receiver(signal=self, sender=sender, **named) responses.append((receiver, response)) @@ -179,7 +185,11 @@ class PluginSignal(Generic[T], django.dispatch.Signal): if not 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): named[chain_kwarg_name] = response response = receiver(signal=self, sender=sender, **named) @@ -204,7 +214,15 @@ class PluginSignal(Generic[T], django.dispatch.Signal): if not 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): try: response = receiver(signal=self, sender=sender, **named) @@ -215,16 +233,33 @@ class PluginSignal(Generic[T], django.dispatch.Signal): return responses def _sorted_receivers(self, sender): - orig_list = self._live_receivers(sender) - sorted_list = sorted( - orig_list, + orig_list_sync = self._live_receivers(sender)[0] + # todo: _live_receivers changed return value from [] to [], [] + 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: ( - 0 if any(receiver.__module__.startswith(m) for m in settings.CORE_MODULES) else 1, - receiver.__module__, - receiver.__name__, + 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 + 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]): diff --git a/src/pretix/presale/views/widget.py b/src/pretix/presale/views/widget.py index 9de49b067b..3d9d275058 100644 --- a/src/pretix/presale/views/widget.py +++ b/src/pretix/presale/views/widget.py @@ -49,7 +49,7 @@ from django.views.decorators.cache import cache_page from django.views.decorators.gzip import gzip_page from django.views.decorators.http import condition from django.views.i18n import ( - JavaScriptCatalog, get_formats, js_catalog_template, + JavaScriptCatalog, get_formats, builtin_template_path, ) from lxml import html @@ -170,7 +170,8 @@ def generate_widget_js(version, lang): 'September', 'October', 'November', 'December' ) 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({ 'catalog_str': indent(json.dumps( catalog, sort_keys=True, indent=2)) if catalog else None, diff --git a/src/pretix/settings.py b/src/pretix/settings.py index 508b185b33..21b54a8337 100644 --- a/src/pretix/settings.py +++ b/src/pretix/settings.py @@ -534,6 +534,7 @@ X_FRAME_OPTIONS = 'DENY' # URL settings ROOT_URLCONF = 'pretix.multidomain.maindomain_urlconf' +FORMS_URLFIELD_ASSUME_HTTPS = True # transitional for django 6.0 WSGI_APPLICATION = 'pretix.wsgi.application'