Fix UTF-8 handling in tables
Previous fix was not complete. Altered the transform for sequence comparison to use str instead of repr for greater py2/py3 compatibility in the face of unicode. Closes-Bug: #1488443 Related-Bug: #1464461 Co-Authored-By: Richard Jones <r1chardj0n3s@gmail.com> Change-Id: I6b2c554350399f97f639e4c1e8d1ac8a34c9d046
This commit is contained in:
parent
079a47a5cd
commit
6a8361de94
@ -812,7 +812,7 @@ class BatchAction(Action):
|
||||
datum_display = table.get_object_display(datum) or datum_id
|
||||
if not table._filter_action(self, request, datum):
|
||||
action_not_allowed.append(datum_display)
|
||||
LOG.warning('Permission denied to %s: "%s"' %
|
||||
LOG.warning(u'Permission denied to %s: "%s"' %
|
||||
(self._get_action_name(past=True).lower(),
|
||||
datum_display))
|
||||
continue
|
||||
@ -822,7 +822,7 @@ class BatchAction(Action):
|
||||
self.update(request, datum)
|
||||
action_success.append(datum_display)
|
||||
self.success_ids.append(datum_id)
|
||||
LOG.info('%s: "%s"' %
|
||||
LOG.info(u'%s: "%s"' %
|
||||
(self._get_action_name(past=True), datum_display))
|
||||
except Exception as ex:
|
||||
# Handle the exception but silence it since we'll display
|
||||
|
@ -1,3 +1,5 @@
|
||||
# encoding=utf-8
|
||||
#
|
||||
# Copyright 2012 Nebula, Inc.
|
||||
# Copyright 2014 IBM Corp.
|
||||
#
|
||||
@ -38,14 +40,16 @@ class FakeObject(object):
|
||||
self.excluded = excluded
|
||||
self.extra = "extra"
|
||||
|
||||
def __repr__(self):
|
||||
return "<%s: %s>" % (self.__class__.__name__, self.name)
|
||||
def __str__(self):
|
||||
return u"%s: %s" % (self.__class__.__name__, self.name)
|
||||
|
||||
|
||||
TEST_DATA = (
|
||||
FakeObject('1', 'object_1', 'value_1', 'up', 'optional_1', 'excluded_1'),
|
||||
FakeObject('2', 'object_2', '<strong>evil</strong>', 'down', 'optional_2'),
|
||||
FakeObject('3', 'object_3', 'value_3', 'up'),
|
||||
FakeObject('4', u'öbject_4', u'välue_1', u'üp', u'öptional_1',
|
||||
u'exclüded_1'),
|
||||
)
|
||||
|
||||
TEST_DATA_2 = (
|
||||
@ -476,7 +480,8 @@ class DataTableTests(test.TestCase):
|
||||
rows = self.table.get_rows()
|
||||
self.assertQuerysetEqual(rows, ['<MyRow: my_table__row__1>',
|
||||
'<MyRow: my_table__row__2>',
|
||||
'<MyRow: my_table__row__3>'])
|
||||
'<MyRow: my_table__row__3>',
|
||||
'<MyRow: my_table__row__4>'])
|
||||
# Verify each row contains the right cells
|
||||
self.assertQuerysetEqual(rows[0].get_cells(),
|
||||
['<Cell: multi_select, my_table__row__1>',
|
||||
@ -607,8 +612,8 @@ class DataTableTests(test.TestCase):
|
||||
self.assertContains(resp, 'id="my_table__row__2"', 1)
|
||||
self.assertContains(resp, 'id="my_table__row__3"', 1)
|
||||
update_string = "action=row_update&table=my_table&obj_id="
|
||||
self.assertContains(resp, update_string, 3)
|
||||
self.assertContains(resp, "data-update-interval", 3)
|
||||
self.assertContains(resp, update_string, 4)
|
||||
self.assertContains(resp, "data-update-interval", 4)
|
||||
# Verify no table heading
|
||||
self.assertNotContains(resp, "<h3 class='table_title'")
|
||||
# Verify our XSS protection
|
||||
@ -796,7 +801,8 @@ class DataTableTests(test.TestCase):
|
||||
handled = self.table.maybe_handle()
|
||||
self.assertIsNone(handled)
|
||||
self.assertQuerysetEqual(self.table.filtered_data,
|
||||
['<FakeObject: object_2>'])
|
||||
['FakeObject: object_2'],
|
||||
transform=six.text_type)
|
||||
|
||||
# with empty filter string, it should return all data
|
||||
req = self.factory.post('/my_url/', {action_string: ''})
|
||||
@ -804,9 +810,11 @@ class DataTableTests(test.TestCase):
|
||||
handled = self.table.maybe_handle()
|
||||
self.assertIsNone(handled)
|
||||
self.assertQuerysetEqual(self.table.filtered_data,
|
||||
['<FakeObject: object_1>',
|
||||
'<FakeObject: object_2>',
|
||||
'<FakeObject: object_3>'])
|
||||
['FakeObject: object_1',
|
||||
'FakeObject: object_2',
|
||||
'FakeObject: object_3',
|
||||
u'FakeObject: öbject_4'],
|
||||
transform=six.text_type)
|
||||
|
||||
# with unknown value it should return empty list
|
||||
req = self.factory.post('/my_url/', {action_string: 'horizon'})
|
||||
@ -981,7 +989,8 @@ class DataTableTests(test.TestCase):
|
||||
handled = self.table.maybe_handle()
|
||||
self.assertIsNone(handled)
|
||||
self.assertQuerysetEqual(self.table.filtered_data,
|
||||
['<FakeObject: object_2>'])
|
||||
['FakeObject: object_2'],
|
||||
transform=six.text_type)
|
||||
|
||||
# Ensure fitering respects the request method, e.g. no filter here
|
||||
req = self.factory.get('/my_url/', {action_string: '2'})
|
||||
@ -989,9 +998,11 @@ class DataTableTests(test.TestCase):
|
||||
handled = self.table.maybe_handle()
|
||||
self.assertIsNone(handled)
|
||||
self.assertQuerysetEqual(self.table.filtered_data,
|
||||
['<FakeObject: object_1>',
|
||||
'<FakeObject: object_2>',
|
||||
'<FakeObject: object_3>'])
|
||||
['FakeObject: object_1',
|
||||
'FakeObject: object_2',
|
||||
'FakeObject: object_3',
|
||||
u'FakeObject: öbject_4'],
|
||||
transform=six.text_type)
|
||||
|
||||
# Updating and preemptive actions
|
||||
params = {"table": "my_table", "action": "row_update", "obj_id": "1"}
|
||||
@ -1040,7 +1051,8 @@ class DataTableTests(test.TestCase):
|
||||
handled = self.table.maybe_handle()
|
||||
self.assertIsNone(handled)
|
||||
self.assertQuerysetEqual(self.table.filtered_data,
|
||||
['<FakeObject: object_2>'])
|
||||
['FakeObject: object_2'],
|
||||
transform=six.text_type)
|
||||
|
||||
# Ensure API filtering does not filter on server, e.g. no filter here
|
||||
req = self.factory.post('/my_url/')
|
||||
@ -1050,9 +1062,11 @@ class DataTableTests(test.TestCase):
|
||||
handled = self.table.maybe_handle()
|
||||
self.assertIsNone(handled)
|
||||
self.assertQuerysetEqual(self.table.filtered_data,
|
||||
['<FakeObject: object_1>',
|
||||
'<FakeObject: object_2>',
|
||||
'<FakeObject: object_3>'])
|
||||
['FakeObject: object_1',
|
||||
'FakeObject: object_2',
|
||||
'FakeObject: object_3',
|
||||
u'FakeObject: öbject_4'],
|
||||
transform=six.text_type)
|
||||
|
||||
def test_inline_edit_update_action_get_non_ajax(self):
|
||||
# Non ajax inline edit request should return None.
|
||||
@ -1453,9 +1467,11 @@ class DataTableViewTests(test.TestCase):
|
||||
context = view.get_context_data()
|
||||
self.assertEqual(context['table'].__class__, MyServerFilterTable)
|
||||
self.assertQuerysetEqual(data,
|
||||
['<FakeObject: object_1>',
|
||||
'<FakeObject: object_2>',
|
||||
'<FakeObject: object_3>'])
|
||||
['FakeObject: object_1',
|
||||
'FakeObject: object_2',
|
||||
'FakeObject: object_3',
|
||||
u'FakeObject: öbject_4'],
|
||||
transform=six.text_type)
|
||||
self.assertEqual(req.session.get(self.fil_value_param), 'up')
|
||||
self.assertEqual(req.session.get(self.fil_field_param), 'status')
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
# encoding=utf-8
|
||||
#
|
||||
# Copyright 2012 Nebula, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
@ -16,6 +18,8 @@ import copy
|
||||
|
||||
from django import http
|
||||
|
||||
import six
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import tabs as horizon_tabs
|
||||
from horizon.test import helpers as test
|
||||
@ -250,9 +254,12 @@ class TabTests(test.TestCase):
|
||||
# Okay, load the data.
|
||||
tab.load_table_data()
|
||||
self.assertTrue(tab._table_data_loaded)
|
||||
self.assertQuerysetEqual(table.data, ['<FakeObject: object_1>',
|
||||
'<FakeObject: object_2>',
|
||||
'<FakeObject: object_3>'])
|
||||
self.assertQuerysetEqual(table.data,
|
||||
['FakeObject: object_1',
|
||||
'FakeObject: object_2',
|
||||
'FakeObject: object_3',
|
||||
u'FakeObject: öbject_4'],
|
||||
transform=six.text_type)
|
||||
context = tab.get_context_data(self.request)
|
||||
# Make sure our table is loaded into the context correctly
|
||||
self.assertEqual(table, context['my_table_table'])
|
||||
@ -266,7 +273,7 @@ class TabTests(test.TestCase):
|
||||
req = self.factory.get("/")
|
||||
res = view(req)
|
||||
self.assertContains(res, "<table", 1)
|
||||
self.assertContains(res, "Displaying 3 items", 1)
|
||||
self.assertContains(res, "Displaying 4 items", 1)
|
||||
|
||||
# AJAX response to GET for row update
|
||||
params = {"table": "my_table", "action": "row_update", "obj_id": "1"}
|
||||
|
Loading…
Reference in New Issue
Block a user