Merge "Drop Django <= 1.10 support"

This commit is contained in:
Zuul 2018-03-09 17:40:17 +00:00 committed by Gerrit Code Review
commit cd06fe813e
13 changed files with 81 additions and 167 deletions

View File

@ -54,11 +54,11 @@
- project: - project:
check: check:
jobs: jobs:
- horizon-openstack-tox-py35dj20: - horizon-openstack-tox-py35dj20
voting: false
- horizon-selenium-headless - horizon-selenium-headless
- horizon-dsvm-tempest-plugin - horizon-dsvm-tempest-plugin
gate: gate:
jobs: jobs:
- horizon-openstack-tox-py35dj20
- horizon-selenium-headless - horizon-selenium-headless
- horizon-dsvm-tempest-plugin - horizon-dsvm-tempest-plugin

View File

@ -27,7 +27,6 @@ import inspect
import logging import logging
import os import os
import django
from django.conf import settings from django.conf import settings
from django.conf.urls import include from django.conf.urls import include
from django.conf.urls import url from django.conf.urls import url
@ -58,12 +57,7 @@ def _decorate_urlconf(urlpatterns, decorator, *args, **kwargs):
for pattern in urlpatterns: for pattern in urlpatterns:
if getattr(pattern, 'callback', None): if getattr(pattern, 'callback', None):
decorated = decorator(pattern.callback, *args, **kwargs) decorated = decorator(pattern.callback, *args, **kwargs)
if django.VERSION >= (1, 10):
pattern.callback = decorated pattern.callback = decorated
else:
# prior to 1.10 callback was a property and we had
# to modify the private attribute behind the property
pattern._callback = decorated
if getattr(pattern, 'url_patterns', []): if getattr(pattern, 'url_patterns', []):
_decorate_urlconf(pattern.url_patterns, decorator, *args, **kwargs) _decorate_urlconf(pattern.url_patterns, decorator, *args, **kwargs)

View File

@ -10,15 +10,11 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import django
from django import template from django import template
from django.template import defaultfilters from django.template import defaultfilters
from django.utils import safestring from django.utils import safestring
if django.VERSION >= (1, 9):
register = template.Library() register = template.Library()
else:
register = template.base.Library()
@register.filter(is_safe=True) @register.filter(is_safe=True)

View File

@ -22,7 +22,6 @@ from importlib import import_module
import six import six
from six import moves from six import moves
import django
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
@ -310,10 +309,7 @@ class HorizonTests(BaseHorizonTests):
self.client.logout() self.client.logout()
resp = self.client.get(url) resp = self.client.get(url)
if django.VERSION >= (1, 9):
self.assertRedirects(resp, settings.TESTSERVER + redirect_url) self.assertRedirects(resp, settings.TESTSERVER + redirect_url)
else:
self.assertRedirects(resp, redirect_url)
# Set SSL settings for test server # Set SSL settings for test server
settings.SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', settings.SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL',

View File

