Experimental organizer-level plugin implementation

This commit is contained in:
Mira Weller
2024-09-23 18:45:33 +02:00
parent e395834811
commit 2ecf81bdfe
5 changed files with 47 additions and 19 deletions
+2 -2
View File
@@ -742,8 +742,8 @@ class Event(EventMixin, LoggedModel):
Returns the names of the plugins activated for this event as a list. Returns the names of the plugins activated for this event as a list.
""" """
if self.plugins is None: if self.plugins is None:
return [] return self.organizer.get_plugins()
return self.plugins.split(",") return self.plugins.split(",") + self.organizer.get_plugins()
def get_cache(self): def get_cache(self):
""" """
+12
View File
@@ -91,6 +91,10 @@ class Organizer(LoggedModel):
verbose_name=_("Short form"), verbose_name=_("Short form"),
unique=True unique=True
) )
plugins = models.TextField(
null=True, blank=True,
verbose_name=_("Plugins"),
)
class Meta: class Meta:
verbose_name = _("Organizer") verbose_name = _("Organizer")
@@ -119,6 +123,14 @@ class Organizer(LoggedModel):
""" """
self.settings.cookie_consent = True self.settings.cookie_consent = True
def get_plugins(self):
"""
Returns the names of the plugins activated for this organizer as a list.
"""
if self.plugins is None:
return []
return self.plugins.split(",")
def get_cache(self): def get_cache(self):
""" """
Returns an :py:class:`ObjectRelatedCache` object. This behaves equivalent to Returns an :py:class:`ObjectRelatedCache` object. This behaves equivalent to
+29 -14
View File
@@ -96,22 +96,27 @@ def is_receiver_active(sender, receiver):
return is_app_active(sender, app) return is_app_active(sender, app)
class EventPluginSignal(django.dispatch.Signal): def is_plugin_host(sender):
return hasattr(sender, 'get_plugins')
class PluginSignal(django.dispatch.Signal):
""" """
This is an extension to Django's built-in signals which differs in a way that it sends This is an extension to Django's built-in signals which differs in a way that it sends
out it's events only to receivers which belong to plugins that are enabled for the given out it's events only to receivers which belong to plugins that are enabled for the given
Event. Event.
""" """
def send(self, sender: Event, **named) -> List[Tuple[Callable, Any]]: def send(self, sender, **named) -> List[Tuple[Callable, Any]]:
""" """
Send signal from sender to all connected receivers that belong to Send signal from sender to all connected receivers that belong to
plugins enabled for the given Event. plugins enabled for the given Event.
sender is required to be an instance of ``pretix.base.models.Event``. sender is required to be a plugin host (an object with a `get_plugins` method),
for example a ``pretix.base.models.Event``.
""" """
if sender and not isinstance(sender, Event): if sender and not is_plugin_host(sender):
raise ValueError("Sender needs to be an event.") raise ValueError("Sender needs to be a plugin host.")
responses = [] responses = []
if not self.receivers or self.sender_receivers_cache.get(sender) is NO_RECEIVERS: if not self.receivers or self.sender_receivers_cache.get(sender) is NO_RECEIVERS:
@@ -126,16 +131,17 @@ class EventPluginSignal(django.dispatch.Signal):
responses.append((receiver, response)) responses.append((receiver, response))
return responses return responses
def send_chained(self, sender: Event, chain_kwarg_name, **named) -> List[Tuple[Callable, Any]]: def send_chained(self, sender, chain_kwarg_name, **named) -> List[Tuple[Callable, Any]]:
""" """
Send signal from sender to all connected receivers. The return value of the first receiver Send signal from sender to all connected receivers. The return value of the first receiver
will be used as the keyword argument specified by ``chain_kwarg_name`` in the input to the will be used as the keyword argument specified by ``chain_kwarg_name`` in the input to the
second receiver and so on. The return value of the last receiver is returned by this method. second receiver and so on. The return value of the last receiver is returned by this method.
sender is required to be an instance of ``pretix.base.models.Event``. sender is required to be a plugin host (an object with a `get_plugins` method),
for example a ``pretix.base.models.Event``.
""" """
if sender and not isinstance(sender, Event): if sender and not is_plugin_host(sender):
raise ValueError("Sender needs to be an event.") raise ValueError("Sender needs to be a plugin host.")
response = named.get(chain_kwarg_name) response = named.get(chain_kwarg_name)
if not self.receivers or self.sender_receivers_cache.get(sender) is NO_RECEIVERS: if not self.receivers or self.sender_receivers_cache.get(sender) is NO_RECEIVERS:
@@ -150,16 +156,17 @@ class EventPluginSignal(django.dispatch.Signal):
response = receiver(signal=self, sender=sender, **named) response = receiver(signal=self, sender=sender, **named)
return response return response
def send_robust(self, sender: Event, **named) -> List[Tuple[Callable, Any]]: def send_robust(self, sender, **named) -> List[Tuple[Callable, Any]]:
""" """
Send signal from sender to all connected receivers. If a receiver raises an exception Send signal from sender to all connected receivers. If a receiver raises an exception
instead of returning a value, the exception is included as the result instead of instead of returning a value, the exception is included as the result instead of
stopping the response chain at the offending receiver. stopping the response chain at the offending receiver.
sender is required to be an instance of ``pretix.base.models.Event``. sender is required to be a plugin host (an object with a `get_plugins` method),
for example a ``pretix.base.models.Event``.
""" """
if sender and not isinstance(sender, Event): if sender and not is_plugin_host(sender):
raise ValueError("Sender needs to be an event.") raise ValueError("Sender needs to be a plugin host.")
responses = [] responses = []
if ( if (
@@ -194,6 +201,14 @@ class EventPluginSignal(django.dispatch.Signal):
return sorted_list return sorted_list
class OrganizerPluginSignal(PluginSignal):
pass
class EventPluginSignal(PluginSignal):
pass
class GlobalSignal(django.dispatch.Signal): class GlobalSignal(django.dispatch.Signal):
def send_chained(self, sender: Event, chain_kwarg_name, **named) -> List[Tuple[Callable, Any]]: def send_chained(self, sender: Event, chain_kwarg_name, **named) -> List[Tuple[Callable, Any]]:
""" """
@@ -245,7 +260,7 @@ class Registry:
return self.by_key.get(key).get(value, (None, None)) return self.by_key.get(key).get(value, (None, None))
class EventPluginRegistry(Registry): class PluginRegistry(Registry):
def __init__(self, keys): def __init__(self, keys):
super().__init__({"plugin": lambda o: get_defining_app(o), **keys}) super().__init__({"plugin": lambda o: get_defining_app(o), **keys})
+2 -2
View File
@@ -34,7 +34,7 @@
from django.dispatch import Signal from django.dispatch import Signal
from pretix.base.signals import DeprecatedSignal, EventPluginSignal from pretix.base.signals import DeprecatedSignal, EventPluginSignal, OrganizerPluginSignal
html_page_start = Signal() html_page_start = Signal()
""" """
@@ -221,7 +221,7 @@ Deprecated signal, no longer works. We just keep the definition so old plugins d
break the installation. break the installation.
""" """
nav_organizer = Signal() nav_organizer = OrganizerPluginSignal()
""" """
Arguments: 'organizer', 'request' Arguments: 'organizer', 'request'
@@ -26,8 +26,9 @@ from django.dispatch import receiver
from django.template.loader import get_template from django.template.loader import get_template
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from pretix.base.logentrytypes import EventLogEntryType
from pretix.base.models import Event, SalesChannel from pretix.base.models import Event, SalesChannel
from pretix.base.models.log import EventLogEntryType, log_entry_types from pretix.base.models.log import log_entry_types
from pretix.base.signals import ( # NOQA: legacy import from pretix.base.signals import ( # NOQA: legacy import
EventPluginSignal, event_copy_data, item_copy_data, layout_text_variables, EventPluginSignal, event_copy_data, item_copy_data, layout_text_variables,
logentry_display, logentry_object_link, register_data_exporters, logentry_display, logentry_object_link, register_data_exporters,