From 397b7305df5f6fa70fcca8c8ec812768494c7c0c Mon Sep 17 00:00:00 2001 From: Thomas Goirand Date: Thu, 18 Feb 2016 16:54:58 +0000 Subject: [PATCH] Added patch: Fix_remaining_Django_1.9_test_failures.patch Rewritten-From: cf4eab3c948858d3192b92414a35401c422d5ad5 --- trusty/debian/changelog | 1 + .../0090-explicitly-declare-app_label.patch | 20 +- ...x_remaining_Django_1.9_test_failures.patch | 378 ++++++++++++++++++ trusty/debian/patches/series | 1 + 4 files changed, 393 insertions(+), 7 deletions(-) create mode 100644 trusty/debian/patches/Fix_remaining_Django_1.9_test_failures.patch diff --git a/trusty/debian/changelog b/trusty/debian/changelog index f996935..4eeb804 100644 --- a/trusty/debian/changelog +++ b/trusty/debian/changelog @@ -5,6 +5,7 @@ horizon (2:9.0.0~b2+2016.02.18.git.cda9604792-1) experimental; urgency=medium * Added patch: Provide_2_simple_methods_to_check_for_disabled_panels.patch * Added patch: 0100-add-openstack_auth-in-INSTALLED_APPS.patch * Added patch: 0090-explicitly-declare-app_label.patch + * Added patch: Fix_remaining_Django_1.9_test_failures.patch -- Thomas Goirand Wed, 09 Dec 2015 11:37:40 +0100 diff --git a/trusty/debian/patches/0090-explicitly-declare-app_label.patch b/trusty/debian/patches/0090-explicitly-declare-app_label.patch index 9d4a73f..4c7e3b3 100644 --- a/trusty/debian/patches/0090-explicitly-declare-app_label.patch +++ b/trusty/debian/patches/0090-explicitly-declare-app_label.patch @@ -3,24 +3,30 @@ Author: Thomas Goirand Forwarded: no Last-Update: 2016-02-19 ---- horizon-9.0.0~b2+2016.02.18.git.cda9604792.orig/horizon/test/settings.py -+++ horizon-9.0.0~b2+2016.02.18.git.cda9604792/horizon/test/settings.py -@@ -170,3 +170,5 @@ LOGGING = { +Index: horizon/horizon/test/settings.py +=================================================================== +--- horizon.orig/horizon/test/settings.py ++++ horizon/horizon/test/settings.py +@@ -169,3 +169,5 @@ LOGGING = { } } } + +APP_LABEL = 'horizon' ---- horizon-9.0.0~b2+2016.02.18.git.cda9604792.orig/openstack_dashboard/local/local_settings.py.example -+++ horizon-9.0.0~b2+2016.02.18.git.cda9604792/openstack_dashboard/local/local_settings.py.example +Index: horizon/openstack_dashboard/local/local_settings.py.example +=================================================================== +--- horizon.orig/openstack_dashboard/local/local_settings.py.example ++++ horizon/openstack_dashboard/local/local_settings.py.example @@ -710,3 +710,5 @@ REST_API_REQUIRED_SETTINGS = ['OPENSTACK # For more information see: # http://tinyurl.com/anticlickjack #DISALLOW_IFRAME_EMBED = True + +APP_LABEL = 'horizon' ---- horizon-9.0.0~b2+2016.02.18.git.cda9604792.orig/openstack_dashboard/test/settings.py -+++ horizon-9.0.0~b2+2016.02.18.git.cda9604792/openstack_dashboard/test/settings.py +Index: horizon/openstack_dashboard/test/settings.py +=================================================================== +--- horizon.orig/openstack_dashboard/test/settings.py ++++ horizon/openstack_dashboard/test/settings.py @@ -232,3 +232,5 @@ REST_API_SETTING_2 = 'bar' REST_API_SECURITY = 'SECURITY' REST_API_REQUIRED_SETTINGS = ['REST_API_SETTING_1'] diff --git a/trusty/debian/patches/Fix_remaining_Django_1.9_test_failures.patch b/trusty/debian/patches/Fix_remaining_Django_1.9_test_failures.patch new file mode 100644 index 0000000..a9fc59d --- /dev/null +++ b/trusty/debian/patches/Fix_remaining_Django_1.9_test_failures.patch @@ -0,0 +1,378 @@ +Subject: [PATCH] [WIP] Fix remaining Django 1.9 test failures + This patch gets Horizon to a passing state in the Django 1.9 tests +Author: Rob Cresswell +Date: Thu, 11 Feb 2016 14:45:32 +0000 +Co-Authored-By: Itxaka +Change-Id: Icbc1a3c039de658faa9fba4a2cdd5027345fe94d +Partially-Implements: blueprint drop-dj17 +Origin: upstream, https://review.openstack.org/#/c/280222/ +Last-Update: 2016-02-19 + +--- horizon-9.0.0~b2+2016.02.18.git.cda9604792.orig/horizon/forms/base.py ++++ horizon-9.0.0~b2+2016.02.18.git.cda9604792/horizon/forms/base.py +@@ -41,7 +41,7 @@ class SelfHandlingForm(SelfHandlingMixin + wish for API errors to appear as errors on the form rather than + using the messages framework. + """ +- self._errors[NON_FIELD_ERRORS] = self.error_class([message]) ++ self.add_error(NON_FIELD_ERRORS, message) + + def set_warning(self, message): + """Sets a warning on the form. +--- horizon-9.0.0~b2+2016.02.18.git.cda9604792.orig/horizon/test/settings.py ++++ horizon-9.0.0~b2+2016.02.18.git.cda9604792/horizon/test/settings.py +@@ -59,7 +59,8 @@ INSTALLED_APPS = ( + 'horizon', + 'horizon.test', + 'horizon.test.test_dashboards.cats', +- 'horizon.test.test_dashboards.dogs' ++ 'horizon.test.test_dashboards.dogs', ++ 'openstack_auth' + ) + + MIDDLEWARE_CLASSES = ( +--- horizon-9.0.0~b2+2016.02.18.git.cda9604792.orig/horizon/test/tests/base.py ++++ horizon-9.0.0~b2+2016.02.18.git.cda9604792/horizon/test/tests/base.py +@@ -17,6 +17,7 @@ + # License for the specific language governing permissions and limitations + # under the License. + ++import django + from django.conf import settings + from django.contrib.auth.models import User # noqa + from django.core.exceptions import ImproperlyConfigured # noqa +@@ -308,7 +309,10 @@ class HorizonTests(BaseHorizonTests): + + self.client.logout() + resp = self.client.get(url) +- self.assertRedirects(resp, redirect_url) ++ if django.VERSION >= (1, 9): ++ self.assertRedirects(resp, settings.TESTSERVER + redirect_url) ++ else: ++ self.assertRedirects(resp, redirect_url) + + # Set SSL settings for test server + settings.SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', +--- horizon-9.0.0~b2+2016.02.18.git.cda9604792.orig/horizon/test/tests/forms.py ++++ horizon-9.0.0~b2+2016.02.18.git.cda9604792/horizon/test/tests/forms.py +@@ -27,6 +27,8 @@ class FormMixinTests(test.TestCase): + view.args = args + view.kwargs = kwargs + view.template_name = 'test_template' ++ # Note(Itxaka): ModalFormView requires a form_class to behave properly ++ view.form_class = TestForm + return view + + def test_modal_form_mixin_hide_true_if_ajax(self): +@@ -80,7 +82,9 @@ class FormErrorTests(test.TestCase): + + def setUp(self): + super(FormErrorTests, self).setUp() +- self.form = TestForm(self.request) ++ # Note(Itxaka): We pass data to the form so its bound and has the ++ # proper cleaned_data fields ++ self.form = TestForm(self.request, data={'fake': 'data'}) + + def _render_form(self): + return shortcuts.render(self.request, self.template, +--- horizon-9.0.0~b2+2016.02.18.git.cda9604792.orig/horizon/test/tests/middleware.py ++++ horizon-9.0.0~b2+2016.02.18.git.cda9604792/horizon/test/tests/middleware.py +@@ -13,8 +13,8 @@ + # License for the specific language governing permissions and limitations + # under the License. + ++import django + from django.conf import settings +- + from django.http import HttpResponseRedirect # noqa + + from horizon import exceptions +@@ -31,7 +31,10 @@ class MiddlewareTests(test.TestCase): + resp = mw.process_exception(request, exceptions.NotAuthorized()) + resp.client = self.client + +- self.assertRedirects(resp, url) ++ if django.VERSION >= (1, 9): ++ self.assertRedirects(resp, settings.TESTSERVER + url) ++ else: ++ self.assertRedirects(resp, url) + + def test_process_response_redirect_on_ajax_request(self): + url = settings.LOGIN_URL +--- horizon-9.0.0~b2+2016.02.18.git.cda9604792.orig/openstack_dashboard/dashboards/admin/networks/tests.py ++++ horizon-9.0.0~b2+2016.02.18.git.cda9604792/openstack_dashboard/dashboards/admin/networks/tests.py +@@ -390,8 +390,9 @@ class NetworkTests(test.BaseAdminViewTes + tenant_id = self.tenants.first().id + network = self.networks.first() + extensions = self.api_extensions.list() +- api.keystone.tenant_list(IsA(http.HttpRequest)).AndReturn([tenants, +- False]) ++ api.keystone.tenant_list( ++ IsA(http.HttpRequest) ++ ).MultipleTimes().AndReturn([tenants, False]) + api.neutron.list_extensions( + IsA(http.HttpRequest)).AndReturn(extensions) + self.mox.ReplayAll() +@@ -417,8 +418,11 @@ class NetworkTests(test.BaseAdminViewTes + tenant_id = self.tenants.first().id + network = self.networks.first() + extensions = self.api_extensions.list() +- api.keystone.tenant_list(IsA(http.HttpRequest)).AndReturn([tenants, +- False]) ++ ++ api.keystone.tenant_list( ++ IsA(http.HttpRequest) ++ ).MultipleTimes().AndReturn([tenants, False]) ++ + api.neutron.list_extensions( + IsA(http.HttpRequest)).AndReturn(extensions) + self.mox.ReplayAll() +@@ -447,8 +451,10 @@ class NetworkTests(test.BaseAdminViewTes + tenant_id = self.tenants.first().id + network = self.networks.first() + extensions = self.api_extensions.list() +- api.keystone.tenant_list(IsA(http.HttpRequest)).AndReturn([tenants, +- False]) ++ api.keystone.tenant_list( ++ IsA(http.HttpRequest) ++ ).MultipleTimes().AndReturn([tenants, False]) ++ + api.neutron.list_extensions( + IsA(http.HttpRequest)).AndReturn(extensions) + self.mox.ReplayAll() +--- horizon-9.0.0~b2+2016.02.18.git.cda9604792.orig/openstack_dashboard/dashboards/admin/volumes/tabs.py ++++ horizon-9.0.0~b2+2016.02.18.git.cda9604792/openstack_dashboard/dashboards/admin/volumes/tabs.py +@@ -36,7 +36,7 @@ class VolumeTab(volumes_tabs.PagedTableM + name = _("Volumes") + slug = "volumes_tab" + template_name = "admin/volumes/volumes/volumes_tables.html" +- preload = False ++ preload = True + + def get_volumes_data(self): + volumes = self._get_volumes(search_opts={'all_tenants': True}) +@@ -69,7 +69,7 @@ class VolumeTypesTab(tabs.TableTab, volu + name = _("Volume Types") + slug = "volume_types_tab" + template_name = "admin/volumes/volume_types/volume_types_tables.html" +- preload = False ++ preload = True + + def get_volume_types_data(self): + try: +@@ -116,7 +116,7 @@ class SnapshotTab(volumes_tabs.PagedTabl + name = _("Volume Snapshots") + slug = "snapshots_tab" + template_name = ("horizon/common/_detail_table.html") +- preload = False ++ preload = True + + def get_volume_snapshots_data(self): + if api.base.is_service_enabled(self.request, 'volume'): +--- horizon-9.0.0~b2+2016.02.18.git.cda9604792.orig/openstack_dashboard/dashboards/admin/volumes/tests.py ++++ horizon-9.0.0~b2+2016.02.18.git.cda9604792/openstack_dashboard/dashboards/admin/volumes/tests.py +@@ -181,7 +181,7 @@ class VolumeTests(test.BaseAdminViewTest + def test_snapshots_tab(self): + cinder.volume_snapshot_list_paged( + IsA(http.HttpRequest), paginate=True, marker=None, sort_dir='desc', +- search_opts={'all_tenants': True},).AndReturn( ++ search_opts={'all_tenants': True},).MultipleTimes().AndReturn( + [self.cinder_volume_snapshots.list(), False, False]) + cinder.volume_list(IsA(http.HttpRequest), search_opts={ + 'all_tenants': True}).\ +--- horizon-9.0.0~b2+2016.02.18.git.cda9604792.orig/openstack_dashboard/dashboards/project/stacks/forms.py ++++ horizon-9.0.0~b2+2016.02.18.git.cda9604792/openstack_dashboard/dashboards/project/stacks/forms.py +@@ -13,6 +13,7 @@ + import json + import logging + ++import django + from django.conf import settings + from django.utils import html + from django.utils.translation import ugettext_lazy as _ +@@ -125,6 +126,13 @@ class TemplateForm(forms.SelfHandlingFor + widget=forms.widgets.Textarea(attrs=attributes), + required=False) + ++ if django.VERSION >= (1, 9): ++ # Note(Itxaka): On django>=1.9 Charfield has an strip option that ++ # we need to set to False as to not hit ++ # https://bugs.launchpad.net/python-heatclient/+bug/1546166 ++ environment_data.strip = False ++ template_data.strip = False ++ + def __init__(self, *args, **kwargs): + self.next_view = kwargs.pop('next_view') + super(TemplateForm, self).__init__(*args, **kwargs) +@@ -252,6 +260,12 @@ class CreateStackForm(forms.SelfHandling + environment_data = forms.CharField( + widget=forms.widgets.HiddenInput, + required=False) ++ if django.VERSION >= (1, 9): ++ # Note(Itxaka): On django>=1.9 Charfield has an strip option that ++ # we need to set to False as to not hit ++ # https://bugs.launchpad.net/python-heatclient/+bug/1546166 ++ environment_data.strip = False ++ + parameters = forms.CharField( + widget=forms.widgets.HiddenInput) + stack_name = forms.RegexField( +--- horizon-9.0.0~b2+2016.02.18.git.cda9604792.orig/openstack_dashboard/dashboards/project/volumes/backups/tests.py ++++ horizon-9.0.0~b2+2016.02.18.git.cda9604792/openstack_dashboard/dashboards/project/volumes/backups/tests.py +@@ -70,21 +70,17 @@ class VolumeBackupsViewTests(test.TestCa + AndReturn(volumes) + api.cinder.volume_backup_delete(IsA(http.HttpRequest), backup.id) + +- api.cinder.volume_backup_list_paged( +- IsA(http.HttpRequest), marker=None, sort_dir='desc', +- paginate=True).AndReturn([vol_backups, False, False]) +- api.cinder.volume_list(IsA(http.HttpRequest)). \ +- AndReturn(volumes) + self.mox.ReplayAll() + + formData = {'action': + 'volume_backups__delete__%s' % backup.id} + res = self.client.post(INDEX_URL + + "?tab=volumes_and_snapshots__backups_tab", +- formData, follow=True) ++ formData) + +- self.assertIn("Scheduled deletion of Volume Backup: backup1", +- [m.message for m in res.context['messages']]) ++ self.assertRedirectsNoFollow(res, INDEX_URL + ++ "?tab=volumes_and_snapshots__backups_tab") ++ self.assertMessageCount(success=1) + + @test.create_stubs({api.cinder: ('volume_backup_get', 'volume_get')}) + def test_volume_backup_detail_get(self): +--- horizon-9.0.0~b2+2016.02.18.git.cda9604792.orig/openstack_dashboard/dashboards/project/volumes/snapshots/tests.py ++++ horizon-9.0.0~b2+2016.02.18.git.cda9604792/openstack_dashboard/dashboards/project/volumes/snapshots/tests.py +@@ -108,7 +108,8 @@ class VolumeSnapshotsViewTests(test.Test + @test.create_stubs({api.cinder: ('volume_snapshot_list_paged', + 'volume_list', + 'volume_backup_supported', +- 'volume_snapshot_delete')}) ++ 'volume_snapshot_delete', ++ 'tenant_absolute_limits')}) + def test_delete_volume_snapshot(self): + vol_snapshots = self.cinder_volume_snapshots.list() + volumes = self.cinder_volumes.list() +@@ -123,19 +124,14 @@ class VolumeSnapshotsViewTests(test.Test + AndReturn(volumes) + + api.cinder.volume_snapshot_delete(IsA(http.HttpRequest), snapshot.id) +- api.cinder.volume_snapshot_list_paged( +- IsA(http.HttpRequest), paginate=True, marker=None, +- sort_dir='desc').AndReturn([[], False, False]) +- api.cinder.volume_list(IsA(http.HttpRequest)). \ +- AndReturn(volumes) + self.mox.ReplayAll() + + formData = {'action': + 'volume_snapshots__delete__%s' % snapshot.id} +- res = self.client.post(VOLUME_SNAPSHOTS_TAB_URL, formData, follow=True) ++ res = self.client.post(VOLUME_SNAPSHOTS_TAB_URL, formData) + +- self.assertIn("Scheduled deletion of Volume Snapshot: test snapshot", +- [m.message for m in res.context['messages']]) ++ self.assertRedirectsNoFollow(res, VOLUME_SNAPSHOTS_TAB_URL) ++ self.assertMessageCount(success=1) + + @test.create_stubs({api.cinder: ('volume_snapshot_get', 'volume_get')}) + def test_volume_snapshot_detail_get(self): +--- horizon-9.0.0~b2+2016.02.18.git.cda9604792.orig/openstack_dashboard/dashboards/project/volumes/tabs.py ++++ horizon-9.0.0~b2+2016.02.18.git.cda9604792/openstack_dashboard/dashboards/project/volumes/tabs.py +@@ -119,7 +119,7 @@ class VolumeTab(PagedTableMixin, tabs.Ta + name = _("Volumes") + slug = "volumes_tab" + template_name = ("horizon/common/_detail_table.html") +- preload = False ++ preload = True + + def get_volumes_data(self): + volumes = self._get_volumes() +@@ -135,7 +135,7 @@ class SnapshotTab(PagedTableMixin, tabs. + name = _("Volume Snapshots") + slug = "snapshots_tab" + template_name = ("horizon/common/_detail_table.html") +- preload = False ++ preload = True + + def get_volume_snapshots_data(self): + try: +@@ -155,7 +155,6 @@ class SnapshotTab(PagedTableMixin, tabs. + for snapshot in snapshots: + volume = volumes.get(snapshot.volume_id) + setattr(snapshot, '_volume', volume) +- + return snapshots + + +@@ -164,7 +163,7 @@ class BackupsTab(PagedTableMixin, tabs.T + name = _("Volume Backups") + slug = "backups_tab" + template_name = ("horizon/common/_detail_table.html") +- preload = False ++ preload = True + + def allowed(self, request): + return api.cinder.volume_backup_supported(self.request) +--- horizon-9.0.0~b2+2016.02.18.git.cda9604792.orig/openstack_dashboard/settings.py ++++ horizon-9.0.0~b2+2016.02.18.git.cda9604792/openstack_dashboard/settings.py +@@ -351,8 +351,14 @@ settings.update_dashboards( + ) + INSTALLED_APPS[0:0] = ADD_INSTALLED_APPS + +-from openstack_auth import policy +-POLICY_CHECK_FUNCTION = policy.check ++ ++def check(actions, request, target=None): ++ # Note(Itxaka): This is to prevent circular dependencies and apps not ready ++ # If you do django imports in your settings, you are gonna have a bad time ++ from openstack_auth import policy ++ return policy.check(actions, request, target=None) ++ ++POLICY_CHECK_FUNCTION = check + + # Add HORIZON_CONFIG to the context information for offline compression + COMPRESS_OFFLINE_CONTEXT = { +@@ -364,11 +370,14 @@ COMPRESS_OFFLINE_CONTEXT = { + if DEBUG: + logging.basicConfig(level=logging.DEBUG) + ++# Note(Itxaka): This does not work due the apps not ready when importing ++# auth_utils + # during django reloads and an active user is logged in, the monkey + # patch below will not otherwise be applied in time - resulting in developers + # appearing to be logged out. In typical production deployments this section + # below may be omitted, though it should not be harmful +-from openstack_auth import utils as auth_utils +-auth_utils.patch_middleware_get_user() ++# ++# from openstack_auth import utils as auth_utils ++# auth_utils.patch_middleware_get_user() + + CSRF_COOKIE_AGE = None +--- horizon-9.0.0~b2+2016.02.18.git.cda9604792.orig/openstack_dashboard/test/helpers.py ++++ horizon-9.0.0~b2+2016.02.18.git.cda9604792/openstack_dashboard/test/helpers.py +@@ -29,6 +29,7 @@ from django.core.handlers import wsgi + from django.core import urlresolvers + from django.test.client import RequestFactory # noqa + from django.test import utils as django_test_utils ++from django.utils import http + + from ceilometerclient.v2 import client as ceilometer_client + from cinderclient import client as cinder_client +@@ -232,8 +233,10 @@ class TestCase(horizon_helpers.TestCase) + processing the view which is redirected to. + """ + if django.VERSION >= (1, 9): +- self.assertEqual(response._headers.get('location', None), +- ('Location', expected_url)) ++ loc = six.text_type(response._headers.get('location', None)[1]) ++ loc = http.urlunquote(loc) ++ expected_url = http.urlunquote(expected_url) ++ self.assertEqual(loc, expected_url) + else: + self.assertEqual(response._headers.get('location', None), + ('Location', settings.TESTSERVER + expected_url)) diff --git a/trusty/debian/patches/series b/trusty/debian/patches/series index d46912c..292da86 100644 --- a/trusty/debian/patches/series +++ b/trusty/debian/patches/series @@ -5,3 +5,4 @@ enable_identity_users_panel.patch #Provide_2_simple_methods_to_check_for_disabled_panels.patch #0100-add-openstack_auth-in-INSTALLED_APPS.patch 0090-explicitly-declare-app_label.patch +Fix_remaining_Django_1.9_test_failures.patch -- 2.45.2