@ -13,7 +13,6 @@
import uuid import uuid
import django
from django.conf import settings from django.conf import settings
from django.contrib import auth from django.contrib import auth
from django import test from django import test
@ -395,10 +394,7 @@ class OpenStackAuthTestsV2(OpenStackAuthTestsMixin, test.TestCase):
response = self.client.get(url, form_data) response = self.client.get(url, form_data)
if next: if next:
if django.VERSION >= (1, 9):
expected_url = next expected_url = next
else:
expected_url = 'http://testserver%s' % next
self.assertEqual(response['location'], expected_url) self.assertEqual(response['location'], expected_url)
else: else:
self.assertRedirects(response, settings.LOGIN_REDIRECT_URL) self.assertRedirects(response, settings.LOGIN_REDIRECT_URL)
@ -444,10 +440,7 @@ class OpenStackAuthTestsV2(OpenStackAuthTestsMixin, test.TestCase):
response = self.client.get(url, form_data) response = self.client.get(url, form_data)
if next: if next:
if django.VERSION >= (1, 9):
expected_url = next expected_url = next
else:
expected_url = 'http://testserver%s' % next
self.assertEqual(response['location'], expected_url) self.assertEqual(response['location'], expected_url)
else: else:
self.assertRedirects(response, settings.LOGIN_REDIRECT_URL) self.assertRedirects(response, settings.LOGIN_REDIRECT_URL)
@ -768,10 +761,7 @@ class OpenStackAuthTestsV3(OpenStackAuthTestsMixin,
response = self.client.get(url, form_data) response = self.client.get(url, form_data)
if next: if next:
if django.VERSION >= (1, 9):
expected_url = next expected_url = next
else:
expected_url = 'http://testserver%s' % next
self.assertEqual(response['location'], expected_url) self.assertEqual(response['location'], expected_url)
else: else:
self.assertRedirects(response, settings.LOGIN_REDIRECT_URL) self.assertRedirects(response, settings.LOGIN_REDIRECT_URL)
@ -816,10 +806,7 @@ class OpenStackAuthTestsV3(OpenStackAuthTestsMixin,
response = self.client.get(url, form_data) response = self.client.get(url, form_data)
if next: if next:
if django.VERSION >= (1, 9):
expected_url = next expected_url = next
else:
expected_url = 'http://testserver%s' % next
self.assertEqual(response['location'], expected_url) self.assertEqual(response['location'], expected_url)
else: else:
self.assertRedirects(response, settings.LOGIN_REDIRECT_URL) self.assertRedirects(response, settings.LOGIN_REDIRECT_URL)

View File

@ -17,7 +17,6 @@ import logging
import os import os
import unittest import unittest
import django
from django import http from django import http
from django.test.utils import override_settings from django.test.utils import override_settings
from django.urls import reverse from django.urls import reverse
@ -277,14 +276,9 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
res = self.client.get(reverse('horizon:identity:projects:create')) res = self.client.get(reverse('horizon:identity:projects:create'))
self.assertTemplateUsed(res, views.WorkflowView.template_name) self.assertTemplateUsed(res, views.WorkflowView.template_name)
if django.VERSION >= (1, 10):
pattern = ('<input autocomplete="off" class="form-control" ' pattern = ('<input autocomplete="off" class="form-control" '
'id="id_subnet" min="-1" ' 'id="id_subnet" min="-1" '
'name="subnet" type="number" value="10" required/>') 'name="subnet" type="number" value="10" required/>')
else:
pattern = ('<input autocomplete="off" class="form-control" '
'id="id_subnet" min="-1" '
'name="subnet" type="number" value="10"/>')
self.assertContains(res, pattern, html=True) self.assertContains(res, pattern, html=True)
workflow = res.context['workflow'] workflow = res.context['workflow']

View File

@ -18,7 +18,6 @@
from socket import timeout as socket_timeout from socket import timeout as socket_timeout
import django
from django import http from django import http
from django.test.utils import override_settings from django.test.utils import override_settings
from django.urls import reverse from django.urls import reverse
@ -238,7 +237,6 @@ class UsersViewTests(test.BaseAdminViewTests):
api.keystone.role_list(IgnoreArg()).AndReturn(self.roles.list()) api.keystone.role_list(IgnoreArg()).AndReturn(self.roles.list())
api.keystone.get_default_role(IgnoreArg()) \ api.keystone.get_default_role(IgnoreArg()) \
.AndReturn(self.roles.first()) .AndReturn(self.roles.first())
if django.VERSION >= (1, 9):
if api.keystone.VERSIONS.active >= 3: if api.keystone.VERSIONS.active >= 3:
api.keystone.tenant_list( api.keystone.tenant_list(
IgnoreArg(), domain=domain_id).AndReturn( IgnoreArg(), domain=domain_id).AndReturn(
@ -291,7 +289,6 @@ class UsersViewTests(test.BaseAdminViewTests):
api.keystone.role_list(IgnoreArg()).AndReturn(self.roles.list()) api.keystone.role_list(IgnoreArg()).AndReturn(self.roles.list())
api.keystone.get_default_role(IgnoreArg()) \ api.keystone.get_default_role(IgnoreArg()) \
.AndReturn(self.roles.first()) .AndReturn(self.roles.first())
if django.VERSION >= (1, 9):
if api.keystone.VERSIONS.active >= 3: if api.keystone.VERSIONS.active >= 3:
api.keystone.tenant_list( api.keystone.tenant_list(
IgnoreArg(), domain=domain_id).AndReturn( IgnoreArg(), domain=domain_id).AndReturn(
@ -347,7 +344,6 @@ class UsersViewTests(test.BaseAdminViewTests):
api.keystone.role_list(IgnoreArg()).AndReturn(self.roles.list()) api.keystone.role_list(IgnoreArg()).AndReturn(self.roles.list())
api.keystone.get_default_role(IgnoreArg()) \ api.keystone.get_default_role(IgnoreArg()) \
.AndReturn(self.roles.first()) .AndReturn(self.roles.first())
if django.VERSION >= (1, 9):
if api.keystone.VERSIONS.active >= 3: if api.keystone.VERSIONS.active >= 3:
api.keystone.tenant_list( api.keystone.tenant_list(
IgnoreArg(), domain=domain_id).AndReturn( IgnoreArg(), domain=domain_id).AndReturn(

View File

@ -1783,18 +1783,11 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
# NOTE(adriant): Django 1.11 changes the checked syntax to use html5 # NOTE(adriant): Django 1.11 changes the checked syntax to use html5
# "checked" rather than XHTML's "checked='checked'". # "checked" rather than XHTML's "checked='checked'".
if django.VERSION >= (1, 11):
checked_box = ( checked_box = (
'<input type="checkbox" name="network" ' '<input type="checkbox" name="network" '
'value="82288d84-e0a5-42ac-95be-e6af08727e42" ' 'value="82288d84-e0a5-42ac-95be-e6af08727e42" '
'id="id_network_0" checked />' 'id="id_network_0" checked />'
) )
else:
checked_box = (
'<input type="checkbox" name="network" '
'value="82288d84-e0a5-42ac-95be-e6af08727e42" '
'id="id_network_0" checked="checked" />'
)
if only_one_network: if only_one_network:
self.assertContains(res, checked_box, html=True) self.assertContains(res, checked_box, html=True)
else: else:

View File

@ -13,7 +13,6 @@
# under the License. # under the License.
import copy import copy
import django
from django import http from django import http
from django.urls import reverse from django.urls import reverse
@ -590,14 +589,9 @@ class RouterActionTests(RouterMixin, test.TestCase):
self.assertTemplateUsed(res, 'project/routers/update.html') self.assertTemplateUsed(res, 'project/routers/update.html')
self.assertContains(res, 'Router Type') self.assertContains(res, 'Router Type')
if django.VERSION >= (1, 10):
pattern = ('<input class="form-control" id="id_mode" name="mode" ' pattern = ('<input class="form-control" id="id_mode" name="mode" '
'readonly="readonly" type="text" value="distributed" ' 'readonly="readonly" type="text" value="distributed" '
'required/>') 'required/>')
else:
pattern = ('<input class="form-control" id="id_mode" name="mode" '
'readonly="readonly" type="text" '
'value="distributed" />')
self.assertContains(res, pattern, html=True) self.assertContains(res, pattern, html=True)
self.assertNotContains(res, 'centralized') self.assertNotContains(res, 'centralized')

View File

@ -21,7 +21,6 @@ import cgi
from mox3.mox import IsA from mox3.mox import IsA
import six import six
import django
from django.conf import settings from django.conf import settings
from django import http from django import http
from django.urls import reverse from django.urls import reverse
@ -478,9 +477,7 @@ class SecurityGroupsViewTests(test.TestCase):
sec_group_list = self.security_groups.list() sec_group_list = self.security_groups.list()
rule = self.security_group_rules.first() rule = self.security_group_rules.first()
api.neutron.security_group_list( for i in range(2):
IsA(http.HttpRequest)).AndReturn(sec_group_list)
if django.VERSION >= (1, 9):
api.neutron.security_group_list( api.neutron.security_group_list(
IsA(http.HttpRequest)).AndReturn(sec_group_list) IsA(http.HttpRequest)).AndReturn(sec_group_list)
@ -503,11 +500,7 @@ class SecurityGroupsViewTests(test.TestCase):
sec_group_list = self.security_groups.list() sec_group_list = self.security_groups.list()
rule = self.security_group_rules.first() rule = self.security_group_rules.first()
for i in range(3): for i in range(6):
api.neutron.security_group_list(
IsA(http.HttpRequest)).AndReturn(sec_group_list)
if django.VERSION >= (1, 9):
for i in range(3):
api.neutron.security_group_list( api.neutron.security_group_list(
IsA(http.HttpRequest)).AndReturn(sec_group_list) IsA(http.HttpRequest)).AndReturn(sec_group_list)
@ -559,10 +552,7 @@ class SecurityGroupsViewTests(test.TestCase):
icmp_rule = self.security_group_rules.list()[1] icmp_rule = self.security_group_rules.list()[1]
# Call POST 5 times (*2 if Django >= 1.9) # Call POST 5 times (*2 if Django >= 1.9)
call_post = 5 call_post = 5 * 2
if django.VERSION >= (1, 9):
call_post *= 2
for i in range(call_post): for i in range(call_post):
api.neutron.security_group_list( api.neutron.security_group_list(
IsA(http.HttpRequest)).AndReturn(sec_group_list) IsA(http.HttpRequest)).AndReturn(sec_group_list)
@ -921,9 +911,7 @@ class SecurityGroupsViewTests(test.TestCase):
sec_group_list = self.security_groups.list() sec_group_list = self.security_groups.list()
rule = self.security_group_rules.first() rule = self.security_group_rules.first()
api.neutron.security_group_list( for i in range(2):
IsA(http.HttpRequest)).AndReturn(sec_group_list)
if django.VERSION >= (1, 9):
api.neutron.security_group_list( api.neutron.security_group_list(
IsA(http.HttpRequest)).AndReturn(sec_group_list) IsA(http.HttpRequest)).AndReturn(sec_group_list)

View File

@ -17,7 +17,6 @@ import copy
import mock import mock
import six import six
import django
from django.conf import settings from django.conf import settings
from django.forms import widgets from django.forms import widgets
from django.template.defaultfilters import slugify from django.template.defaultfilters import slugify
@ -634,12 +633,8 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
self.assertFormError(res, 'form', None, self.assertFormError(res, 'form', None,
"The volume size cannot be less than the " "The volume size cannot be less than the "
"snapshot size (40GiB)") "snapshot size (40GiB)")
if django.VERSION >= (1, 9):
self.assertEqual(3, self.mock_volume_type_list.call_count) self.assertEqual(3, self.mock_volume_type_list.call_count)
self.assertEqual(2, self.mock_volume_type_default.call_count) self.assertEqual(2, self.mock_volume_type_default.call_count)
else:
self.assertEqual(2, self.mock_volume_type_list.call_count)
self.assertEqual(1, self.mock_volume_type_default.call_count)
self.mock_volume_snapshot_get.assert_called_with(test.IsHttpRequest(), self.mock_volume_snapshot_get.assert_called_with(test.IsHttpRequest(),
str(snapshot.id)) str(snapshot.id))
@ -812,12 +807,8 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
self.assertFormError(res, 'form', None, msg) self.assertFormError(res, 'form', None, msg)
if django.VERSION >= (1, 9):
self.assertEqual(3, self.mock_volume_type_list.call_count) self.assertEqual(3, self.mock_volume_type_list.call_count)
self.assertEqual(2, self.mock_volume_type_default.call_count) self.assertEqual(2, self.mock_volume_type_default.call_count)
else:
self.assertEqual(2, self.mock_volume_type_list.call_count)
self.assertEqual(1, self.mock_volume_type_default.call_count)
self.assertEqual(2, self.mock_tenant_limit_usages.call_count) self.assertEqual(2, self.mock_tenant_limit_usages.call_count)
self.mock_image_get.assert_called_with(test.IsHttpRequest(), self.mock_image_get.assert_called_with(test.IsHttpRequest(),
@ -861,14 +852,9 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
self.assertFormError(res, 'form', None, self.assertFormError(res, 'form', None,
"The volume size cannot be less than the " "The volume size cannot be less than the "
"image minimum disk size (30GiB)") "image minimum disk size (30GiB)")
if django.VERSION >= (1, 9):
self.assertEqual(3, self.mock_volume_type_list.call_count) self.assertEqual(3, self.mock_volume_type_list.call_count)
self.assertEqual(2, self.mock_volume_type_default.call_count) self.assertEqual(2, self.mock_volume_type_default.call_count)
self.assertEqual(2, self.mock_availability_zone_list.call_count) self.assertEqual(2, self.mock_availability_zone_list.call_count)
else:
self.assertEqual(2, self.mock_volume_type_list.call_count)
self.assertEqual(1, self.mock_volume_type_default.call_count)
self.assertEqual(1, self.mock_availability_zone_list.call_count)
self.mock_image_get.assert_called_with(test.IsHttpRequest(), self.mock_image_get.assert_called_with(test.IsHttpRequest(),
str(image.id)) str(image.id))
@ -932,16 +918,10 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
' have 20GiB of your quota available.'] ' have 20GiB of your quota available.']
self.assertEqual(res.context['form'].errors['__all__'], expected_error) self.assertEqual(res.context['form'].errors['__all__'], expected_error)
if django.VERSION >= (1, 9):
self.assertEqual(3, self.mock_volume_type_list.call_count) self.assertEqual(3, self.mock_volume_type_list.call_count)
self.assertEqual(2, self.mock_volume_type_default.call_count) self.assertEqual(2, self.mock_volume_type_default.call_count)
self.assertEqual(2, self.mock_volume_list.call_count) self.assertEqual(2, self.mock_volume_list.call_count)
self.assertEqual(2, self.mock_availability_zone_list.call_count) self.assertEqual(2, self.mock_availability_zone_list.call_count)
else:
self.assertEqual(2, self.mock_volume_type_list.call_count)
self.assertEqual(1, self.mock_volume_type_default.call_count)
self.assertEqual(1, self.mock_volume_list.call_count)
self.assertEqual(1, self.mock_availability_zone_list.call_count)
self.assertEqual(2, self.mock_tenant_limit_usages.call_count) self.assertEqual(2, self.mock_tenant_limit_usages.call_count)
self.mock_volume_snapshot_list.assert_called_with( self.mock_volume_snapshot_list.assert_called_with(
@ -993,14 +973,9 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
' volumes.'] ' volumes.']
self.assertEqual(res.context['form'].errors['__all__'], expected_error) self.assertEqual(res.context['form'].errors['__all__'], expected_error)
if django.VERSION >= (1, 9):
self.assertEqual(3, self.mock_volume_type_list.call_count) self.assertEqual(3, self.mock_volume_type_list.call_count)
self.assertEqual(2, self.mock_volume_type_default.call_count) self.assertEqual(2, self.mock_volume_type_default.call_count)
self.assertEqual(2, self.mock_availability_zone_list.call_count) self.assertEqual(2, self.mock_availability_zone_list.call_count)
else:
self.assertEqual(2, self.mock_volume_type_list.call_count)
self.assertEqual(1, self.mock_volume_type_default.call_count)
self.assertEqual(1, self.mock_availability_zone_list.call_count)
self.mock_volume_snapshot_list.assert_called_with( self.mock_volume_snapshot_list.assert_called_with(
test.IsHttpRequest(), search_opts=SEARCH_OPTS) test.IsHttpRequest(), search_opts=SEARCH_OPTS)

View File

@ -25,7 +25,6 @@ import os
import traceback import traceback
import unittest import unittest
import django
from django.conf import settings from django.conf import settings
from django.contrib.messages.storage import default_storage from django.contrib.messages.storage import default_storage
from django.core.handlers import wsgi from django.core.handlers import wsgi
@ -342,14 +341,10 @@ class TestCase(horizon_helpers.TestCase):
Asserts that the given response issued a 302 redirect without Asserts that the given response issued a 302 redirect without
processing the view which is redirected to. processing the view which is redirected to.
""" """
if django.VERSION >= (1, 9):
loc = six.text_type(response._headers.get('location', None)[1]) loc = six.text_type(response._headers.get('location', None)[1])
loc = http.urlunquote(loc) loc = http.urlunquote(loc)
expected_url = http.urlunquote(expected_url) expected_url = http.urlunquote(expected_url)
self.assertEqual(loc, expected_url) self.assertEqual(loc, expected_url)
else:
self.assertEqual(response._headers.get('location', None),
('Location', settings.TESTSERVER + expected_url))
self.assertEqual(response.status_code, 302) self.assertEqual(response.status_code, 302)
def assertNoFormErrors(self, response, context_name="form"): def assertNoFormErrors(self, response, context_name="form"):

View File

@ -0,0 +1,6 @@
---
upgrade:
- |
Django 2.0 support is added as experimental.
Support for Django 1.10 or older releases is dropped.
Django 1.11 (LTS) is still the primary supported Django version.