Integrate hierarkey package (#460)

This commit is contained in:
Raphael Michel
2017-04-10 18:11:21 +02:00
committed by GitHub
parent 43121a08bd
commit 984d5c716b
17 changed files with 144 additions and 601 deletions

View File

@@ -1,14 +1,10 @@
import logging
import i18nfield.forms
from django import forms
from django.core.files import File
from django.core.files.storage import default_storage
from django.core.files.uploadedfile import UploadedFile
from django.forms.models import ModelFormMetaclass
from django.utils import six
from django.utils.crypto import get_random_string
from django.utils.translation import ugettext_lazy as _
from hierarkey.forms import HierarkeyForm
from pretix.base.models import Event
@@ -49,67 +45,22 @@ class I18nInlineFormSet(i18nfield.forms.I18nInlineFormSet):
super().__init__(*args, **kwargs)
class SettingsForm(i18nfield.forms.I18nForm):
"""
This form is meant to be used for modifying EventSettings or OrganizerSettings. It takes
care of loading the current values of the fields and saving the field inputs to the
settings storage. It also deals with setting the available languages for internationalized
fields.
:param obj: The event or organizer object which should be used for the settings storage
"""
BOOL_CHOICES = (
('False', _('disabled')),
('True', _('enabled')),
)
class SettingsForm(i18nfield.forms.I18nFormMixin, HierarkeyForm):
def __init__(self, *args, **kwargs):
self.obj = kwargs.pop('obj', None)
self.obj = kwargs.get('obj', None)
self.locales = kwargs.pop('locales', None)
kwargs['attribute_name'] = 'settings'
kwargs['locales'] = self.obj.settings.get('locales') if self.obj else self.locales
kwargs['initial'] = self.obj.settings.freeze()
super().__init__(*args, **kwargs)
def save(self):
"""
Performs the save operation
"""
for name, field in self.fields.items():
value = self.cleaned_data[name]
if isinstance(value, UploadedFile):
# Delete old file
fname = self.obj.settings.get(name, as_type=File)
if fname:
try:
default_storage.delete(fname.name)
except OSError:
logger.error('Deleting file %s failed.' % fname.name)
# Create new file
nonce = get_random_string(length=8)
if isinstance(self.obj, Event):
fname = '%s/%s/%s.%s.%s' % (
self.obj.organizer.slug, self.obj.slug, name, nonce, value.name.split('.')[-1]
)
else:
fname = '%s/%s.%s.%s' % (self.obj.slug, name, nonce, value.name.split('.')[-1])
newname = default_storage.save(fname, value)
value._name = newname
self.obj.settings.set(name, value)
elif isinstance(value, File):
# file is unchanged
continue
elif isinstance(field, forms.FileField):
# file is deleted
fname = self.obj.settings.get(name, as_type=File)
if fname:
try:
default_storage.delete(fname.name)
except OSError:
logger.error('Deleting file %s failed.' % fname.name)
del self.obj.settings[name]
elif value is None:
del self.obj.settings[name]
elif self.obj.settings.get(name, as_type=type(value)) != value:
self.obj.settings.set(name, value)
def get_new_filename(self, name: str) -> str:
nonce = get_random_string(length=8)
if isinstance(self.obj, Event):
fname = '%s/%s/%s.%s.%s' % (
self.obj.organizer.slug, self.obj.slug, name, nonce, name.split('.')[-1]
)
else:
fname = '%s/%s.%s.%s' % (self.obj.slug, name, nonce, name.split('.')[-1])
return fname

View File

@@ -0,0 +1,59 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2017-04-09 16:51
from __future__ import unicode_literals
import django.db.models.deletion
from django.db import migrations, models
def migrate_global_settings(apps, schema_editor):
GlobalSetting = apps.get_model('pretixbase', 'GlobalSetting')
GlobalSettingsObject_SettingsStore = apps.get_model('pretixbase', 'GlobalSettingsObject_SettingsStore')
l = []
for s in GlobalSetting.objects.all():
l.append(GlobalSettingsObject_SettingsStore(key=s.key, value=s.value))
GlobalSettingsObject_SettingsStore.objects.bulk_create(l)
class Migration(migrations.Migration):
dependencies = [
('pretixbase', '0052_auto_20170324_1506'),
]
operations = [
migrations.RenameModel(
old_name='EventSetting',
new_name='Event_SettingsStore',
),
migrations.RenameModel(
old_name='OrganizerSetting',
new_name='Organizer_SettingsStore',
),
migrations.CreateModel(
name='GlobalSettingsObject_SettingsStore',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('key', models.CharField(db_index=True, max_length=255)),
('value', models.TextField()),
],
),
migrations.RunPython(
migrate_global_settings, migrations.RunPython.noop
),
migrations.DeleteModel(
name='GlobalSetting',
),
migrations.AlterField(
model_name='event_settingsstore',
name='object',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='_settings_objects', to='pretixbase.Event'),
),
migrations.AlterField(
model_name='organizer_settingsstore',
name='object',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='_settings_objects', to='pretixbase.Organizer'),
),
]

