On Mon, 08 Sep 2014, Raphael Hertzog wrote:
> So the first fix is this one:

Here's a more complete set of patches. It still fails 3 tests due to
a missing lava-health user. That user is created by the south migrations
which are not used with Django 1.7. Otherwise all other unit tests passes.

We need thus to create an equivalent Django 1.7 migrations, but I failed
to do so since "lava_server/manage.py makemigrations" fails trying to
create migration that increases the username from 30 to 255 in length.

This means in fact that python-django-longerusername is not Django 1.7 ready
and should be fixed too with a proper migration. I'm filing a bug about
this (it was not caught because it doesn't depend on python-django).

Cheers,
-- 
Raphaël Hertzog ◈ Debian Developer

Discover the Debian Administrator's Handbook:
→ http://debian-handbook.info/get/
>From 087921c8066d3f4d19084020fbd50c4b427070bd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rapha=C3=ABl=20Hertzog?= <hert...@debian.org>
Date: Mon, 8 Sep 2014 14:25:25 +0000
Subject: [PATCH 1/6] Don't add django_tables2 to INSTALLED_APPS if it's
 already there

This is required to work with Django 1.7.
---
 lava_scheduler_app/extension.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lava_scheduler_app/extension.py b/lava_scheduler_app/extension.py
index 49fbeef..df00338 100644
--- a/lava_scheduler_app/extension.py
+++ b/lava_scheduler_app/extension.py
@@ -68,7 +68,8 @@ class SchedulerExtension(LavaServerExtension):
 
     def contribute_to_settings(self, settings_module):
         super(SchedulerExtension, self).contribute_to_settings(settings_module)
-        settings_module['INSTALLED_APPS'].append('django_tables2')
+        if 'django_tables2' not in settings_module['INSTALLED_APPS']:
+            settings_module['INSTALLED_APPS'].append('django_tables2')
         from_module = settings_module.get('SCHEDULER_DAEMON_OPTIONS', {})
         settings_module['SCHEDULER_DAEMON_OPTIONS'] = {
             'LOG_FILE_PATH': None,
-- 
2.1.0

>From 0fdb885fb4e56f6d657ee618d04d44af61cf4c6a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rapha=C3=ABl=20Hertzog?= <hert...@debian.org>
Date: Mon, 8 Sep 2014 16:35:13 +0200
Subject: [PATCH 2/6] Move admin related definitions to admin.py

Loading django.contrib.admin from a models.py lead to failure in Django
1.7 because it expects models to be already ready which they aren't
at the time models.py are loaded by django.setup().
---
 lava_scheduler_app/admin.py  | 19 ++++++++++++++++++-
 lava_scheduler_app/models.py | 18 ------------------
 2 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/lava_scheduler_app/admin.py b/lava_scheduler_app/admin.py
index d3b75b8..681c9d1 100644
--- a/lava_scheduler_app/admin.py
+++ b/lava_scheduler_app/admin.py
@@ -1,9 +1,26 @@
 from django.contrib import admin
+from django.contrib.auth.admin import UserAdmin
 from lava_scheduler_app.models import (
     Device, DeviceStateTransition, DeviceType, TestJob, Tag, JobFailureTag,
-    UserAdmin, User, Worker
+    User, Worker, DefaultDeviceOwner
 )
 
+class DefaultOwnerInline(admin.StackedInline):
+    """
+    Exposes the default owner override class
+    in the Django admin interface
+    """
+    model = DefaultDeviceOwner
+    can_delete = False
+
+
+class UserAdmin(UserAdmin):
+    """
+    Defines the override class for DefaultOwnerInline
+    """
+    inlines = (DefaultOwnerInline, )
+
+
 #  Setup the override in the django admin interface at startup.
 admin.site.unregister(User)
 admin.site.register(User, UserAdmin)
diff --git a/lava_scheduler_app/models.py b/lava_scheduler_app/models.py
index abeae7a..186e855 100644
--- a/lava_scheduler_app/models.py
+++ b/lava_scheduler_app/models.py
@@ -8,8 +8,6 @@ import smtplib
 import socket
 
 from django.conf import settings
-from django.contrib import admin
-from django.contrib.auth.admin import UserAdmin
 from django.contrib.auth.models import User, Group
 from django.contrib.sites.models import Site
 from django.utils.safestring import mark_safe
@@ -118,22 +116,6 @@ class DefaultDeviceOwner(models.Model):
     )
 
 
-class DefaultOwnerInline(admin.StackedInline):
-    """
-    Exposes the default owner override class
-    in the Django admin interface
-    """
-    model = DefaultDeviceOwner
-    can_delete = False
-
-
-class UserAdmin(UserAdmin):
-    """
-    Defines the override class for DefaultOwnerInline
-    """
-    inlines = (DefaultOwnerInline, )
-
-
 class Worker(models.Model):
     """
     A worker node to which devices are attached.
-- 
2.1.0

>From ba401fa901ceb244ad982893cc51fc0fc3dd098b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rapha=C3=ABl=20Hertzog?= <hert...@debian.org>
Date: Mon, 8 Sep 2014 14:44:00 +0000
Subject: [PATCH 3/6] Do not load "south" if we use Django 1.7 or newer

Django 1.7 is incompatible with South.
---
 lava_server/settings/common.py | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/lava_server/settings/common.py b/lava_server/settings/common.py
index 041aaa2..d5dcce5 100644
--- a/lava_server/settings/common.py
+++ b/lava_server/settings/common.py
@@ -24,7 +24,7 @@
 # should happen strictly to etc/settings.conf, etc. files.
 # All comments below are strictly for development usage and
 # reference.
-
+import django
 
 # Administrator contact, used for sending
 # emergency email when something breaks
@@ -127,10 +127,13 @@ INSTALLED_APPS = [
     'longerusername',
     'linaro_django_xmlrpc',
     'lava_markitup',  # Support app for MarkItUp in LAVA
-    'south',
     'google_analytics',
 ]
 
+if django.VERSION < (1, 7):
+    # Django 1.7 has built-in migration suppport
+    INSTALLED_APPS += ['south']
+
 try:
     import devserver
     INSTALLED_APPS += ['devserver']
-- 
2.1.0

>From d8d7366719b64bdf5c14f079668f9406eaccc591 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rapha=C3=ABl=20Hertzog?= <hert...@debian.org>
Date: Mon, 8 Sep 2014 15:21:50 +0000
Subject: [PATCH 4/6] Apparently the work-around is not needed with Django 1.7

Altough there's an upstream ticket that is not yet closed:
https://code.djangoproject.com/ticket/7835
---
 dashboard_app/tests/models/test_attachment.py | 31 +++++++++++++++------------
 1 file changed, 17 insertions(+), 14 deletions(-)

diff --git a/dashboard_app/tests/models/test_attachment.py b/dashboard_app/tests/models/test_attachment.py
index 6eb6ecc..b3448f5 100644
--- a/dashboard_app/tests/models/test_attachment.py
+++ b/dashboard_app/tests/models/test_attachment.py
@@ -23,6 +23,7 @@ from django.contrib.contenttypes import generic
 from django.core.files.base import ContentFile
 from django.db import models
 from django.test import TestCase
+import django
 
 from dashboard_app.models import Attachment
 
@@ -33,23 +34,25 @@ class ModelWithAttachments(models.Model):
     """
     attachments = generic.GenericRelation(Attachment)
 
-    class Meta:
-        # This requires a bit of explanation. Traditionally we could add new
-        # models inside test modules and they would be picked up by django and
-        # synchronized (created in the test database) as a part of the test
-        # provisioning process.
+    if django.VERSION < (1, 7):
+        class Meta:
+            # This requires a bit of explanation. Traditionally we could add new
+            # models inside test modules and they would be picked up by django
+            # and synchronized (created in the test database) as a part of the
+            # test provisioning process.
 
-        # Since we started using south, synchronization is no longer occurring
-        # for the 'dashboard_app' application. This caused some test failures
-        # such as any tests that depended on the existence of this model.
+            # Since we started using south, synchronization is no longer
+            # occurring for the 'dashboard_app' application. This caused some
+            # test failures such as any tests that depended on the existence of
+            # this model.
 
-        # As a workaround we artificially "stick" this model into the only
-        # application that we can count on to exist _and_ not use south as well
-        # -- that is south itself.
+            # As a workaround we artificially "stick" this model into the only
+            # application that we can count on to exist _and_ not use south as
+            # well -- that is south itself.
 
-        # This way the test model gets synchronized when south is synchronized
-        # and all the test code below works as expected.
-        app_label = "south"
+            # This way the test model gets synchronized when south is
+            # synchronized and all the test code below works as expected.
+            app_label = "south"
 
 
 class AttachmentTestCase(TestCase):
-- 
2.1.0

>From cec7f7ee643e1f3d20d267c034f40533eb76ab43 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rapha=C3=ABl=20Hertzog?= <hert...@debian.org>
Date: Mon, 8 Sep 2014 16:19:09 +0000
Subject: [PATCH 5/6] dashboard_app/models: drop an unused and non-working
 get_absolute_url()

It's actually harmful with Django 1.7 as it leads to weird errors
like this one:
ERROR: test_test_result_permalink (dashboard_app.tests.views.test_redirects.RedirectTests)
test_test_result_permalink (dashboard_app.tests.views.test_redirects.RedirectTests)
----------------------------------------------------------------------
_StringException: Traceback (most recent call last):
  File "/home/rhertzog/tmp/django17/lava-server/lava_server/../dashboard_app/tests/views/test_redirects.py", line 109, in test_test_result_permalink
    self.assertRedirects(response, test_result.get_absolute_url())
  File "/usr/lib/python2.7/dist-packages/django/test/testcases.py", line 295, in assertRedirects
    secure=(scheme == 'https'))
  File "/usr/lib/python2.7/dist-packages/django/test/client.py", line 467, in get
    **extra)
  File "/usr/lib/python2.7/dist-packages/django/test/client.py", line 285, in get
    return self.generic('GET', path, secure=secure, **r)
  File "/usr/lib/python2.7/dist-packages/django/test/client.py", line 355, in generic
    return self.request(**r)
  File "/usr/lib/python2.7/dist-packages/django/test/client.py", line 419, in request
    response = self.handler(environ)
  File "/usr/lib/python2.7/dist-packages/django/test/client.py", line 110, in __call__
    response = self.get_response(request)
  File "/usr/lib/python2.7/dist-packages/django/core/handlers/base.py", line 199, in get_response
    response = self.handle_uncaught_exception(request, resolver, sys.exc_info())
  File "/usr/lib/python2.7/dist-packages/django/core/handlers/base.py", line 111, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/rhertzog/tmp/django17/lava-server/lava_server/../dashboard_app/views/__init__.py", line 742, in test_result_detail
    }, RequestContext(request))
  File "/usr/lib/python2.7/dist-packages/django/shortcuts.py", line 23, in render_to_response
    return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs)
  File "/usr/lib/python2.7/dist-packages/django/template/loader.py", line 178, in render_to_string
    return t.render(context_instance)
  File "/usr/lib/python2.7/dist-packages/django/template/base.py", line 148, in render
    return self._render(context)
  File "/usr/lib/python2.7/dist-packages/django/test/utils.py", line 88, in instrumented_test_render
    return self.nodelist.render(context)
  File "/usr/lib/python2.7/dist-packages/django/template/base.py", line 844, in render
    bit = self.render_node(node, context)
  File "/usr/lib/python2.7/dist-packages/django/template/debug.py", line 80, in render_node
    return node.render(context)
  File "/usr/lib/python2.7/dist-packages/django/template/loader_tags.py", line 126, in render
    return compiled_parent._render(context)
  File "/usr/lib/python2.7/dist-packages/django/test/utils.py", line 88, in instrumented_test_render
    return self.nodelist.render(context)
  File "/usr/lib/python2.7/dist-packages/django/template/base.py", line 844, in render
    bit = self.render_node(node, context)
  File "/usr/lib/python2.7/dist-packages/django/template/debug.py", line 80, in render_node
    return node.render(context)
  File "/usr/lib/python2.7/dist-packages/django/template/loader_tags.py", line 126, in render
    return compiled_parent._render(context)
  File "/usr/lib/python2.7/dist-packages/django/test/utils.py", line 88, in instrumented_test_render
    return self.nodelist.render(context)
  File "/usr/lib/python2.7/dist-packages/django/template/base.py", line 844, in render
    bit = self.render_node(node, context)
  File "/usr/lib/python2.7/dist-packages/django/template/debug.py", line 80, in render_node
    return node.render(context)
  File "/usr/lib/python2.7/dist-packages/django/template/loader_tags.py", line 65, in render
    result = block.nodelist.render(context)
  File "/usr/lib/python2.7/dist-packages/django/template/base.py", line 844, in render
    bit = self.render_node(node, context)
  File "/usr/lib/python2.7/dist-packages/django/template/debug.py", line 80, in render_node
    return node.render(context)
  File "/usr/lib/python2.7/dist-packages/django/template/loader_tags.py", line 65, in render
    result = block.nodelist.render(context)
  File "/usr/lib/python2.7/dist-packages/django/template/base.py", line 844, in render
    bit = self.render_node(node, context)
  File "/usr/lib/python2.7/dist-packages/django/template/debug.py", line 80, in render_node
    return node.render(context)
  File "/usr/lib/python2.7/dist-packages/django/template/debug.py", line 90, in render
    output = self.filter_expression.resolve(context)
  File "/usr/lib/python2.7/dist-packages/django/template/base.py", line 596, in resolve
    obj = self.var.resolve(context)
  File "/usr/lib/python2.7/dist-packages/django/template/base.py", line 734, in resolve
    value = self._resolve_lookup(context)
  File "/usr/lib/python2.7/dist-packages/django/template/base.py", line 788, in _resolve_lookup
    current = current()
  File "/usr/lib/python2.7/dist-packages/django/utils/functional.py", line 17, in _curried
    return _curried_func(*(args + moreargs), **dict(kwargs, **morekwargs))
  File "/usr/lib/python2.7/dist-packages/django/db/models/base.py", line 1451, in get_absolute_url
    return settings.ABSOLUTE_URL_OVERRIDES.get('%s.%s' % (opts.app_label, opts.model_name), func)(self, *args, **kwargs)
  File "/usr/lib/python2.7/dist-packages/django/db/models/__init__.py", line 40, in inner
    return reverse(bits[0], None, *bits[1:3])
  File "/usr/lib/python2.7/dist-packages/django/core/urlresolvers.py", line 546, in reverse
    return iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs))
TypeError: _reverse_with_prefix() argument after ** must be a mapping, not unicode
---
 dashboard_app/models.py | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/dashboard_app/models.py b/dashboard_app/models.py
index 68e3e2d..146f733 100644
--- a/dashboard_app/models.py
+++ b/dashboard_app/models.py
@@ -714,10 +714,6 @@ class Test(models.Model):
     def __unicode__(self):
         return self.name or self.test_id
 
-    @models.permalink
-    def get_absolute_url(self):
-        return self.test_id
-
     def count_results_without_test_case(self):
         return TestResult.objects.filter(
             test_run__test=self,
-- 
2.1.0

Attachment: 0006-Rename-migrations-directories-in-south_migrations.patch.xz
Description: Binary data

Reply via email to