From 773d91ead2f47c3329c0c2d3745339e81d06eb4e Mon Sep 17 00:00:00 2001
From: Jannis Leidel <jannis@leidel.info>
Date: Thu, 17 Nov 2011 21:30:07 +0000
Subject: [PATCH] Fixed #17128 -- Fixed a Python 2.5 incompatibility. Thanks,
 Simon Meers.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@17102 bcc190cf-cafb-0310-a4f2-bffc1f526a37
---
 django/contrib/admin/views/main.py            | 24 +++----
 .../regressiontests/admin_changelist/admin.py |  8 ++-
 .../admin_changelist/models.py                |  8 +++
 .../regressiontests/admin_changelist/tests.py | 63 +++++++++++--------
 4 files changed, 63 insertions(+), 40 deletions(-)

diff --git a/django/contrib/admin/views/main.py b/django/contrib/admin/views/main.py
index 616b24957a..4eed0160e2 100644
--- a/django/contrib/admin/views/main.py
+++ b/django/contrib/admin/views/main.py
@@ -221,25 +221,25 @@ class ChangeList(object):
             # for ordering specified on ModelAdmin or model Meta, we don't know
             # the right column numbers absolutely, because there might be more
             # than one column associated with that ordering, so we guess.
-            for f in ordering:
-                if f.startswith('-'):
-                    f = f[1:]
+            for field in ordering:
+                if field.startswith('-'):
+                    field = field[1:]
                     order_type = 'desc'
                 else:
                     order_type = 'asc'
-                i = None
+                index = None
                 try:
                     # Search for simply field name first
-                    i = self.list_display.index(f)
+                    index = list(self.list_display).index(field)
                 except ValueError:
-                    # No match, but their might be a match if we take into account
-                    # 'admin_order_field'
-                    for j, attr in enumerate(self.list_display):
-                        if getattr(attr, 'admin_order_field', '') == f:
-                            i = j
+                    # No match, but there might be a match if we take into
+                    # account 'admin_order_field'
+                    for _index, attr in enumerate(self.list_display):
+                        if getattr(attr, 'admin_order_field', '') == field:
+                            index = _index
                             break
-                if i is not None:
-                    ordering_fields[i] = order_type
+                if index is not None:
+                    ordering_fields[index] = order_type
         else:
             for p in self.params[ORDER_VAR].split('.'):
                 none, pfx, idx = p.rpartition('-')
diff --git a/tests/regressiontests/admin_changelist/admin.py b/tests/regressiontests/admin_changelist/admin.py
index d1d8e0fd1e..80bb732eb0 100644
--- a/tests/regressiontests/admin_changelist/admin.py
+++ b/tests/regressiontests/admin_changelist/admin.py
@@ -4,7 +4,7 @@ from django.contrib import admin
 from django.core.paginator import Paginator
 
 from .models import (Child, Parent, Genre, Band, Musician, Group, Quartet,
-    Membership, ChordsMusician, ChordsBand, Invitation)
+    Membership, ChordsMusician, ChordsBand, Invitation, Swallow)
 
 
 site = admin.AdminSite(name="admin")
@@ -75,3 +75,9 @@ class DynamicListDisplayLinksChildAdmin(admin.ModelAdmin):
         return ['age']
 
 site.register(Child, DynamicListDisplayChildAdmin)
+
+class SwallowAdmin(admin.ModelAdmin):
+    actions = None # prevent ['action_checkbox'] + list(list_display)
+    list_display = ('origin', 'load', 'speed')
+
+site.register(Swallow, SwallowAdmin)
diff --git a/tests/regressiontests/admin_changelist/models.py b/tests/regressiontests/admin_changelist/models.py
index eed3f68508..97080fb548 100644
--- a/tests/regressiontests/admin_changelist/models.py
+++ b/tests/regressiontests/admin_changelist/models.py
@@ -49,3 +49,11 @@ class Invitation(models.Model):
     player = models.ForeignKey(ChordsMusician)
     band = models.ForeignKey(ChordsBand)
     instrument = models.CharField(max_length=15)