View File

@@ -1,8 +1,9 @@
from ..settings import GlobalSettingsObject_SettingsStore
from .auth import U2FDevice, User
from .base import CachedFile, LoggedModel, cachedfile_name
from .checkin import Checkin
from .event import (
Event, EventLock, EventPermission, EventSetting, RequiredAction,
Event, Event_SettingsStore, EventLock, EventPermission, RequiredAction,
generate_invite_token,
)
from .invoices import Invoice, InvoiceLine, invoice_filename
@@ -17,6 +18,6 @@ from .orders import (
cachedcombinedticket_name, cachedticket_name, generate_position_secret,
generate_secret,
)
from .organizer import Organizer, OrganizerPermission, OrganizerSetting
from .organizer import Organizer, Organizer_SettingsStore, OrganizerPermission
from .vouchers import Voucher
from .waitinglist import WaitingListEntry

View File

@@ -11,22 +11,21 @@ from django.core.validators import RegexValidator
from django.db import models
from django.template.defaultfilters import date as _date
from django.utils.crypto import get_random_string
from django.utils.functional import cached_property
from django.utils.timezone import make_aware, now
from django.utils.translation import ugettext_lazy as _
from i18nfield.fields import I18nCharField
from pretix.base.email import CustomSMTPBackend
from pretix.base.models.base import LoggedModel
from pretix.base.settings import SettingsProxy
from pretix.base.validators import EventSlugBlacklistValidator
from pretix.helpers.daterange import daterange
from ..settings import settings_hierarkey
from .auth import User
from .organizer import Organizer
from .settings import EventSetting
@settings_hierarkey.add(parent_field='organizer', cache_namespace='event')
class Event(LoggedModel):
"""
This model represents an event. An event is anything you can buy
@@ -183,17 +182,6 @@ class Event(LoggedModel):
return ObjectRelatedCache(self)
@cached_property
def settings(self) -> SettingsProxy:
"""
Returns an object representing this event's settings.
"""
try:
return SettingsProxy(self, type=EventSetting, parent=self.organizer)
except Organizer.DoesNotExist:
# Should only happen when creating new events
return SettingsProxy(self, type=EventSetting)
@property
def presale_has_ended(self):
if self.presale_end and now() > self.presale_end:
@@ -290,7 +278,7 @@ class Event(LoggedModel):
o.question = q
o.save()
for s in EventSetting.objects.filter(object=other):
for s in other.settings._objects.all():
s.object = self
s.pk = None
if s.value.startswith('file://'):

View File

@@ -3,17 +3,16 @@ import string
from django.core.validators import RegexValidator
from django.db import models
from django.utils.crypto import get_random_string
from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _
from pretix.base.models.base import LoggedModel
from pretix.base.settings import SettingsProxy
from pretix.base.validators import OrganizerSlugBlacklistValidator
from ..settings import settings_hierarkey
from .auth import User
from .settings import OrganizerSetting
@settings_hierarkey.add(cache_namespace='organizer')
class Organizer(LoggedModel):
"""
This model represents an entity organizing events, e.g. a company, institution,
@@ -59,14 +58,6 @@ class Organizer(LoggedModel):
self.get_cache().clear()
return obj
@cached_property
def settings(self) -> SettingsProxy:
"""
Returns an object representing this organizer's settings
"""
from pretix.base.settings import GlobalSettingsObject
return SettingsProxy(self, type=OrganizerSetting, parent=GlobalSettingsObject())
def get_cache(self) -> "pretix.base.cache.ObjectRelatedCache":
"""
Returns an :py:class:`ObjectRelatedCache` object. This behaves equivalent to

View File

@@ -1,34 +0,0 @@
from django.db import models
class GlobalSetting(models.Model):
"""
A global setting is a key-value setting which can be set for a
pretix instance. It will be inherited by all events and organizers.
It is filled via the register_global_settings signal.
"""
key = models.CharField(max_length=255, primary_key=True)
value = models.TextField()
def __init__(self, *args, object=None, **kwargs):
super().__init__(*args, **kwargs)
class OrganizerSetting(models.Model):
"""
An organizer setting is a key-value setting which can be set for an
organizer. It will be inherited by the events of this organizer
"""
object = models.ForeignKey('Organizer', related_name='setting_objects', on_delete=models.CASCADE)
key = models.CharField(max_length=255)
value = models.TextField()
class EventSetting(models.Model):
"""
An event setting is a key-value setting which can be set for a
specific event
"""
object = models.ForeignKey('Event', related_name='setting_objects', on_delete=models.CASCADE)
key = models.CharField(max_length=255)
value = models.TextField()

View File

@@ -54,7 +54,7 @@ def assign_automatically(event_id: int, user_id: int=None):
@receiver(signal=periodic_task)
def process_waitinglist(sender, **kwargs):
qs = Event.objects.prefetch_related('setting_objects', 'organizer__setting_objects').select_related('organizer')
qs = Event.objects.prefetch_related('_settings_objects', 'organizer___settings_objects').select_related('organizer')
for e in qs:
if e.settings.waiting_list_enabled and e.settings.waiting_list_auto:
assign_automatically.apply_async(args=(e.pk,))

View File

@@ -1,19 +1,14 @@
import decimal
import json
from datetime import date, datetime, time
from datetime import datetime
from django.core.cache import cache
from typing import Any, Dict, Optional
import dateutil.parser
from django.conf import settings
from django.core.files import File
from django.core.files.storage import default_storage
from django.db.models import Model
from django.utils.translation import ugettext_noop
from hierarkey.models import GlobalSettingsBase, Hierarkey
from i18nfield.strings import LazyI18nString
from pretix.base.models.settings import GlobalSetting
from typing import Any
DEFAULTS = {
'max_items_per_order': {
@@ -382,194 +377,27 @@ Your {event} team"""))
}
}
settings_hierarkey = Hierarkey(attribute_name='settings')
class SettingsProxy:
"""
This object allows convenient access to settings stored in the
EventSettings/OrganizerSettings database model. It exposes all settings as
properties and it will do all the nasty inheritance and defaults stuff for
you.
"""
for k, v in DEFAULTS.items():
settings_hierarkey.add_default(k, v['default'], v['type'])
def __init__(self, obj: Model, parent: Optional[Model]=None, type=None):
self._obj = obj
self._parent = parent
self._cached_obj = None
self._write_cached_obj = None
self._type = type
def _cache(self) -> Dict[str, Any]:
if self._cached_obj is None:
self._cached_obj = cache.get_or_set(
'settings_{}_{}'.format(self._obj.settings_namespace, self._obj.pk),
lambda: {s.key: s.value for s in self._obj.setting_objects.all()},
timeout=1800
)
return self._cached_obj
def i18n_uns(v):
try:
return LazyI18nString(json.loads(v))
except ValueError:
return LazyI18nString(str(v))
def _write_cache(self) -> Dict[str, Any]:
if self._write_cached_obj is None:
self._write_cached_obj = {
s.key: s for s in self._obj.setting_objects.all()
}
return self._write_cached_obj
def _flush(self) -> None:
self._cached_obj = None
self._write_cached_obj = None
self._flush_external_cache()
settings_hierarkey.add_type(LazyI18nString,
serialize=lambda s: json.dumps(s.data),
unserialize=i18n_uns)
def _flush_external_cache(self):
cache.delete('settings_{}_{}'.format(self._obj.settings_namespace, self._obj.pk))
def freeze(self) -> dict:
"""
Returns a dictionary of all settings set for this object, including
any default values of its parents or hardcoded in pretix.
"""
settings = {}
for key, v in DEFAULTS.items():
settings[key] = self._unserialize(v['default'], v['type'])
if self._parent:
settings.update(self._parent.settings.freeze())
for key in self._cache():
settings[key] = self.get(key)
return settings
def _unserialize(self, value: str, as_type: type, binary_file=False) -> Any:
if as_type is None and value is not None and value.startswith('file://'):
as_type = File
if as_type is not None and isinstance(value, as_type):
return value
elif value is None:
return None
elif as_type == int or as_type == float or as_type == decimal.Decimal:
return as_type(value)
elif as_type == dict or as_type == list:
return json.loads(value)
elif as_type == bool or value in ('True', 'False'):
return value == 'True'
elif as_type == File:
try:
fi = default_storage.open(value[7:], 'rb' if binary_file else 'r')
fi.url = default_storage.url(value[7:])
return fi
except OSError:
return False
elif as_type == datetime:
return dateutil.parser.parse(value)
elif as_type == date:
return dateutil.parser.parse(value).date()
elif as_type == time:
return dateutil.parser.parse(value).time()
elif as_type == LazyI18nString and not isinstance(value, LazyI18nString):
try:
return LazyI18nString(json.loads(value))
except ValueError:
return LazyI18nString(str(value))
elif as_type is not None and issubclass(as_type, Model):
return as_type.objects.get(pk=value)
return value
def _serialize(self, value: Any) -> str:
if isinstance(value, str):
return value
elif isinstance(value, int) or isinstance(value, float) \
or isinstance(value, bool) or isinstance(value, decimal.Decimal):
return str(value)
elif isinstance(value, list) or isinstance(value, dict):
return json.dumps(value)
elif isinstance(value, datetime) or isinstance(value, date) or isinstance(value, time):
return value.isoformat()
elif isinstance(value, Model):
return value.pk
elif isinstance(value, LazyI18nString):
return json.dumps(value.data)
elif isinstance(value, File):
return 'file://' + value.name
raise TypeError('Unable to serialize %s into a setting.' % str(type(value)))
def get(self, key: str, default=None, as_type: type=None, binary_file=False):
"""
Get a setting specified by key ``key``. Normally, settings are strings, but
if you put non-strings into the settings object, you can request unserialization
by specifying ``as_type``. If the key does not have a harcdoded type in the pretix source,
omitting ``as_type`` always will get you a string.
If the setting with the specified name does not exist on this object, any parent object
will be queried (e.g. the organizer of an event). If still no value is found, a default
value hardcoded will be returned if one exists. If not, the value of the ``default`` argument
will be returned instead.
"""
if as_type is None and key in DEFAULTS:
as_type = DEFAULTS[key]['type']
if key in self._cache():
value = self._cache()[key]
else:
value = None
if self._parent:
value = self._parent.settings.get(key, as_type=str)
if value is None and key in DEFAULTS:
value = DEFAULTS[key]['default']
if value is None and default is not None:
value = default
return self._unserialize(value, as_type, binary_file=binary_file)
def __getitem__(self, key: str) -> Any:
return self.get(key)
def __getattr__(self, key: str) -> Any:
if key.startswith('_'):
return super().__getattr__(key)
return self.get(key)
def __setattr__(self, key: str, value: Any) -> None:
if key.startswith('_'):
return super().__setattr__(key, value)
self.set(key, value)
def __setitem__(self, key: str, value: Any) -> None:
self.set(key, value)
def set(self, key: str, value: Any) -> None:
"""
Stores a setting to the database of its object.
"""
wc = self._write_cache()
if key in wc:
s = wc[key]
else:
s = self._type(object=self._obj, key=key)
s.value = self._serialize(value)
s.save()
self._cache()[key] = s.value
wc[key] = s
self._flush_external_cache()
def __delattr__(self, key: str) -> None:
if key.startswith('_'):
return super().__delattr__(key)
self.delete(key)
def __delitem__(self, key: str) -> None:
self.delete(key)
def delete(self, key: str) -> None:
"""
Deletes a setting from this object's storage.
"""
if key in self._write_cache():
self._write_cache()[key].delete()
del self._write_cache()[key]
if key in self._cache():
del self._cache()[key]
self._flush_external_cache()
@settings_hierarkey.set_global(cache_namespace='global')
class GlobalSettingsObject(GlobalSettingsBase):
slug = '_global'
class SettingsSandbox:
@@ -614,13 +442,3 @@ class SettingsSandbox:
def set(self, key: str, value: Any):
self._event.settings.set(self._convert_key(key), value)
class GlobalSettingsObject():
settings_namespace = 'global'
def __init__(self):
self.settings = SettingsProxy(self, type=GlobalSetting)
self.setting_objects = GlobalSetting.objects
self.slug = '_global'
self.pk = '_global'

