From f0156cfcb3ca0337ed3fea556a814c566269d6fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Th=C3=A9pot?= Date: Wed, 14 Jan 2015 11:15:45 +0100 Subject: [PATCH 1/6] Populate user settings w/ data migration, Django1.7 compatible, fix #276 --- .../migrations/0003_populate_usersettings.py | 50 +++++++++++++++++++ helpdesk/models.py | 22 ++------ 2 files changed, 54 insertions(+), 18 deletions(-) create mode 100644 helpdesk/migrations/0003_populate_usersettings.py diff --git a/helpdesk/migrations/0003_populate_usersettings.py b/helpdesk/migrations/0003_populate_usersettings.py new file mode 100644 index 00000000..ebf57a8b --- /dev/null +++ b/helpdesk/migrations/0003_populate_usersettings.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.contrib.auth import get_user_model +from django.db import models, migrations + +from helpdesk.settings import DEFAULT_USER_SETTINGS + + +def picke_settings(data): + """Pickling as defined at migration's creation time""" + import cPickle + from helpdesk.lib import b64encode + return b64encode(cPickle.dumps(data)) + + +# https://docs.djangoproject.com/en/1.7/topics/migrations/#data-migrations +def populate_usersettings(apps, schema_editor): + """Create a UserSettings entry for each existing user. + This will only happen once (at install time, or at upgrade) + when the UserSettings model doesn't already exist.""" + + _User = get_user_model() + User = apps.get_model(_User._meta.app_label, _User._meta.model_name) + + # Import historical version of models + UserSettings = apps.get_model("helpdesk", "UserSettings") + + settings_pickled = picke_settings(DEFAULT_USER_SETTINGS) + + for u in User.objects.all(): + try: + UserSettings.objects.get(user=u) + except UserSettings.DoesNotExist: + UserSettings.objects.create(user=u, settings_pickled=settings_pickled) + + +noop = lambda *args, **kwargs: None + +class Migration(migrations.Migration): + + dependencies = [ + ('helpdesk', '0002_socks_proxy'), + ] + + operations = [ + migrations.RunPython(populate_usersettings, reverse_code=noop), + ] + + diff --git a/helpdesk/models.py b/helpdesk/models.py index 44a69b89..1143e491 100644 --- a/helpdesk/models.py +++ b/helpdesk/models.py @@ -1027,7 +1027,7 @@ class UserSettings(models.Model): verbose_name_plural = _('User Settings') -def create_usersettings(sender, created_models=[], instance=None, created=False, **kwargs): +def create_usersettings(sender, instance, created, **kwargs): """ Helper function to create UserSettings instances as required, eg when we first create the UserSettings database @@ -1037,30 +1037,16 @@ def create_usersettings(sender, created_models=[], instance=None, created=False, 'DoesNotExist: UserSettings matching query does not exist.' errors. """ from helpdesk.settings import DEFAULT_USER_SETTINGS - if sender == settings.AUTH_USER_MODEL and created: - # This is a new user, so lets create their settings entry. - s, created = UserSettings.objects.get_or_create(user=instance, defaults={'settings': DEFAULT_USER_SETTINGS}) - s.save() - elif UserSettings in created_models: - User = get_user_model() - # We just created the UserSettings model, lets create a UserSettings - # entry for each existing user. This will only happen once (at install - # time, or at upgrade) when the UserSettings model doesn't already - # exist. - for u in User.objects.all(): - try: - s = UserSettings.objects.get(user=u) - except UserSettings.DoesNotExist: - s = UserSettings(user=u, settings=DEFAULT_USER_SETTINGS) - s.save() + if created: + UserSettings.objects.create(user=instance, settings=DEFAULT_USER_SETTINGS) -models.signals.post_syncdb.connect(create_usersettings) try: models.signals.post_save.connect(create_usersettings, sender=settings.AUTH_USER_MODEL) except: signal_user = get_user_model() models.signals.post_save.connect(create_usersettings, sender=signal_user) + class IgnoreEmail(models.Model): """ This model lets us easily ignore e-mails from certain senders when From afb0bd25b3681c00927c9a712a88cc54700be89c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Th=C3=A9pot?= Date: Wed, 14 Jan 2015 14:10:09 +0100 Subject: [PATCH 2/6] Test fix: adding a django.setup() phase --- quicktest.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/quicktest.py b/quicktest.py index f6aa9af6..528c3b3f 100644 --- a/quicktest.py +++ b/quicktest.py @@ -1,8 +1,11 @@ import os import sys import argparse + +import django from django.conf import settings + class QuickDjangoTest(object): """ A quick way to run the Django test suite without a fully-configured project. @@ -79,6 +82,8 @@ class QuickDjangoTest(object): INSTALLED_APPS = self.INSTALLED_APPS + self.apps, ROOT_URLCONF = self.apps[0] + '.urls', ) + django.setup() + from django.test.simple import DjangoTestSuiteRunner failures = DjangoTestSuiteRunner().run_tests(self.apps, verbosity=1) if failures: From f68c1b3ae9957abf19aef6e2353af3b51b3f6235 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Th=C3=A9pot?= Date: Wed, 14 Jan 2015 15:36:37 +0100 Subject: [PATCH 3/6] Django1.7 tests: load initial_data w/ migration --- .../migrations/0004_initial_data_import.py | 44 +++++++++++++++++++ quicktest.py | 10 +++-- 2 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 helpdesk/migrations/0004_initial_data_import.py diff --git a/helpdesk/migrations/0004_initial_data_import.py b/helpdesk/migrations/0004_initial_data_import.py new file mode 100644 index 00000000..f3015cd9 --- /dev/null +++ b/helpdesk/migrations/0004_initial_data_import.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +import os +from sys import path + +from django.db import models, migrations +from django.core import serializers + +fixture_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '../fixtures')) +fixture_filename = 'initial_data.json' + +def deserialize_fixture(): + fixture_file = os.path.join(fixture_dir, fixture_filename) + + with open(fixture_file, 'rb') as fixture: + return list(serializers.deserialize('json', fixture, ignorenonexistent=True)) + + +def load_fixture(apps, schema_editor): + objects = deserialize_fixture() + + for obj in objects: + obj.save() + + +def unload_fixture(apps, schema_editor): + "Delete all EmailTemplate objects" + + objects = deserialize_fixture() + + EmailTemplate = apps.get_model("helpdesk", "emailtemplate") + EmailTemplate.objects.filter(pk__in=[ obj.object.pk for obj in objects ]).delete() + + +class Migration(migrations.Migration): + + dependencies = [ + ('helpdesk', '0003_populate_usersettings'), + ] + + operations = [ + migrations.RunPython(load_fixture, reverse_code=unload_fixture), + ] diff --git a/quicktest.py b/quicktest.py index 528c3b3f..b251e5a6 100644 --- a/quicktest.py +++ b/quicktest.py @@ -28,6 +28,7 @@ class QuickDjangoTest(object): 'django.contrib.humanize', 'bootstrapform', ) + MIDDLEWARE_CLASSES = [] def __init__(self, *args, **kwargs): self.apps = args @@ -43,8 +44,7 @@ class QuickDjangoTest(object): """ Figure out which version of Django's test suite we have to play with. """ - from django import VERSION - if VERSION[0] == 1 and VERSION[1] >= 2: + if django.VERSION > (1, 2): return 'new' else: return 'old' @@ -67,6 +67,7 @@ class QuickDjangoTest(object): """ Fire up the Django test suite developed for version 1.2 """ + settings.configure( DEBUG = True, DATABASES = { @@ -80,9 +81,12 @@ class QuickDjangoTest(object): } }, INSTALLED_APPS = self.INSTALLED_APPS + self.apps, + MIDDLEWARE_CLASSES = self.MIDDLEWARE_CLASSES, ROOT_URLCONF = self.apps[0] + '.urls', ) - django.setup() + + if django.VERSION > (1, 7): + django.setup() from django.test.simple import DjangoTestSuiteRunner failures = DjangoTestSuiteRunner().run_tests(self.apps, verbosity=1) From b53d3ad9bc4b6561542dffd1bdf16e2a3cd59308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Th=C3=A9pot?= Date: Wed, 14 Jan 2015 15:49:08 +0100 Subject: [PATCH 4/6] Rename initial_data.json to emailtemplate.json --- .../{initial_data.json => emailtemplate.json} | 0 helpdesk/migrations/0004_initial_data_import.py | 2 +- quicktest.py | 12 +++++++++--- 3 files changed, 10 insertions(+), 4 deletions(-) rename helpdesk/fixtures/{initial_data.json => emailtemplate.json} (100%) diff --git a/helpdesk/fixtures/initial_data.json b/helpdesk/fixtures/emailtemplate.json similarity index 100% rename from helpdesk/fixtures/initial_data.json rename to helpdesk/fixtures/emailtemplate.json diff --git a/helpdesk/migrations/0004_initial_data_import.py b/helpdesk/migrations/0004_initial_data_import.py index f3015cd9..e64f4112 100644 --- a/helpdesk/migrations/0004_initial_data_import.py +++ b/helpdesk/migrations/0004_initial_data_import.py @@ -8,7 +8,7 @@ from django.db import models, migrations from django.core import serializers fixture_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '../fixtures')) -fixture_filename = 'initial_data.json' +fixture_filename = 'emailtemplate.json' def deserialize_fixture(): fixture_file = os.path.join(fixture_dir, fixture_filename) diff --git a/quicktest.py b/quicktest.py index b251e5a6..458db8c3 100644 --- a/quicktest.py +++ b/quicktest.py @@ -28,7 +28,13 @@ class QuickDjangoTest(object): 'django.contrib.humanize', 'bootstrapform', ) - MIDDLEWARE_CLASSES = [] + MIDDLEWARE_CLASSES = [ + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + ] def __init__(self, *args, **kwargs): self.apps = args @@ -44,7 +50,7 @@ class QuickDjangoTest(object): """ Figure out which version of Django's test suite we have to play with. """ - if django.VERSION > (1, 2): + if django.VERSION >= (1, 2): return 'new' else: return 'old' @@ -85,7 +91,7 @@ class QuickDjangoTest(object): ROOT_URLCONF = self.apps[0] + '.urls', ) - if django.VERSION > (1, 7): + if django.VERSION >= (1, 7): django.setup() from django.test.simple import DjangoTestSuiteRunner From ed9dbbe42c04830bf398be15a96dabbb729bb602 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Th=C3=A9pot?= Date: Wed, 14 Jan 2015 15:54:39 +0100 Subject: [PATCH 5/6] Blindly test if failure for django < 1.7 comes from middlewares --- quicktest.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/quicktest.py b/quicktest.py index 458db8c3..d49084b9 100644 --- a/quicktest.py +++ b/quicktest.py @@ -29,11 +29,12 @@ class QuickDjangoTest(object): 'bootstrapform', ) MIDDLEWARE_CLASSES = [ + 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] def __init__(self, *args, **kwargs): From 83affccec5120d327d1d1317f7d212cfe2ac09d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Th=C3=A9pot?= Date: Wed, 14 Jan 2015 16:00:35 +0100 Subject: [PATCH 6/6] Specify features to load in failing testcase for django < 1.7 --- helpdesk/tests/ticket_submission.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/helpdesk/tests/ticket_submission.py b/helpdesk/tests/ticket_submission.py index 785f7ec1..e4779433 100644 --- a/helpdesk/tests/ticket_submission.py +++ b/helpdesk/tests/ticket_submission.py @@ -5,6 +5,8 @@ from django.test.client import Client from django.core.urlresolvers import reverse class TicketBasicsTestCase(TestCase): + fixtures = ['emailtemplate.json'] + def setUp(self): self.queue_public = Queue.objects.create(title='Queue 1', slug='q1', allow_public_submission=True, new_ticket_cc='new.public@example.com', updated_ticket_cc='update.public@example.com') self.queue_private = Queue.objects.create(title='Queue 2', slug='q2', allow_public_submission=False, new_ticket_cc='new.private@example.com', updated_ticket_cc='update.private@example.com')