+
+class Swallow(models.Model):
+    origin = models.CharField(max_length=255)
+    load = models.FloatField()
+    speed = models.FloatField()
+
+    class Meta:
+        ordering = ('speed', 'load')
diff --git a/tests/regressiontests/admin_changelist/tests.py b/tests/regressiontests/admin_changelist/tests.py
index 9292895552..b422519bfb 100644
--- a/tests/regressiontests/admin_changelist/tests.py
+++ b/tests/regressiontests/admin_changelist/tests.py
@@ -11,9 +11,10 @@ from django.test.client import RequestFactory
 from .admin import (ChildAdmin, QuartetAdmin, BandAdmin, ChordsBandAdmin,
     GroupAdmin, ParentAdmin, DynamicListDisplayChildAdmin,
     DynamicListDisplayLinksChildAdmin, CustomPaginationAdmin,
-    FilteredChildAdmin, CustomPaginator, site as custom_site)
+    FilteredChildAdmin, CustomPaginator, site as custom_site,
+    SwallowAdmin)
 from .models import (Child, Parent, Genre, Band, Musician, Group, Quartet,
-    Membership, ChordsMusician, ChordsBand, Invitation)
+    Membership, ChordsMusician, ChordsBand, Invitation, Swallow)
 
 
 class ChangeListTests(TestCase):
@@ -22,6 +23,14 @@ class ChangeListTests(TestCase):
     def setUp(self):
         self.factory = RequestFactory()
 
+    def _create_superuser(self, username):
+        return User.objects.create(username=username, is_superuser=True)
+
+    def _mocked_authenticated_request(self, url, user):
+        request = self.factory.get(url)
+        request.user = user
+        return request
+
     def test_select_related_preserved(self):
         """
         Regression test for #10348: ChangeList.get_query_set() shouldn't
@@ -323,21 +332,12 @@ class ChangeListTests(TestCase):
         for i in range(10):
             Child.objects.create(name='child %s' % i, parent=parent)
 
-        user_noparents = User.objects.create(
-            username='noparents',
-            is_superuser=True)
-        user_parents = User.objects.create(
-            username='parents',
-            is_superuser=True)
-
-        def _mocked_authenticated_request(user):
-            request = self.factory.get('/child/')
-            request.user = user
-            return request
+        user_noparents = self._create_superuser('noparents')
+        user_parents = self._create_superuser('parents')
 
         # Test with user 'noparents'
         m = custom_site._registry[Child]
-        request = _mocked_authenticated_request(user_noparents)
+        request = self._mocked_authenticated_request('/child/', user_noparents)
         response = m.changelist_view(request)
         self.assertNotContains(response, 'Parent object')
 
@@ -348,7 +348,7 @@ class ChangeListTests(TestCase):
 
         # Test with user 'parents'
         m = DynamicListDisplayChildAdmin(Child, admin.site)
-        request = _mocked_authenticated_request(user_parents)
+        request = self._mocked_authenticated_request('/child/', user_parents)
         response = m.changelist_view(request)
         self.assertContains(response, 'Parent object')
 
@@ -362,7 +362,7 @@ class ChangeListTests(TestCase):
         # Test default implementation
         custom_site.register(Child, ChildAdmin)
         m = custom_site._registry[Child]
-        request = _mocked_authenticated_request(user_noparents)
+        request = self._mocked_authenticated_request('/child/', user_noparents)
         response = m.changelist_view(request)
         self.assertContains(response, 'Parent object')
 
@@ -402,17 +402,9 @@ class ChangeListTests(TestCase):
         for i in range(1, 10):
             Child.objects.create(id=i, name='child %s' % i, parent=parent, age=i)
 
-        superuser = User.objects.create(
-            username='superuser',
-            is_superuser=True)
-
-        def _mocked_authenticated_request(user):
-            request = self.factory.get('/child/')
-            request.user = user
-            return request
-
         m = DynamicListDisplayLinksChildAdmin(Child, admin.site)
-        request = _mocked_authenticated_request(superuser)
+        superuser = self._create_superuser('superuser')
+        request = self._mocked_authenticated_request('/child/', superuser)
         response = m.changelist_view(request)
         for i in range(1, 10):
             self.assertContains(response, '<a href="%s/">%s</a>' % (i, i))
@@ -420,4 +412,21 @@ class ChangeListTests(TestCase):
         list_display = m.get_list_display(request)
         list_display_links = m.get_list_display_links(request, list_display)
         self.assertEqual(list_display, ('parent', 'name', 'age'))
-        self.assertEqual(list_display_links, ['age'])
\ No newline at end of file
+        self.assertEqual(list_display_links, ['age'])
+
+    def test_tuple_list_display(self):
+        """
+        Regression test for #17128
+        (ChangeList failing under Python 2.5 after r16319)
+        """
+        swallow = Swallow.objects.create(
+            origin='Africa', load='12.34', speed='22.2')
+        model_admin = SwallowAdmin(Swallow, admin.site)
+        superuser = self._create_superuser('superuser')
+        request = self._mocked_authenticated_request('/swallow/', superuser)
+        response = model_admin.changelist_view(request)
+        # just want to ensure it doesn't blow up during rendering
+        self.assertContains(response, unicode(swallow.origin))
+        self.assertContains(response, unicode(swallow.load))
+        self.assertContains(response, unicode(swallow.speed))
+