View File

@@ -22,13 +22,13 @@ class EventList(ListView):
def get_queryset(self):
if self.request.user.is_superuser:
return Event.objects.all().select_related("organizer").prefetch_related(
"setting_objects", "organizer__setting_objects"
"_settings_objects", "organizer___settings_objects"
)
else:
return Event.objects.filter(
permitted__id__exact=self.request.user.pk
).select_related("organizer").prefetch_related(
"setting_objects", "organizer__setting_objects"
"_settings_objects", "organizer___settings_objects"
)

View File

@@ -7,10 +7,10 @@ pep8-naming
flake8
codecov
coverage
pytest==2.9.*
pytest==3.0.*
pytest-django
isort
pytest-mock
pytest-mock==1.4.*
pytest-rerunfailures
pytest-warnings
responses

View File

@@ -5,6 +5,7 @@ pytz
django-bootstrap3==8.0.*
django-formset-js-improved==0.5.0.1
django-compressor==2.1
django-hierarkey==1.0.*
reportlab==3.2.*
PyPDF2==1.26.*
easy-thumbnails==2.*

View File

@@ -68,6 +68,7 @@ setup(
'django-bootstrap3==7.1.*',
'django-formset-js-improved==0.5.0.1',
'django-compressor==2.1',
'django-hierarkey==1.0.*',
'reportlab==3.2.*',
'easy-thumbnails==2.*',
'PyPDF2==1.26.*',

View File

@@ -1,15 +1,9 @@
from datetime import date, datetime, time
from decimal import Decimal
from django.core.files import File
from django.core.files.storage import default_storage
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import TestCase
from django.utils.timezone import now
from i18nfield.strings import LazyI18nString
from pretix.base import settings
from pretix.base.models import Event, Organizer, User
from pretix.base.models import Event, Organizer
from pretix.base.settings import SettingsSandbox
from pretix.control.forms.global_settings import GlobalSettingsObject
@@ -21,243 +15,24 @@ class SettingsTestCase(TestCase):
'type': str
}
self.global_settings = GlobalSettingsObject()
self.global_settings.settings._flush()
self.global_settings.settings.flush()
self.organizer = Organizer.objects.create(name='Dummy', slug='dummy')
self.organizer.settings._flush()
self.organizer.settings.flush()
self.event = Event.objects.create(
organizer=self.organizer, name='Dummy', slug='dummy',
date_from=now(),
)
self.event.settings._flush()
def test_global_set_explicit(self):
self.global_settings.settings.test = 'foo'
self.assertEqual(self.global_settings.settings.test, 'foo')
# Reload object
self.global_settings = GlobalSettingsObject()
self.assertEqual(self.global_settings.settings.test, 'foo')
def test_organizer_set_explicit(self):
self.organizer.settings.test = 'foo'
self.assertEqual(self.organizer.settings.test, 'foo')
# Reload object
self.organizer = Organizer.objects.get(id=self.organizer.id)
self.assertEqual(self.organizer.settings.test, 'foo')
def test_event_set_explicit(self):
self.event.settings.test = 'foo'
self.assertEqual(self.event.settings.test, 'foo')
# Reload object
self.event = Event.objects.get(id=self.event.id)
self.assertEqual(self.event.settings.test, 'foo')
def test_event_set_twice(self):
self.event.settings.test = 'bar'
self.event.settings.test = 'foo'
self.assertEqual(self.event.settings.test, 'foo')
# Reload object
self.event = Event.objects.get(id=self.event.id)
self.assertEqual(self.event.settings.test, 'foo')
def test_organizer_set_on_global(self):
self.global_settings.settings.test = 'foo'
self.assertEqual(self.global_settings.settings.test, 'foo')
self.assertEqual(self.organizer.settings.test, 'foo')
# Reload object
self.global_settings = GlobalSettingsObject()
self.assertEqual(self.global_settings.settings.test, 'foo')
self.assertEqual(self.organizer.settings.test, 'foo')
def test_event_set_on_global(self):
self.global_settings.settings.test = 'foo'
self.assertEqual(self.global_settings.settings.test, 'foo')
self.assertEqual(self.event.settings.test, 'foo')
# Reload object
self.global_settings = GlobalSettingsObject()
self.assertEqual(self.global_settings.settings.test, 'foo')
self.assertEqual(self.event.settings.test, 'foo')
def test_event_set_on_organizer(self):
self.organizer.settings.test = 'foo'
self.assertEqual(self.organizer.settings.test, 'foo')
self.assertEqual(self.event.settings.test, 'foo')
# Reload object
self.organizer = Organizer.objects.get(id=self.organizer.id)
self.assertEqual(self.organizer.settings.test, 'foo')
self.assertEqual(self.event.settings.test, 'foo')
def test_event_override_organizer(self):
self.organizer.settings.test = 'foo'
self.event.settings.test = 'bar'
self.assertEqual(self.organizer.settings.test, 'foo')
self.assertEqual(self.event.settings.test, 'bar')
# Reload object
self.organizer = Organizer.objects.get(id=self.organizer.id)
self.event = Event.objects.get(id=self.event.id)
self.assertEqual(self.organizer.settings.test, 'foo')
self.assertEqual(self.event.settings.test, 'bar')
def test_event_override_global(self):
self.global_settings.settings.test = 'foo'
self.event.settings.test = 'bar'
self.assertEqual(self.global_settings.settings.test, 'foo')
self.assertEqual(self.event.settings.test, 'bar')
# Reload object
self.global_settings = GlobalSettingsObject()
self.event = Event.objects.get(id=self.event.id)
self.assertEqual(self.global_settings.settings.test, 'foo')
self.assertEqual(self.event.settings.test, 'bar')
def test_default(self):
self.assertEqual(self.global_settings.settings.test_default, 'def')
self.assertEqual(self.organizer.settings.test_default, 'def')
self.assertEqual(self.event.settings.test_default, 'def')
self.assertEqual(self.event.settings.get('nonexistant', default='abc'), 'abc')
def test_default_typing(self):
self.assertIs(type(self.event.settings.get('nonexistant', as_type=Decimal, default=0)), Decimal)
def test_item_access(self):
self.event.settings['foo'] = 'abc'
self.assertEqual(self.event.settings['foo'], 'abc')
del self.event.settings['foo']
self.assertIsNone(self.event.settings['foo'])
def test_delete(self):
self.organizer.settings.test = 'foo'
self.event.settings.test = 'bar'
self.assertEqual(self.organizer.settings.test, 'foo')
self.assertEqual(self.event.settings.test, 'bar')
del self.event.settings.test
self.assertEqual(self.event.settings.test, 'foo')
self.event = Event.objects.get(id=self.event.id)
self.assertEqual(self.event.settings.test, 'foo')
del self.organizer.settings.test
self.assertIsNone(self.organizer.settings.test)
self.organizer = Organizer.objects.get(id=self.organizer.id)
self.assertIsNone(self.organizer.settings.test)
def test_serialize_str(self):
self._test_serialization('ABC', as_type=str)
def test_serialize_float(self):
self._test_serialization(2.3, float)
def test_serialize_int(self):
self._test_serialization(2, int)
def test_serialize_datetime(self):
self._test_serialization(now(), datetime)
def test_serialize_time(self):
self._test_serialization(now().time(), time)
def test_serialize_date(self):
self._test_serialization(now().date(), date)
def test_serialize_decimal(self):
self._test_serialization(Decimal('2.3'), Decimal)
def test_serialize_dict(self):
self._test_serialization({'a': 'b', 'c': 'd'}, dict)
def test_serialize_list(self):
self._test_serialization([1, 2, 'a'], list)
def test_serialize_lazyi18nstring(self):
self._test_serialization(LazyI18nString({'de': 'Hallo', 'en': 'Hello'}), LazyI18nString)
def test_serialize_bool(self):
self._test_serialization(True, bool)
self._test_serialization(False, bool)
def test_serialize_bool_implicit(self):
self.event.settings.set('test', True)
self.event.settings._flush()
self.assertIs(self.event.settings.get('test', as_type=None), True)
self.event.settings.set('test', False)
self.event.settings._flush()
self.assertIs(self.event.settings.get('test', as_type=None), False)
def test_serialize_versionable(self):
self._test_serialization(self.event, Event)
def test_serialize_model(self):
self._test_serialization(User.objects.create_user('dummy@dummy.dummy', 'dummy'), User)
def test_serialize_unknown(self):
class Type:
pass
try:
self._test_serialization(Type(), Type)
self.assertTrue(False, 'No exception thrown!')
except TypeError:
pass
def test_serialize_file(self):
val = SimpleUploadedFile("sample_invalid_image.jpg", b"file_content", content_type="image/jpeg")
default_storage.save(val.name, val)
val.close()
self.event.settings.set('test', val)
self.event.settings._flush()
f = self.event.settings.get('test', as_type=File)
self.assertIsInstance(f, File)
self.assertTrue(f.name.endswith(val.name))
f.close()
def test_unserialize_file_value(self):
val = SimpleUploadedFile("sample_invalid_image.jpg", b"file_content", content_type="image/jpeg")
default_storage.save(val.name, val)
val.close()
self.event.settings.set('test', val)
self.event.settings._flush()
f = self.event.settings.get('test', as_type=File)
self.assertIsInstance(f, File)
self.assertTrue(f.name.endswith(val.name))
f.close()
def test_autodetect_file_value(self):
val = SimpleUploadedFile("sample_invalid_image.jpg", b"file_content", content_type="image/jpeg")
default_storage.save(val.name, val)
val.close()
self.event.settings.set('test', val)
self.event.settings._flush()
f = self.event.settings.get('test')
self.assertIsInstance(f, File)
self.assertTrue(f.name.endswith(val.name))
f.close()
def test_autodetect_file_value_of_parent(self):
val = SimpleUploadedFile("sample_invalid_image.jpg", b"file_content", content_type="image/jpeg")
default_storage.save(val.name, val)
val.close()
self.organizer.settings.set('test', val)
self.organizer.settings._flush()
f = self.event.settings.get('test')
self.assertIsInstance(f, File)
self.assertTrue(f.name.endswith(val.name))
f.close()
self.event.settings.flush()
def _test_serialization(self, val, as_type):
self.event.settings.set('test', val)
self.event.settings._flush()
self.event.settings.flush()
self.assertEqual(self.event.settings.get('test', as_type=as_type), val)
self.assertIsInstance(self.event.settings.get('test', as_type=as_type), as_type)
def test_serialize_lazyi18nstring(self):
self._test_serialization(LazyI18nString({'de': 'Hallo', 'en': 'Hello'}), LazyI18nString)
def test_sandbox(self):
sandbox = SettingsSandbox('testing', 'foo', self.event)
sandbox.set('foo', 'bar')
@@ -278,26 +53,3 @@ class SettingsTestCase(TestCase):
self.assertIsNone(sandbox.bar)
self.assertIsNone(sandbox['baz'])
def test_freeze(self):
olddef = settings.DEFAULTS
settings.DEFAULTS = {
'test_default': {
'default': 'def',
'type': str
}
}
self.event.organizer.settings.set('bar', 'baz')
self.event.organizer.settings.set('foo', 'baz')
self.event.settings.set('foo', 'bar')
frozen = self.event.settings.freeze()
self.event.settings.set('foo', 'notfrozen')
try:
self.assertEqual(frozen, {
'test_default': 'def',
'bar': 'baz',
'foo': 'bar'
})
finally:
settings.DEFAULTS = olddef

