mirror of
https://github.com/pretix/pretix.git
synced 2026-06-11 01:25:13 +00:00
general cleanup
This commit is contained in:
@@ -25,9 +25,7 @@ import os
|
||||
import warnings
|
||||
from collections import namedtuple
|
||||
from dataclasses import dataclass
|
||||
from typing import (
|
||||
TYPE_CHECKING, Iterable, List, Literal, Tuple, Union,
|
||||
)
|
||||
from typing import TYPE_CHECKING, Iterable, List, Literal, Tuple, Union
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from dateutil import parser
|
||||
@@ -40,9 +38,12 @@ from django.utils.timezone import now
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from pretix.base.forms.widgets import OptionAttrsSelect
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .models import Event, Order, SubEvent
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class BaseChoice:
|
||||
base: Literal["event", "order", "order.subevents"]
|
||||
@@ -103,6 +104,7 @@ SUBEVENT_BASE_CHOICES = [
|
||||
x for x in BASE_CHOICES if x.base == 'order.subevents'
|
||||
]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class RelativeDate:
|
||||
"""
|
||||
@@ -173,8 +175,8 @@ class RelativeDate:
|
||||
raise ValueError("The selected modifier does not exist")
|
||||
elif choice.base == "event" and isinstance(base, SubEvent):
|
||||
event = base.event
|
||||
base_date = (getattr(base, self.attribute) or
|
||||
getattr(base.event, self.attribute) or
|
||||
base_date = (getattr(base, choice.attribute) or
|
||||
getattr(base.event, choice.attribute) or
|
||||
base.date_from)
|
||||
elif choice.base == "event" and isinstance(base, Event):
|
||||
event = base
|
||||
@@ -342,8 +344,9 @@ reldatetimeparts = namedtuple('reldatetimeparts', (
|
||||
reldatetimeparts.indizes = reldatetimeparts(*range(9))
|
||||
|
||||
|
||||
def _get_choices(choices: List[BaseChoice])->List[Tuple[str, Promise]]:
|
||||
return [(c.key, c.text) for c in choices]
|
||||
def _get_choices(base_choices: List[BaseChoice]) -> List[Tuple[str, Promise]]:
|
||||
return [(c.key, c.text) for c in base_choices]
|
||||
|
||||
|
||||
def _get_choice_validation_obj(choices: List[BaseChoice]):
|
||||
return {c.key: {"data-supports-before": c.supports_before, "data-supports-after": c.supports_after} for c in choices}
|
||||
@@ -373,14 +376,22 @@ class RelativeDateTimeWidget(forms.MultiWidget):
|
||||
attrs={'placeholder': lazy(placeholder_datetime_format, str), 'class': 'datetimepicker'}
|
||||
),
|
||||
rel_days_number=forms.NumberInput(),
|
||||
rel_mins_relationto=OptionAttrsSelect(attrs={'data-relative-choice': True}, choices=self.base_choices, option_attrs=_get_choice_validation_obj(self.base_choices)),
|
||||
rel_mins_relationto=OptionAttrsSelect(
|
||||
attrs={'data-relative-choice': True},
|
||||
choices=self.base_choices,
|
||||
option_attrs=_get_choice_validation_obj(self.base_choices)
|
||||
),
|
||||
rel_days_timeofday=forms.TimeInput(
|
||||
attrs={'placeholder': lazy(placeholder_time_format, str), 'class': 'timepickerfield'}
|
||||
),
|
||||
rel_mins_number=forms.NumberInput(),
|
||||
rel_days_relationto=OptionAttrsSelect(attrs={'data-relative-choice': True}, choices=self.base_choices, option_attrs=_get_choice_validation_obj(self.base_choices)),
|
||||
rel_days_relationto=OptionAttrsSelect(
|
||||
attrs={'data-relative-choice': True},
|
||||
choices=self.base_choices,
|
||||
option_attrs=_get_choice_validation_obj(self.base_choices)
|
||||
),
|
||||
rel_mins_relation=forms.Select(attrs={'data-relation-choice': True}, choices=BEFORE_AFTER_CHOICE),
|
||||
rel_days_relation=forms.Select(attrs={'data-relation-choice': True},choices=BEFORE_AFTER_CHOICE),
|
||||
rel_days_relation=forms.Select(attrs={'data-relation-choice': True}, choices=BEFORE_AFTER_CHOICE),
|
||||
)
|
||||
super().__init__(widgets=widgets, *args, **kwargs)
|
||||
|
||||
@@ -473,14 +484,17 @@ class RelativeDateTimeField(forms.MultiValueField):
|
||||
_warn_skips = (os.path.dirname(__file__),)
|
||||
warnings.warn(
|
||||
"Please prefix limit_choices with the base the attributes refer to, for example event__date_from",
|
||||
skip_file_prefixes=_warn_skips)
|
||||
skip_file_prefixes=_warn_skips
|
||||
)
|
||||
|
||||
possible_choices = [c for c in possible_choices if
|
||||
# new base case as we want limit_choices to be expressed as base__attribute
|
||||
(c.key in limit) or
|
||||
# fallback for old event based entries
|
||||
# if the base is an event, then using only attribute is fine
|
||||
(c.base == "event" and c.attribute in limit)]
|
||||
possible_choices = [
|
||||
c for c in possible_choices if
|
||||
# new base case as we want limit_choices to be expressed as base__attribute
|
||||
(c.key in limit) or
|
||||
# fallback for old event based entries
|
||||
# if the base is an event, then using only attribute is fine
|
||||
(c.base == "event" and c.attribute in limit)
|
||||
]
|
||||
|
||||
if not kwargs.get('required', True):
|
||||
status_choices.insert(0, ('unset', _('Not set')))
|
||||
@@ -490,7 +504,7 @@ class RelativeDateTimeField(forms.MultiValueField):
|
||||
fields = reldatetimeparts(
|
||||
status=forms.ChoiceField(
|
||||
choices=status_choices,
|
||||
required=True
|
||||
required=True,
|
||||
),
|
||||
absolute=forms.DateTimeField(
|
||||
required=False
|
||||
@@ -500,7 +514,7 @@ class RelativeDateTimeField(forms.MultiValueField):
|
||||
),
|
||||
rel_mins_relationto=forms.ChoiceField(
|
||||
choices=choices,
|
||||
required=False
|
||||
required=False,
|
||||
),
|
||||
rel_days_timeofday=forms.TimeField(
|
||||
required=False,
|
||||
@@ -510,7 +524,7 @@ class RelativeDateTimeField(forms.MultiValueField):
|
||||
),
|
||||
rel_days_relationto=forms.ChoiceField(
|
||||
choices=choices,
|
||||
required=False
|
||||
required=False,
|
||||
),
|
||||
rel_mins_relation=forms.ChoiceField(
|
||||
choices=BEFORE_AFTER_CHOICE,
|
||||
@@ -655,7 +669,7 @@ class RelativeDateWidget(RelativeDateTimeWidget):
|
||||
status="relative",
|
||||
absolute=None,
|
||||
rel_days_number=value.data.days,
|
||||
rel_days_relationto=value.data.base_date_name,
|
||||
rel_days_relationto=value.data.key,
|
||||
rel_days_relation="after" if value.data.is_after else "before"
|
||||
)
|
||||
|
||||
@@ -677,10 +691,16 @@ class RelativeDateField(RelativeDateTimeField):
|
||||
if not kwargs.get('required', True):
|
||||
status_choices.insert(0, ('unset', _('Not set')))
|
||||
|
||||
choices = [(c.key, c.text) for c in EVENT_BASE_CHOICES]
|
||||
self.relative_to_order = kwargs.pop('relative_to_order', False)
|
||||
self.relative_to_subevent_positions = kwargs.pop('relative_to_subevent_positions', False)
|
||||
|
||||
possible_choices = copy.deepcopy(EVENT_BASE_CHOICES)
|
||||
if self.relative_to_order:
|
||||
choices += [(c.key, c.text) for c in ORDER_BASE_CHOICES]
|
||||
possible_choices.extend(ORDER_BASE_CHOICES)
|
||||
if self.relative_to_subevent_positions:
|
||||
possible_choices.extend(SUBEVENT_BASE_CHOICES)
|
||||
|
||||
choices = _get_choices(possible_choices)
|
||||
|
||||
fields = reldateparts(
|
||||
status=forms.ChoiceField(
|
||||
@@ -695,15 +715,16 @@ class RelativeDateField(RelativeDateTimeField):
|
||||
),
|
||||
rel_days_relationto=forms.ChoiceField(
|
||||
choices=choices,
|
||||
required=False
|
||||
required=False,
|
||||
),
|
||||
rel_days_relation=forms.ChoiceField(
|
||||
choices=BEFORE_AFTER_CHOICE,
|
||||
required=False
|
||||
),
|
||||
)
|
||||
|
||||
if 'widget' not in kwargs:
|
||||
kwargs['widget'] = RelativeDateWidget(status_choices=status_choices, base_choices=choices)
|
||||
kwargs['widget'] = RelativeDateWidget(status_choices=status_choices, base_choices=possible_choices)
|
||||
forms.MultiValueField.__init__(
|
||||
self, fields=fields, require_all_fields=False, *args, **kwargs
|
||||
)
|
||||
@@ -714,6 +735,8 @@ class RelativeDateField(RelativeDateTimeField):
|
||||
]
|
||||
if self.relative_to_order:
|
||||
choices += [(c.key, c.text) for c in ORDER_BASE_CHOICES]
|
||||
if self.relative_to_subevent_positions and event.has_subevents:
|
||||
choices += [(c.key, c.text) for c in SUBEVENT_BASE_CHOICES]
|
||||
self.widget.widgets[reldateparts.indizes.rel_days_relationto].choices = choices
|
||||
|
||||
def compress(self, data_list):
|
||||
|
||||
@@ -141,7 +141,6 @@ def test_unserialize_backwards_compatibility():
|
||||
|
||||
# keeping the test for the old from_string_format to ensure that we don't break anything
|
||||
rdw = RelativeDateWrapper.from_string('RELDATE/1/-/date_from/')
|
||||
x = RelativeDate(days=1, time=None, base_date_name='date_from', minutes=None)
|
||||
assert rdw.data == RelativeDate(days=1, time=None, base_date_name='date_from', minutes=None)
|
||||
|
||||
# keeping the test for the old from_string_format to ensure that we don't break anything
|
||||
@@ -152,6 +151,7 @@ def test_unserialize_backwards_compatibility():
|
||||
rdw = RelativeDateWrapper.from_string('RELDATE/minutes/60/date_from/')
|
||||
assert rdw.data == RelativeDate(days=0, time=None, base_date_name='date_from', minutes=60)
|
||||
|
||||
|
||||
def test_backwards_compatibility():
|
||||
# the data model of RelativeDate had to be extended to support other models as relation target
|
||||
# previously only:
|
||||
@@ -163,8 +163,6 @@ def test_backwards_compatibility():
|
||||
# where valid values for the fourth slot (base_date_names) of the serialized form.
|
||||
# the relationship in this case always pointed at event
|
||||
# so any preexisting base_date_names without __ should continue to work and upgrade to event__{old_base_date_name}
|
||||
|
||||
|
||||
d = datetime(2017, 12, 25, 10, 0, 0, tzinfo=TOKYO)
|
||||
rdw = RelativeDateWrapper.from_string(d.isoformat())
|
||||
assert rdw.data == d
|
||||
@@ -190,6 +188,7 @@ def test_backwards_compatibility():
|
||||
with pytest.raises(TypeError):
|
||||
RelativeDateWrapper.from_string('RELDATE/1/-/expires/')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_relative_to_order(event):
|
||||
with scope(organizer=event.organizer):
|
||||
|
||||
Reference in New Issue
Block a user