From 40018b093721f2f8beb9e746eedb79309fcf0697 Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Thu, 11 Mar 2021 23:11:31 +0100 Subject: [PATCH] more stuff --- src/pretix/base/signals.py | 9 ++++----- src/pretix/control/views/__init__.py | 4 ++-- src/pretix/helpers/models.py | 4 +++- src/pretix/plugins/badges/exporters.py | 2 +- src/pretix/plugins/checkinlists/exporters.py | 16 ++++++++++------ src/pretix/plugins/ticketoutputpdf/exporters.py | 6 +++--- src/tests/control/test_auth.py | 14 +++++++------- src/tests/plugins/test_checkinlist.py | 2 -- 8 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/pretix/base/signals.py b/src/pretix/base/signals.py index a3331c54c8..7beeaf62d6 100644 --- a/src/pretix/base/signals.py +++ b/src/pretix/base/signals.py @@ -266,8 +266,7 @@ multiple events. Receivers should return a subclass of pretix.base.exporter.Base The ``sender`` keyword argument will contain an organizer. """ -validate_order = EventPluginSignal( -) +validate_order = EventPluginSignal() """ Arguments: ``payment_provider``, ``positions``, ``email``, ``locale``, ``invoice_address``, ``meta_info`` @@ -413,10 +412,10 @@ the deletion of the order. As with all event-plugin signals, the ``sender`` keyword argument will contain the event. """ -checkin_created = EventPluginSignal( - providing_args=["checkin"], -) +checkin_created = EventPluginSignal() """ +Arguments: ``checkin`` + This signal is sent out every time a check-in is created (i.e. an order position is marked as checked in). It is not send if the position was already checked in and is force-checked-in a second time. The check-in object is given as the first argument diff --git a/src/pretix/control/views/__init__.py b/src/pretix/control/views/__init__.py index 71e3465b78..fef8c66623 100644 --- a/src/pretix/control/views/__init__.py +++ b/src/pretix/control/views/__init__.py @@ -1,4 +1,4 @@ -import collections +import collections.abc import warnings from django.core.paginator import ( @@ -65,7 +65,7 @@ class PaginationMixin: return ctx -class LargeResultSetPage(collections.Sequence): +class LargeResultSetPage(collections.abc.Sequence): def __init__(self, object_list, number, paginator): self.object_list = object_list diff --git a/src/pretix/helpers/models.py b/src/pretix/helpers/models.py index f40d3a0059..234e0a4f91 100644 --- a/src/pretix/helpers/models.py +++ b/src/pretix/helpers/models.py @@ -1,5 +1,6 @@ import copy +from django.core.files import File from django.db import models @@ -16,7 +17,8 @@ def modelcopy(obj: models.Model): n = obj.__class__() for f in obj._meta.fields: val = getattr(obj, f.name) - if isinstance(val, models.Model): + print(f, f.name, val) + if isinstance(val, (models.Model, File)): setattr(n, f.name, copy.copy(val)) else: setattr(n, f.name, copy.deepcopy(val)) diff --git a/src/pretix/plugins/badges/exporters.py b/src/pretix/plugins/badges/exporters.py index 699becb089..1202c5fec7 100644 --- a/src/pretix/plugins/badges/exporters.py +++ b/src/pretix/plugins/badges/exporters.py @@ -274,7 +274,7 @@ class BadgeExporter(BaseExporter): resolved_name=Coalesce('attendee_name_parts', 'addon_to__attendee_name_parts', 'order__invoice_address__name_parts') ).order_by( - f'resolved_name_part__{part}' + f'resolved_name__{part}' ) outbuffer = render_pdf(self.event, qs, OPTIONS[form_data.get('rendering', 'one')]) diff --git a/src/pretix/plugins/checkinlists/exporters.py b/src/pretix/plugins/checkinlists/exporters.py index b0b52fc413..8e4496470a 100644 --- a/src/pretix/plugins/checkinlists/exporters.py +++ b/src/pretix/plugins/checkinlists/exporters.py @@ -4,7 +4,7 @@ from datetime import datetime, time, timedelta import dateutil.parser from django import forms from django.db.models import ( - Case, Exists, Max, OuterRef, Q, Subquery, Value, When, + Case, Exists, Max, OuterRef, Q, Subquery, Value, When, F, ) from django.db.models.functions import Coalesce, NullIf from django.urls import reverse @@ -178,13 +178,17 @@ class CheckInListMixin(BaseExporter): part = sort[5:] qs = qs.annotate( resolved_name=Case( - When(attendee_name_cached__ne='', then='attendee_name_parts'), - When(addon_to__attendee_name_cached__isnull=False, addon_to__attendee_name_cached__ne='', then='addon_to__attendee_name_parts'), - default='order__invoice_address__name_parts', - ) + When(attendee_name_cached__isnull=False, attendee_name_cached__ne='', + then='attendee_name_parts'), + When(addon_to__attendee_name_cached__isnull=False, addon_to__attendee_name_cached__ne='', + then='addon_to__attendee_name_parts'), + default='order__invoice_address__name_parts', + ), + ).annotate( + resolved_name_part=F(f'resolved_name__{part}') ).order_by( *o, - f'resolved_name_part__{part}' + f'resolved_name__{part}' ) if form_data.get('attention_only'): diff --git a/src/pretix/plugins/ticketoutputpdf/exporters.py b/src/pretix/plugins/ticketoutputpdf/exporters.py index 9917b1a692..108f840df1 100644 --- a/src/pretix/plugins/ticketoutputpdf/exporters.py +++ b/src/pretix/plugins/ticketoutputpdf/exporters.py @@ -36,10 +36,10 @@ class AllTicketsPDF(BaseExporter): choices=[ ('name', _('Attendee name')), ('code', _('Order code')), - ] + [ + ] + ([ ('name:{}'.format(k), _('Attendee name: {part}').format(part=label)) for k, label, w in name_scheme['fields'] - ], + ] if name_scheme else []) )), ] ) @@ -67,7 +67,7 @@ class AllTicketsPDF(BaseExporter): qs = qs.annotate( resolved_name=Coalesce('attendee_name_parts', 'addon_to__attendee_name_parts', 'order__invoice_address__name_parts') ).order_by( - f'resolved_name_part__{part}' + f'resolved_name__{part}' ) o = PdfTicketOutput(Event.objects.none()) diff --git a/src/tests/control/test_auth.py b/src/tests/control/test_auth.py index dd2ab71e5d..2caef92bea 100644 --- a/src/tests/control/test_auth.py +++ b/src/tests/control/test_auth.py @@ -1,5 +1,5 @@ import time -from datetime import date, timedelta +from datetime import datetime, timedelta import pytest from django.conf import settings @@ -314,7 +314,7 @@ class Login2FAFormTest(TestCase): d = TOTPDevice.objects.create(user=self.user, name='test') totp = TOTP(d.bin_key, d.step, d.t0, d.digits, d.drift) totp.time = time.time() - response = self.client.post('/control/login/2fa'.format(d.pk), { + response = self.client.post('/control/login/2fa', { 'token': str(totp.token() + 2) }) self.assertEqual(response.status_code, 302) @@ -326,7 +326,7 @@ class Login2FAFormTest(TestCase): d = TOTPDevice.objects.create(user=self.user, name='test') totp = TOTP(d.bin_key, d.step, d.t0, d.digits, d.drift) totp.time = time.time() - response = self.client.post('/control/login/2fa?next=/control/events/'.format(d.pk), { + response = self.client.post('/control/login/2fa?next=/control/events/', { 'token': str(totp.token()) }) self.assertEqual(response.status_code, 302) @@ -350,7 +350,7 @@ class Login2FAFormTest(TestCase): response = self.client.get('/control/login/2fa') assert 'token' in response.content.decode() - response = self.client.post('/control/login/2fa'.format(d.pk), { + response = self.client.post('/control/login/2fa', { 'token': '{"response": "true"}' }) self.assertEqual(response.status_code, 302) @@ -372,7 +372,7 @@ class Login2FAFormTest(TestCase): response = self.client.get('/control/login/2fa') assert 'token' in response.content.decode() - response = self.client.post('/control/login/2fa'.format(d.pk), { + response = self.client.post('/control/login/2fa', { 'token': '{"response": "true"}' }) self.assertEqual(response.status_code, 302) @@ -493,8 +493,8 @@ class PasswordRecoveryFormTest(TestCase): def test_recovery_expired_token(self): class Mocked(PasswordResetTokenGenerator): - def _today(self): - return date.today() - timedelta(settings.PASSWORD_RESET_TIMEOUT_DAYS + 1) + def _now(self): + return datetime.now() - timedelta(seconds=settings.PASSWORD_RESET_TIMEOUT + 3600) generator = Mocked() token = generator.make_token(self.user) diff --git a/src/tests/plugins/test_checkinlist.py b/src/tests/plugins/test_checkinlist.py index fd94a98a6e..68371ceca9 100644 --- a/src/tests/plugins/test_checkinlist.py +++ b/src/tests/plugins/test_checkinlist.py @@ -119,8 +119,6 @@ def test_csv_order_by_name_parts(event): # noqa @pytest.mark.django_db def test_csv_order_by_inherited_name_parts(event): # noqa - from django.conf import settings - with scope(organizer=event.organizer): OrderPosition.objects.filter(attendee_name_cached__icontains="Andrea").delete() op = OrderPosition.objects.get()