View File

@@ -135,7 +135,7 @@ class EventsTest(SoupTest):
'settings-payment_term_days': '2',
'settings-tax_rate_default': '19.00',
})
self.event1.settings._flush()
self.event1.settings.flush()
assert self.event1.settings.get('payment_banktransfer__enabled', as_type=bool)
assert self.event1.settings.get('payment_banktransfer__fee_abs', as_type=Decimal) == Decimal('12.23')
@@ -177,7 +177,7 @@ class EventsTest(SoupTest):
doc = self.post_doc('/control/event/%s/%s/settings/invoice' % (self.orga1.slug, self.event1.slug),
data, follow=True)
assert doc.select('.alert-success')
self.event1.settings._flush()
self.event1.settings.flush()
assert self.event1.settings.get('invoice_address_required', as_type=bool)
def test_display_settings(self):
@@ -190,7 +190,7 @@ class EventsTest(SoupTest):
doc = self.post_doc('/control/event/%s/%s/settings/display' % (self.orga1.slug, self.event1.slug),
data, follow=True)
assert doc.select('.alert-success')
self.event1.settings._flush()
self.event1.settings.flush()
assert self.event1.settings.get('primary_color') == '#FF0000'
mocked.assert_any_call(args=(self.event1.pk,))
@@ -204,7 +204,7 @@ class EventsTest(SoupTest):
doc = self.post_doc('/control/event/%s/%s/settings/email' % (self.orga1.slug, self.event1.slug),
data, follow=True)
assert doc.select('.alert-success')
self.event1.settings._flush()
self.event1.settings.flush()
assert mocked.called
def test_ticket_settings(self):
@@ -214,7 +214,7 @@ class EventsTest(SoupTest):
data['ticketoutput_testdummy__enabled'] = 'on'
doc = self.post_doc('/control/event/%s/%s/settings/tickets' % (self.orga1.slug, self.event1.slug),
data, follow=True)
self.event1.settings._flush()
self.event1.settings.flush()
assert self.event1.settings.get('ticket_download', as_type=bool)
def test_create_event_unauthorized(self):

