Package: horizon / 2014.1.3-7+deb8u2

0008_Handle_TypeError_from_table_column_summation_code.patch Patch series | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
Description: Fix summation code to handle invalid input data
 This commit fixes multiple test failures with Django 1.7 that all ended with
 this:
 .
  File "/usr/lib/python2.7/dist-packages/django/template/base.py", line 734, in resolve
    value = self._resolve_lookup(context)
  File "/usr/lib/python2.7/dist-packages/django/template/base.py", line 788, in _resolve_lookup
    current = current()
  File "/home/rhertzog/tmp/django17/horizon/horizon/tables/base.py", line 404, in get_summation
    summation = summation_function(data)
  File "/home/rhertzog/tmp/django17/horizon/horizon/tables/base.py", line 206, in <lambda>
    "average": lambda data: sum(data, 0.0) / len(data)
 TypeError: unsupported operand type(s) for +: 'float' and 'str'
 .
 With Django 1.6, the template code that looked up the variable behind
 get_summation was catching the TypeError exception:
 .
    try: # method call (assuming no args required)
	current = current()
    except TypeError: # arguments *were* required
	# GOTCHA: This will also catch any TypeError
	# raised in the function itself.
	current = settings.TEMPLATE_STRING_IF_INVALID  # invalid method call
 .
 With Django 1.7, the code has been refined to catch the exception only when
 the function really requires argument (which get_summation() doesn't):
 .
    try:  # method call (assuming no args required)
	current = current()
    except TypeError:
	try:
	    getcallargs(current)
	except TypeError:  # arguments *were* required
	    current = settings.TEMPLATE_STRING_IF_INVALID  # invalid method call
	else:
	    raise
 .
 So instead of blindly relying on sum(), I introduced a safe_sum() and safe_average()
 functions which mimick the behaviour we got with Django 1.6 by returning an empty
 string when we have invalid input data.
Author: Raphael Hertzog <hertzog@debian.org>
Date: Mon, 4 Aug 2014 22:27:51 +0200

From d9c8a2e62fbf620eef4d1bdb292cb6ca6b830f17 Mon Sep 17 00:00:00 2001
From: Akihiro Motoki <motoki@da.jp.nec.com>
Date: Wed, 13 Aug 2014 04:05:11 +0900
Subject: [PATCH] Handle TypeError from table column summation code

This commit catches TypeError from horizon.tables.Column
summation calculation. This TypeError is caught inside Django
until Django 1.6, but Django 1.7 code is refined to catch
more specific case and it leads to horizon unit test failure.

Closes-Bug: #1355939
Change-Id: I9d5b4565f1238a9880ccf117f2ea623fed466a44
---
 horizon/tables/base.py       |   14 ++++++++------
 horizon/test/tests/tables.py |    9 +++++++++
 2 files changed, 17 insertions(+), 6 deletions(-)

--- a/horizon/tables/base.py
+++ b/horizon/tables/base.py
@@ -401,12 +401,14 @@ class Column(html.HTMLElement):
         data = filter(lambda datum: datum is not None, data)
 
         if len(data):
-            summation = summation_function(data)
-            for filter_func in self.filters:
-                summation = filter_func(summation)
-            return summation
-        else:
-            return None
+            try:
+                summation = summation_function(data)
+                for filter_func in self.filters:
+                    summation = filter_func(summation)
+                return summation
+            except TypeError:
+                pass
+        return None
 
 
 class Row(html.HTMLElement):
--- a/horizon/test/tests/tables.py
+++ b/horizon/test/tests/tables.py
@@ -999,6 +999,15 @@ class DataTableTests(test.TestCase):
         self.assertNotContains(res, '<td>3.0</td>')
         self.assertNotContains(res, '<td>6</td>')
 
+        # Even if "average" summation method is specified,
+        # we have summation fields but no value is provoded
+        # if the provided data cannot be summed.
+        table = MyTable(self.request, TEST_DATA)
+        res = http.HttpResponse(table.render())
+        self.assertContains(res, '<tr class="summation"')
+        self.assertNotContains(res, '<td>3.0</td>')
+        self.assertNotContains(res, '<td>6</td>')
+
     def test_table_action_attributes(self):
         table = MyTable(self.request, TEST_DATA)
         self.assertTrue(table.has_actions)