diff --git a/horizon/exceptions.py b/horizon/exceptions.py
index 68ac98cd7e..21f8a7dabd 100644
--- a/horizon/exceptions.py
+++ b/horizon/exceptions.py
@@ -40,56 +40,6 @@ class HorizonReporterFilter(SafeExceptionReporterFilter):
def is_active(self, request):
return True
- # TODO(gabriel): This bugfix is cribbed from Django's code. When 1.4.1
- # is available we can remove this code.
- def get_traceback_frame_variables(self, request, tb_frame):
- """Replaces the values of variables marked as sensitive with
- stars (*********).
- """
- # Loop through the frame's callers to see if the sensitive_variables
- # decorator was used.
- current_frame = tb_frame.f_back
- sensitive_variables = None
- while current_frame is not None:
- if (current_frame.f_code.co_name == 'sensitive_variables_wrapper'
- and 'sensitive_variables_wrapper'
- in current_frame.f_locals):
- # The sensitive_variables decorator was used, so we take note
- # of the sensitive variables' names.
- wrapper = current_frame.f_locals['sensitive_variables_wrapper']
- sensitive_variables = getattr(wrapper,
- 'sensitive_variables',
- None)
- break
- current_frame = current_frame.f_back
-
- cleansed = []
- if self.is_active(request) and sensitive_variables:
- if sensitive_variables == '__ALL__':
- # Cleanse all variables
- for name, value in tb_frame.f_locals.items():
- cleansed.append((name, CLEANSED_SUBSTITUTE))
- return cleansed
- else:
- # Cleanse specified variables
- for name, value in tb_frame.f_locals.items():
- if name in sensitive_variables:
- value = CLEANSED_SUBSTITUTE
- elif isinstance(value, HttpRequest):
- # Cleanse the request's POST parameters.
- value = self.get_request_repr(value)
- cleansed.append((name, value))
- return cleansed
- else:
- # Potentially cleanse only the request if it's one of the
- # frame variables.
- for name, value in tb_frame.f_locals.items():
- if isinstance(value, HttpRequest):
- # Cleanse the request's POST parameters.
- value = self.get_request_repr(value)
- cleansed.append((name, value))
- return cleansed
-
class HorizonException(Exception):
"""Base exception class for distinguishing our own exception classes."""
diff --git a/horizon/loaders.py b/horizon/loaders.py
index 850fa99a43..820b82a844 100644
--- a/horizon/loaders.py
+++ b/horizon/loaders.py
@@ -19,19 +19,15 @@ import os
import django
from django.conf import settings
+from django.template.engine import Engine
+from django.template.loaders.base import Loader as tLoaderCls
+from django.utils._os import safe_join # noqa
+
if django.VERSION >= (1, 9):
from django.template.exceptions import TemplateDoesNotExist
else:
from django.template.base import TemplateDoesNotExist # noqa
-if django.get_version() >= '1.8':
- from django.template.engine import Engine
- from django.template.loaders.base import Loader as tLoaderCls
-else:
- from django.template.loader import BaseLoader as tLoaderCls # noqa
-
-from django.utils._os import safe_join # noqa
-
# Set up a cache of the panel directories to search.
panel_template_dirs = {}
@@ -65,8 +61,5 @@ class TemplateLoader(tLoaderCls):
raise TemplateDoesNotExist(template_name)
-if django.get_version() >= '1.8':
- e = Engine()
- _loader = TemplateLoader(e)
-else:
- _loader = TemplateLoader()
+e = Engine()
+_loader = TemplateLoader(e)
diff --git a/horizon/test/patches.py b/horizon/test/patches.py
deleted file mode 100644
index f94714e56b..0000000000
--- a/horizon/test/patches.py
+++ /dev/null
@@ -1,71 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import re
-
-from six.moves import html_parser as _HTMLParser
-
-
-def parse_starttag_patched(self, i):
- """This method is a patched version of the parse_starttag method from
- django.utils.html_parser.HTMLParser class, used to patch bug 1273943.
- The code is taken from file django/utils/html_parser.py, commit 6bc1b22299.
- """
- self.__starttag_text = None
- endpos = self.check_for_whole_start_tag(i)
- if endpos < 0:
- return endpos
- rawdata = self.rawdata
- self.__starttag_text = rawdata[i:endpos]
-
- # Now parse the data between i+1 and j into a tag and attrs
- attrs = []
- tagfind = re.compile('([a-zA-Z][-.a-zA-Z0-9:_]*)(?:\s|/(?!>))*')
- match = tagfind.match(rawdata, i + 1)
- assert match, 'unexpected call to parse_starttag()'
- k = match.end()
- self.lasttag = tag = match.group(1).lower()
-
- while k < endpos:
- m = _HTMLParser.attrfind.match(rawdata, k)
- if not m:
- break
- attrname, rest, attrvalue = m.group(1, 2, 3)
- if not rest:
- attrvalue = None
- elif (attrvalue[:1] == '\'' == attrvalue[-1:] or
- attrvalue[:1] == '"' == attrvalue[-1:]):
- attrvalue = attrvalue[1:-1]
- if attrvalue:
- attrvalue = self.unescape(attrvalue)
- attrs.append((attrname.lower(), attrvalue))
- k = m.end()
-
- end = rawdata[k:endpos].strip()
- if end not in (">", "/>"):
- lineno, offset = self.getpos()
- if "\n" in self.__starttag_text:
- lineno = lineno + self.__starttag_text.count("\n")
- offset = (len(self.__starttag_text)
- - self.__starttag_text.rfind("\n"))
- else:
- offset = offset + len(self.__starttag_text)
- self.error("junk characters in start tag: %r"
- % (rawdata[k:endpos][:20],))
- if end.endswith('/>'):
- # XHTML-style empty tag:
- self.handle_startendtag(tag, attrs)
- else:
- self.handle_starttag(tag, attrs)
- if tag in self.CDATA_CONTENT_ELEMENTS:
- self.set_cdata_mode(tag) # <--------------------------- Changed
- return endpos
diff --git a/horizon/test/settings.py b/horizon/test/settings.py
index 146d0fc1f1..e231348fdd 100644
--- a/horizon/test/settings.py
+++ b/horizon/test/settings.py
@@ -18,20 +18,11 @@
import os
import socket
-import sys
-import django
-from django.utils import html_parser
from openstack_dashboard.static_settings import get_staticfiles_dirs # noqa
-from horizon.test import patches
-
STATICFILES_DIRS = get_staticfiles_dirs()
-# Patch django.utils.html_parser.HTMLParser as a workaround for bug 1273943
-if django.get_version() == '1.4' and sys.version_info[:3] > (2, 7, 3):
- html_parser.HTMLParser.parse_starttag = patches.parse_starttag_patched
-
socket.setdefaulttimeout(1)
LOGIN_URL = '/auth/login/'
@@ -77,13 +68,7 @@ MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
-)
-if django.VERSION >= (1, 8, 0):
- MIDDLEWARE_CLASSES += (
- 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',)
-else:
- MIDDLEWARE_CLASSES += ('django.middleware.doc.XViewMiddleware',)
-MIDDLEWARE_CLASSES += (
+ 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'horizon.middleware.HorizonMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
diff --git a/horizon/utils/urlresolvers.py b/horizon/utils/urlresolvers.py
deleted file mode 100644
index 2f9d02a463..0000000000
--- a/horizon/utils/urlresolvers.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright 2012 Nebula, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import six
-
-from django.core.urlresolvers import reverse as django_reverse
-from django.utils.http import urlquote # noqa
-from django import VERSION # noqa
-
-
-def reverse(viewname, urlconf=None, args=None, kwargs=None, prefix=None,
- current_app=None):
- if VERSION < (1, 6):
- if args:
- args = [urlquote(x) for x in args]
- if kwargs:
- kwargs = dict([(x, urlquote(y)) for x, y in six.iteritems(kwargs)])
- return django_reverse(viewname, urlconf, args, kwargs, prefix,
- current_app)
diff --git a/openstack_dashboard/dashboards/identity/projects/tests.py b/openstack_dashboard/dashboards/identity/projects/tests.py
index d58287bd99..3eb85747d9 100644
--- a/openstack_dashboard/dashboards/identity/projects/tests.py
+++ b/openstack_dashboard/dashboards/identity/projects/tests.py
@@ -18,7 +18,6 @@ import logging
import os
import unittest
-import django
from django.core.urlresolvers import reverse
from django import http
from django.test.utils import override_settings
@@ -266,18 +265,11 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
res = self.client.get(reverse('horizon:identity:projects:create'))
self.assertTemplateUsed(res, views.WorkflowView.template_name)
- if django.VERSION >= (1, 6):
- self.assertContains(res, '''
-
- ''', html=True)
- else:
- self.assertContains(res, '''
-
- ''', html=True)
+ self.assertContains(res, '''
+
+ ''', html=True)
workflow = res.context['workflow']
self.assertEqual(res.context['workflow'].name,
@@ -1463,11 +1455,6 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
self.assertMessageCount(error=2, warning=1)
self.assertRedirectsNoFollow(res, INDEX_URL)
- # django 1.7 and later does not handle the thrown keystoneclient
- # exception well enough.
- # TODO(mrunge): re-check when django-1.8 is stable
- @unittest.skipIf(django.VERSION >= (1, 7, 0),
- 'Currently skipped with Django >= 1.7')
@test.create_stubs({api.keystone: ('get_default_role',
'tenant_get',
'domain_get'),
diff --git a/openstack_dashboard/dashboards/identity/users/forms.py b/openstack_dashboard/dashboards/identity/users/forms.py
index c227ec44a1..bbaebbe580 100644
--- a/openstack_dashboard/dashboards/identity/users/forms.py
+++ b/openstack_dashboard/dashboards/identity/users/forms.py
@@ -19,7 +19,6 @@
import collections
import logging
-import django
from django.conf import settings
from django.forms import ValidationError # noqa
from django import http
@@ -118,13 +117,8 @@ class CreateUserForm(PasswordMixin, BaseUserForm):
"description", "email", "password",
"confirm_password", "project", "role_id",
"enabled"]
- # Starting from 1.7 Django uses OrderedDict for fields and keyOrder
- # no longer works for it
- if django.VERSION >= (1, 7):
- self.fields = collections.OrderedDict(
- (key, self.fields[key]) for key in ordering)
- else:
- self.fields.keyOrder = ordering
+ self.fields = collections.OrderedDict(
+ (key, self.fields[key]) for key in ordering)
role_choices = [(role.id, role.name) for role in roles]
self.fields['role_id'].choices = role_choices
diff --git a/openstack_dashboard/dashboards/project/containers/tables.py b/openstack_dashboard/dashboards/project/containers/tables.py
index 04ae578fff..fef97c5842 100644
--- a/openstack_dashboard/dashboards/project/containers/tables.py
+++ b/openstack_dashboard/dashboards/project/containers/tables.py
@@ -13,8 +13,8 @@
# under the License.
import logging
-import django
from django.conf import settings
+from django.core.urlresolvers import reverse
from django import shortcuts
from django import template
from django.template import defaultfilters as filters
@@ -26,27 +26,16 @@ from django.utils.translation import ungettext_lazy
from horizon import exceptions
from horizon import messages
from horizon import tables
-from horizon.utils.urlresolvers import reverse # noqa
from openstack_dashboard import api
from openstack_dashboard.api import swift
from openstack_dashboard.dashboards.project.containers import utils
-
LOG = logging.getLogger(__name__)
static_url = getattr(settings, 'STATIC_URL', '/static/')
LOADING_IMAGE = '' % static_url
-def _escape_full_url(url):
- # NOTE (lhcheng): In Django 1.8, HttpRequest.get_full_path()
- # method now escapes unsafe characters
- # TODO(robcresswell): Remove in M, once django 1.7 is dropped
- if django.VERSION < (1, 8):
- return http.urlquote(url)
- return url
-
-
class ViewContainer(tables.LinkAction):
name = "view"
verbose_name = _("View Details")
@@ -292,21 +281,6 @@ class ContainersTable(tables.DataTable):
def get_object_id(self, container):
return container.name
- def get_absolute_url(self):
- url = super(ContainersTable, self).get_absolute_url()
- return _escape_full_url(url)
-
- def get_full_url(self):
- """Returns the encoded absolute URL path with its query string.
-
- This is used for the POST action attribute on the form element
- wrapping the table. We use this method to persist the
- pagination marker.
-
- """
- url = super(ContainersTable, self).get_full_url()
- return _escape_full_url(url)
-
class ViewObject(tables.LinkAction):
name = "view"
@@ -361,10 +335,6 @@ class DeleteObject(tables.DeleteAction):
obj_id = obj_id[(len(container_name) + 1):] + "/"
api.swift.swift_delete_object(request, container_name, obj_id)
- def get_success_url(self, request):
- url = super(DeleteObject, self).get_success_url(request)
- return _escape_full_url(url)
-
class DeleteMultipleObjects(DeleteObject):
name = "delete_multiple_objects"
@@ -462,18 +432,3 @@ class ObjectsTable(tables.DataTable):
data_types = ("subfolders", "objects")
browser_table = "content"
footer = False
-
- def get_absolute_url(self):
- url = super(ObjectsTable, self).get_absolute_url()
- return _escape_full_url(url)
-
- def get_full_url(self):
- """Returns the encoded absolute URL path with its query string.
-
- This is used for the POST action attribute on the form element
- wrapping the table. We use this method to persist the
- pagination marker.
-
- """
- url = super(ObjectsTable, self).get_full_url()
- return _escape_full_url(url)
diff --git a/openstack_dashboard/dashboards/project/containers/tests.py b/openstack_dashboard/dashboards/project/containers/tests.py
index a85fdb31be..109ed79547 100644
--- a/openstack_dashboard/dashboards/project/containers/tests.py
+++ b/openstack_dashboard/dashboards/project/containers/tests.py
@@ -19,8 +19,8 @@
import copy
import tempfile
-import django
from django.core.files.uploadedfile import InMemoryUploadedFile # noqa
+from django.core.urlresolvers import reverse
from django import http
from django.utils import http as utils_http
@@ -34,9 +34,6 @@ from openstack_dashboard.dashboards.project.containers import utils
from openstack_dashboard.dashboards.project.containers import views
from openstack_dashboard.test import helpers as test
-from horizon.utils.urlresolvers import reverse # noqa
-
-
CONTAINER_NAME_1 = u"container one%\u6346"
CONTAINER_NAME_2 = u"container_two\u6346"
CONTAINER_NAME_1_QUOTED = utils_http.urlquote(CONTAINER_NAME_1)
@@ -356,14 +353,9 @@ class SwiftTests(test.TestCase):
res = self.client.get(download_url)
self.assertTrue(res.has_header('Content-Disposition'))
- if django.VERSION >= (1, 5):
- self.assertEqual(b''.join(res.streaming_content), _data)
- self.assertNotContains(res, INVALID_CONTAINER_NAME_1)
- self.assertNotContains(res, INVALID_CONTAINER_NAME_2)
- else:
- self.assertEqual(res.content, _data)
- self.assertNotContains(res, INVALID_CONTAINER_NAME_1)
- self.assertNotContains(res, INVALID_CONTAINER_NAME_2)
+ self.assertEqual(b''.join(res.streaming_content), _data)
+ self.assertNotContains(res, INVALID_CONTAINER_NAME_1)
+ self.assertNotContains(res, INVALID_CONTAINER_NAME_2)
# Check that the returned Content-Disposition filename is well
# surrounded by double quotes and with commas removed
diff --git a/openstack_dashboard/dashboards/project/containers/views.py b/openstack_dashboard/dashboards/project/containers/views.py
index 78021ee486..99b4889e50 100644
--- a/openstack_dashboard/dashboards/project/containers/views.py
+++ b/openstack_dashboard/dashboards/project/containers/views.py
@@ -22,6 +22,7 @@ Views for managing Swift containers.
import os
+from django.core.urlresolvers import reverse
from django import http
from django.utils.functional import cached_property # noqa
from django.utils.translation import ugettext_lazy as _
@@ -32,7 +33,6 @@ from horizon import browsers
from horizon import exceptions
from horizon import forms
from horizon.utils import memoized
-from horizon.utils.urlresolvers import reverse # noqa
from openstack_dashboard import api
from openstack_dashboard.api import swift
diff --git a/openstack_dashboard/dashboards/project/stacks/tests.py b/openstack_dashboard/dashboards/project/stacks/tests.py
index fa3d55b42f..a8168772c5 100644
--- a/openstack_dashboard/dashboards/project/stacks/tests.py
+++ b/openstack_dashboard/dashboards/project/stacks/tests.py
@@ -13,7 +13,6 @@
import json
import re
-import django
from django.conf import settings
from django.core import exceptions
from django.core.urlresolvers import reverse
@@ -565,18 +564,11 @@ class StackTests(test.TestCase):
'id="id___param_param1" '
'name="__param_param1" '
'type="text" />', html=True)
- if django.VERSION >= (1, 6):
- self.assertContains(res,
- '', html=True)
- else:
- self.assertContains(res,
- '', html=True)
+ self.assertContains(res,
+ '', html=True)
self.assertContains(res,
'= (1, 6):
- msg = (u"The volume size cannot be less than the "
- u"image size (20.0\xa0GB)")
- else:
- msg = (u"The volume size cannot be less than the "
- u"image size (20.0 GB)")
+ msg = (u"The volume size cannot be less than the "
+ u"image size (20.0\xa0GB)")
self.assertFormError(res, 'form', None, msg)
diff --git a/openstack_dashboard/settings.py b/openstack_dashboard/settings.py
index 9c82c3cfc5..4ff22b0a91 100644
--- a/openstack_dashboard/settings.py
+++ b/openstack_dashboard/settings.py
@@ -21,7 +21,6 @@ import os
import sys
import warnings
-import django
from django.utils.translation import ugettext_lazy as _
from openstack_dashboard import exceptions
@@ -104,13 +103,7 @@ MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
-)
-if django.VERSION >= (1, 8, 0):
- MIDDLEWARE_CLASSES += (
- 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',)
-else:
- MIDDLEWARE_CLASSES += ('django.middleware.doc.XViewMiddleware',)
-MIDDLEWARE_CLASSES += (
+ 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'horizon.middleware.HorizonMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',