View File

@@ -52,12 +52,12 @@ def test_settings(client, user):
client.post('/control/global/update/', {'update_check_email': 'test@example.org', 'update_check_perform': 'on'})
gs = GlobalSettingsObject()
gs.settings._flush()
gs.settings.flush()
assert gs.settings.update_check_perform
assert gs.settings.update_check_email
client.post('/control/global/update/', {'update_check_email': '', 'update_check_perform': ''})
gs.settings._flush()
gs.settings.flush()
assert not gs.settings.update_check_perform
assert not gs.settings.update_check_email
@@ -78,5 +78,5 @@ def test_trigger(client, user):
gs = GlobalSettingsObject()
assert not gs.settings.update_check_last
client.post('/control/global/update/', {'trigger': 'on'})
gs.settings._flush()
gs.settings.flush()
assert gs.settings.update_check_last

View File

@@ -44,11 +44,11 @@ def test_flush_key(client, env):
env[0].settings.set('pretixdroid_key', 'abcdefg')
client.get('/control/event/%s/%s/pretixdroid/' % (env[0].organizer.slug, env[0].slug))
env[0].settings._flush()
env[0].settings.flush()
env[0].settings.get('pretixdroid_key') == 'abcdefg'
client.get('/control/event/%s/%s/pretixdroid/?flush_key=1' % (env[0].organizer.slug, env[0].slug))
env[0].settings._flush()
env[0].settings.flush()
env[0].settings.get('pretixdroid_key') != 'abcdefg'